Пытаясь улучшить производительность моего класса обнаружения столкновений, я обнаружил, что ~ 80% времени, проведенного в графическом процессоре, тратится на условия if / else, просто пытающиеся определить границы для сегментов, через которые он должен проходить.
Точнее:
каждый поток получает идентификатор, по этому идентификатору он выбирает свой треугольник из памяти (по 3 целых числа каждый), а по этим 3 он выбирает свои вершины (по 3 числа с плавающей точкой).
Затем он преобразует вершины в целочисленные точки сетки (в настоящее время 8x8x8) и преобразует их в границы треугольника на этой сетке.
Чтобы преобразовать 3 точки в границы, он находит мин / макс каждого измерения среди каждой из точек
Поскольку в используемом мной языке программирования отсутствует внутреннее минимальное значение, я сделал его сам, выглядит так:
procedure MinMax(a, b, c):
local min, max
if a > b:
max = a
min = b
else:
max = b
min = a
if c > max:
max = c
else:
if c < min:
min = c
return (min, max)
Таким образом, в среднем это должно быть 2,5 * 3 * 3 = 22,5 сравнения, которые заканчиваются тем, что потребляют намного больше времени, чем фактические тесты пересечения треугольника и края (около 100 * 11-50 инструкций).
На самом деле, я обнаружил, что предварительный расчет требуемых сегментов в процессоре (однопоточный, без векторизации), размещение их в представлении gpu вместе с определением сегментов и заставление gpu делать ~ 4 дополнительных чтения на поток выполнялся в 6 раз быстрее, чем попытки выяснить границы на месте. (обратите внимание, что они пересчитываются перед каждым выполнением, так как я имею дело с динамическими сетками)
Так почему сравнение так ужасно медленно на GPU?