Популярно рендерить процедурный контент внутри графического процессора, например, на демосцене (рисовать один квад для заполнения экрана и позволить графическому процессору вычислять пиксели).
Лучевой марш популярен:
Это означает, что графический процессор выполняет некоторое неизвестное число итераций цикла на пиксель (хотя вы можете иметь верхнюю границу, например maxIterations
).
Как петля переменной длины влияет на производительность шейдера?
Представьте себе простой маршевый псевдокод:
t = 0.f;
while(t < maxDist) {
p = rayStart + rayDir * t;
d = DistanceFunc(p);
t += d;
if(d < epsilon) {
... emit p
return;
}
}
Как влияют различные семейства графических процессоров (Nvidia, ATI, PowerVR, Mali, Intel и т. Д.)? Вершинные шейдеры, но особенно фрагментные шейдеры?
Как это можно оптимизировать?
opengl
glsl
opengl-es2
raytracing
Будет
источник
источник
Ответы:
На GDC 2012 было приятно поговорить о дистанционном полевом поле GPU (и других темах): http://directtovideo.wordpress.com/2012/03/15/get-my-slides-from-gdc2012/
Что касается производительности, то новейшие видеокарты (класса DX11) выполняют шейдеры на SIMD-блоках, в которых 32 (NVIDIA) или 64 (AMD) «потока» находятся в режиме ожидания. Эти группы по-разному известны как деформации или волновые фронты. Для пиксельных шейдеров каждый поток равен одному пикселю, поэтому я ожидаю, что модуль SIMD обрабатывает что-то вроде блока пикселей 8x4 (NVIDIA) или 8x8 (AMD) вместе. Ветвление и управление потоком выполняются для каждого волнового фронта, поэтому все потоки в волновом фронте должны зацикливаться столько раз, сколько самый глубокий отдельный пиксель в этом волновом фронте. Маски линий SIMD отключат выполнение для уже законченных пикселей, но им все равно придется молча согласиться с управлением потоком всего волнового фронта. Это означает, конечно, что система намного более эффективна, когда ветвление является последовательным,
По моему опыту, издержки ветвления все еще довольно высоки, даже если все потоки в ветви волнового фронта одинаковы. В некоторых случаях я видел прирост производительности при развертывании цикла, чтобы амортизировать некоторые накладные расходы ветви. Однако, конечно, это зависит от того, сколько работы вы выполняете в каждой итерации цикла. Если в теле цикла достаточно «материала», развертывание не будет победой.
источник
Я предлагаю прочитать « Запуск кода на терафлопе: как работают ядра шейдеров GPU» (pdf) из SIGGRAPH 2008: за пределами программируемого шейдинга . Это говорит о динамическом ветвлении.
источник
Что касается динамического ветвления, еще одно замечание (может быть очевидным, но все же стоит обратить внимание на некоторых людей): оно может серьезно повлиять на производительность развернутых циклов (очевидно, что вы не можете развернуть цикл, если существует непостоянное число итераций) ,
источник
int s = 0;
теперь для (int k = 1; k <= n; k ++) {s + = k;} то же самое, что s = n * (n + 1) / 2
так что это не так в целом: D
источник