Стоит ли объединять два одинаковых ядра с помощью оператора if, что может привести к потере производительности? - PullRequest
34 голосов
/ 30 мая 2011

У меня есть 2 очень похожие функции ядра, в том смысле, что код почти такой же, но с небольшой разницей. На данный момент у меня есть 2 варианта:

  • Напишите 2 разных метода (но очень похожих)
  • Напишите одно ядро ​​и поместите блоки кода, которые отличаются в операторе if / else

Насколько выражение if повлияет на производительность моего алгоритма?
Я знаю, что ветвления нет, поскольку все потоки во всех блоках будут вводить либо if, либо else.
Так уменьшит ли один оператор if мою производительность, если функция ядра будет вызываться много раз?

Ответы [ 2 ]

94 голосов
/ 30 мая 2011

У вас есть третий вариант, который заключается в использовании шаблонов C ++ и превращении переменной, используемой в операторе if / switch, в параметр шаблона.Создайте каждую версию ядра, в которой вы нуждаетесь, и тогда у вас есть несколько ядер, которые делают разные вещи, без расхождений в ветвях или условной оценки, потому что компилятор будет оптимизировать мертвый код и ветвления с ним.

Возможно, что-то вроде этого:

template<int action>
__global__ void kernel()
{
    switch(action) {
       case 1:
       // First code
       break;

       case 2:
       // Second code
       break;
    }
}

template void kernel<1>();
template void kernel<2>();
4 голосов
/ 31 мая 2011

Это немного снизит вашу производительность, особенно если это происходит во внутреннем цикле, так как вы тратите время на прохождение инструкций, но это не так сильно, как если бы деформация была расходящейся.

Если это большое дело, возможно, стоит переместить условие за пределы цикла. Если деформация действительно расходится, подумайте о том, как удалить разветвление: например, вместо

if (i>0) {
    x = 3;
} else {
    x = y;
}

попробовать

x = ((i>0)*3) | ((i<3)*y);
...