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