Я недавно преобразовал ядро OpenCL в CUDA, и запустил nvvp
, и обнаружил следующие две строки кода , которые сильно повлияли на скорость моего кода:
#define FL4(f) make_float4(f,f,f,f)
float4 S = FL4(r->vec.x)*normal[eid]+FL4(r->vec.y)*normal[eid+1]+FL4(r->vec.z)*normal[eid+2];
float4 T = normal[eid+3] - (FL4(r->p0.x)*normal[eid]+FL4(r->p0.y)*normal[eid+1]+FL4(r->p0.z)*normal[eid+2]);
, где каждый normal[i]
является float4
(только для чтения) в глобальной памяти, и, как вы можете видеть, мне нужно прочитать 3x normal
s, чтобы вычислить S
и 4x normal
s (3 из них перекрываются с предыдущей строкой) для вычисления T
. Таким образом, для этих двух строк необходимо всего 64 байта, что делает их ответственными за почти 90% задержки памяти моего кода.
Обновление [18.04.2020]
Чтобы воспроизвести это, можно выполнить следующие простые команды (оптимизация этого кода имеет смысл только с учетом существующей функциональности и сложности программного обеспечения, поэтому я хотел бы исследовать это без децимации ядра)
git clone https://github.com/fangq/mmc_trinity.git
cd mmc_trinity/src
git checkout trinity
make clean
make cuda
cd ../examples/validation
./run_tess.sh -n 1e6 -D T -c cuda -G 1
Чтобы скомпилировать приведенный выше код, вам необходимо предварительно установить cuda (nv cc) в вашей системе. Makefile должен работать на Linux, Ma c и cygwin64 / mys2 на windows. Используйте -G ??
, чтобы выбрать, какой графический процессор использовать, используйте -c cuda -L
, чтобы вывести список всех устройств cuda. Увеличьте 1e6 до 1e7 или 1e8, если у вас есть способный графический процессор.
В настоящее время скорость (-n 1e8
) из вышеприведенного теста с использованием предварительно оптимизированного ядра составляет
22507.31 photon/ms on Titan V
16051.36 photon/ms on RTX 2080
8112.93 photon/ms on GTX 1080Ti
5050.76 photon/ms on GTX 980Ti
Полный Файл ядра (совместимый с opencl / cuda) можно найти по адресу https://github.com/fangq/mmc_trinity/blob/trinity/src/mmc_core.cl
. Две упомянутые мной точки доступа расположены по адресу https://github.com/fangq/mmc_trinity/blob/trinity/src/mmc_core.cl#L526 -L527
Код хоста, связанный с cuda, можно найти по адресу https://github.com/fangq/mmc_trinity/blob/trinity/src/mmc_cu_host.cu
Я хотел бы значительно повысить скорость выполнения, особенно сократить объем памяти, выделяемый горячими точками.
Раньше я думал, что каждое глобальное чтение памяти в CUDA идет с 128-байтовой строкой кэша - так, чтение 1x с плавающей запятой против 4x float4
стоит столько же. Тем не менее, задержка памяти, которую я наблюдал в этих двух строках, значительно выше, чем я ожидаю при чтении одного числа с плавающей запятой.
Ниже приведено значение nvvp
. Я хотел бы услышать, что вы думаете о стратегиях по сокращению стоимости чтения из памяти этих двух строк. Хочу отметить, что в этом коде реализован алгоритм Монте-Карло. из-за случайного характера выполнения слияние потоков очень мало.