2016-09-18 4 views
1

Давайте предположим, что простой if так:предсказания Branch и многопоточность

if (something) 
    // do_something 
else 
    // do_else 

Предположит, что это if-else оператора выполняется параллельно в разных потоках, и каждая нить что дает другой результат, но постоянное через свою собственную жизнь. Например, в потоке 1 условие всегда оценивается как false, в потоке 2 - true; в потоке 3 всегда истинно, и так далее.

Прогнозирование ветвления рассматривает контекст выполнения каждого потока, чтобы сделать его статистику? Потому что, если это не так (я не думаю, что, но его трудно проверить путем тестирования), CPU увидит, что условие следует случайному шаблону и не будет вообще прогнозировать.

+1

Определить нить. CPU, очевидно, не знает о потоках ОС. Но большинство процессоров в эти дни знают об аппаратных потоках. –

+1

Прогнозирование филиала - это деталь реализации процессора, которая работает с разрешением наносекунды. Исполнение потока выполняется с разрешением в миллисекундах. Эти разницы в 6 порядков делают проблему нерелевантной. –

ответ

1

Если мы игнорируем SMT (f.ex. гиперпоточность), то большинство архитектур имеют предиктор ветвления для каждого аппаратного потока. Плотно соединен с блоком извлечения отдельного сердечника. Несколько (AMD?) Хранят информацию о прогнозировании ветвлений в I-кеше L1/L2, но в основном нацелены на следующую выборку.

Итак, если вы не запустите свой код на SMT, вы находитесь на небесах и получите 100% предсказание каждый раз за счет нескольких инструкций.

Если вы запустите свой код на SMT, вы часто обнаружите, что ваша жизнь - это ад, с 50 +% неправильным прогнозом.

Теперь вы можете решить вашу проблему легко, просто вам нужно использовать больше кода, проверить свое состояние раньше и называть ветку своего кода с помощью do_something или do_else.

Если у вас есть цикл, который вызывает вашу функцию, где у вас есть свой филиал вы можете сделать что-то вроде:

если (что-то) do_something_loop(); еще do_else_loop();

void do_something_loop() { для (авто x: myVec) do_something; }

Это имеет тот недостаток, что вам необходимо поддерживать 2 почти равных ветви кода.

Или вы можете иметь свою ветку в вызове функции branch_me(), который вы можете создать функцию шаблона, и из-за магии удаления мертвого кода вы не должны получать никаких ветвей в циклах.

C++ Концептуальный код.

template<bool b_something> 
void brancher() { 
    // do things 
    if (b_something) 
    // do_something 
    else 
    // do_else 
    } 
    // do more things 
} 

void branch_user() { 
    if (something) { 
    for (auto x : myVec) 
     brancher<true>(); 
    } else { 
    for (auto x : myVec) 
     brancher<false>(); 
    } 
} 

Теперь вам нужно поддерживать только две ветви внешней функции, которые, надеюсь, меньше работают.

Смежные вопросы