Enquanto tentava melhorar o desempenho da minha classe de detecção de colisões, descobri que ~ 80% do tempo gasto na gpu passava em condições if / else apenas tentando descobrir os limites dos buckets pelos quais deveria passar.
Mais precisamente:
cada thread obtém um ID, por esse ID ele busca seu triângulo na memória (3 inteiros cada) e pelos 3 busca seus vértices (3 flutua cada).
Em seguida, transforma os vértices em pontos inteiros da grade (atualmente 8x8x8) e os transforma nos limites do triângulo nessa grade
Para transformar os 3 pontos em limites, ele encontra o mínimo / máximo de cada dimensão entre cada um dos pontos
Como a linguagem de programação que estou usando está com falta de um minmax intrínseco, eu mesmo criei uma, assim:
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)
Portanto, em média, deve haver comparações de 2,5 * 3 * 3 = 22,5, o que acaba consumindo muito mais tempo do que os testes reais de interseção da borda do triângulo (cerca de 100 * 11-50 instruções).
De fato, descobri que pré-calcular os buckets necessários na CPU (thread único, sem vetorização), empilhá-los em uma exibição de GPU junto com a definição do bucket e fazer com que a GPU faça ~ 4 leituras extras por thread foi 6 vezes mais rápida do que tentar para descobrir os limites no local. (observe que eles são recalculados antes de cada execução, pois estou lidando com malhas dinâmicas)
Então, por que a comparação é tão terrivelmente lenta em uma gpu?