Ответ 1
Предикация команды означает, что команда условно выполняется потоком в зависимости от предиката. Темы, для которых предикат является истинным, выполняют инструкцию, остальные ничего не делают.
Например:
var = 0;
// Not taken by all threads
if (condition) {
var = 1;
} else {
var = 2;
}
output = var;
Результат (не фактический вывод компилятора):
mov.s32 var, 0; // Executed by all threads.
setp pred, condition; // Executed by all threads, sets predicate.
@pred mov.s32 var, 1; // Executed only by threads where pred is true.
@!pred mov.s32 var, 2; // Executed only by threads where pred is false.
mov.s32 output, var; // Executed by all threads.
В целом, это 3 инструкции для if
, без ветвления. Очень эффективен.
Эквивалентный код с ветвями будет выглядеть так:
mov.s32 var, 0; // Executed by all threads.
setp pred, condition; // Executed by all threads, sets predicate.
@!pred bra IF_FALSE; // Conditional branches are predicated instructions.
IF_TRUE: // Label for clarity, not actually used.
mov.s32 var, 1;
bra IF_END;
IF_FALSE:
mov.s32 var, 2;
IF_END:
mov.s32 output, var;
Обратите внимание на то, что дольше это (5 инструкций для if
). Для условной ветки требуется отключение части основы, выполнение первого пути, затем возврат к точке, где деформация расходится и выполняется второй путь, пока оба не сходятся. Это занимает больше времени, требует дополнительной бухгалтерии, дополнительной загрузки кода (особенно в случае, когда есть много инструкций для выполнения) и, следовательно, больше запросов на память. Все, что делает ветвление медленнее, чем простое предикатирование.
И в самом деле, в случае этого очень простого условного присваивания, компилятор может сделать еще лучше, всего лишь 2 инструкции для if
:
mov.s32 var, 0; // Executed by all threads.
setp pred, condition; // Executed by all threads, sets predicate.
selp var, 1, 2, pred; // Sets var depending on predicate (true: 1, false: 2).