在计算着色器中执行N个线程后退出



所以我有一个计算着色器内核与以下逻辑:

[numthreads(64,1,1)] 
void CVProjectOX(uint3 t : SV_DispatchThreadID){ 

if(t.x >= TotalN) 
return; 
uint compt = DbMap[t.x]; 
....

我确实明白,在计算着色器中有ifs/分支是不理想的?如果是这样,如果期望的总线程数与内核的numthreads不完全匹配,那么限制线程工作的最佳方法是什么?

例如,在我的例子中,内核组有64个线程,假设我期望总共961个线程(实际上可以是任何线程),如果我调度960个线程,1个db插槽将不会被处理,如果我调度1024个线程,将有63个不必要的工作或可能指向不存在的db插槽的工作。(db槽号会有变化)

如果(t。x比;TotalN)/返回fine和正确的方法在这里?我应该只写min吗,tx = min(t)x, TotalN)并继续写最后的db槽?我应该取模吗?tx = t.x % TotalN并重写第一个db槽?

还有其他解决方案吗?

以这种方式限制线程数是可以的。但是,请注意,像这样的早期返回实际上并没有像您期望的那样节省(那么多)工作:

硬件利用类似线程集合的SIMD(在directX中称为wavefont)。根据硬件的不同,这种波峰的大小通常是4 (Intel igpu), 32 (NVidia和大多数AMD gpu)或64(少数AMD gpu)。由于SIMD的性质,这样一个波型中的所有线程总是做完全相同的工作,您只能"掩码输出"。他们中的一些(意思是,他们的写将被忽略,他们很好地读取超出边界的内存)。

这意味着,在最坏的情况下(当wavefont大小为64时),当您需要执行961个线程并且因此调度1024个线程时,仍然会有63个线程执行代码,它们的行为就像它们不存在一样。如果波的大小更小,硬件可能至少会提前处理一些波的字体,所以在这些情况下,提前返回确实节省了一些工作。

因此,如果您实际上永远不需要的线程数量不是您的组大小的倍数(反过来,希望是硬件波形大小的倍数),那么这将是最好的。但是,如果这是不可能的,那么以这种方式限制线程的数量是次优选择,特别是因为所有到达早期返回的线程都是彼此相邻的,这最大化了整个波型可以提前退出的机会。

最新更新