CUDA: почему побитовые операторы иногда быстрее логических операторов?

когда я собираюсь выжать последний бит производительности из ядра, я обычно нахожу, что замена логические операторы (&& и ||) С побитовые операторы (& и |) делает ядро немного быстрее. Это было замечено, посмотрев на сводку времени ядра в CUDA Visual Profiler.

Итак, почему побитовые операторы быстрее чем логические операторы в CUDA? Я должен признать, что они не всегда быстрее, но много раз они. Интересно, какая магия может ускорить это.

отказ от ответственности: я знаю, что логические операторы короткого замыкания и побитовые операторы не. Я хорошо знаю как эти операторы могут быть использованы в результате неправильного кода. Я использую эту замену с осторожностью только тогда, когда результирующая логика остается той же, есть ускорение, и ускорение, полученное таким образом, имеет значение для меня :-)

3 ответов


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


A & & B:

if (!A) {
  return 0;
}
if (!B) {
  return 0;
}
return 1;

A & B:

return A & B;

это семантика, учитывая, что оценка A и B может иметь побочные эффекты (они могут быть функциями, которые изменяют состояние системы при оценке).

есть много способов, которыми компилятор может оптимизировать A && B case, в зависимости от типов A и B и контекста.


побитовые операции могут выполняться в регистрах на аппаратном уровне. Операции регистра являются самыми быстрыми, это особенно верно, когда данные могут поместиться в регистре. Логические операции включают оценку выражений, которые не могут быть привязаны к регистру. Как правило,&,|, ^, >>... некоторые из самых быстрых деятельностей и использованный широко в логике высокой эффективности.