为什么在GPU上进行比较如此昂贵?


10

在尝试提高碰撞检测类的性能时,我发现在gpu上花费了大约80%的时间,它花费在if / else条件上只是试图弄清楚应该循环通过的存储桶的界限。

更确切地说:

  1. 每个线程都有一个ID,通过该ID从内存中获取其三角形(每个3个整数),并通过这3个线程获取其顶点(每个3个浮点)。

  2. 然后将顶点转换为整数网格点(当前为8x8x8),并将其转换为该网格上的三角形边界

  3. 要将3个点转换为边界,它会在每个点中找到每个维度的最小值/最大值

由于我使用的编程语言缺少minmax内在函数,因此我自己做了一个代码,看起来像这样:

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条指令)消耗的时间更多。

实际上,我发现在cpu上预先计算所需的存储桶(单线程,无向量化),将它们与gpu定义一起存储在gpu视图中,并使gpu每个线程进行约4次额外读取,比尝试快6倍。找出当场的界限。(请注意,由于我要处理动态网格物体,因此在每次执行之前都要重新计算它们)

那么,为什么在GPU上进行比较却如此缓慢呢?


2
您的问题是关于特定类型的硬件上特定代码段的指令级性能。在我看来,这听起来更像是编程问题,而不是计算机科学问题。
David Richerby,2015年

7
我的猜测是,比较不是昂贵的而是分支。如果编译器不使用谓词(或GPU不提供谓词),则将使用导致“线程”派生的分支(因为GPU是面向SIMD的)。将条件转换为遮罩并使用遮罩合成条件移动/掉期可能是一个合理的选择。
保罗·克莱顿

1
@DavidRicherby我不确定这是否具体。这个问题不适用于任何SIMD架构吗?
kasperd 2015年

1
@DavidRicherby:之所以在CS部门教授comp arch是因为comp arch对您选择的算法有影响。仅当您知道如何编写无嵌套分支的程序时,SIMD架构才能产生高吞吐量。
2015年

2
由于Wandering Logic给出的答案不太明显,GPU通过假设许多“线程”同时处于同一条指令中来工作。因此,从广义上讲,GPU占据了每个分支,而不仅仅是真正的分支。这就是为什么GPU利用邻居通常采用相同分支的事实。如果不是这样,性能会很糟糕。
罗布

Answers:


10

GPU是SIMD架构。在SIMD架构中,需要为您处理的每个元素执行每条指令。(此规则有一个例外,但很少有帮助)。

因此,在您的MinMax例程中,不仅每个调用都需要获取所有三个分支指令(即使平均只评估了2.5条指令),而且每个赋值语句也占用一个周期(即使实际上并未“执行”) )。

该问题有时称为线程发散。如果您的计算机具有32条SIMD执行通道,则它仍将只有一个获取单元。(这里的“线程”基本上是指“ SIMD执行通道”。)因此,内部每个SIMD执行通道都有一个“启用/禁用”位,而分支实际上只是在操纵该位。(例外是,在每个SIMD通道都被禁用的那一刻,提取单元通常将直接跳转到“ else”子句。)

因此,在您的代码中,每个SIMD执行通道都在执行以下操作:

compare (a > b)
assign (max = a if a>b)
assign (min = b if a>b)
assign (max = b if not(a>b))
assign (min = a if not(a>b))
compare (c > max)
assign (max = c if c>max)
compare (c < min if not(c>max))
assign (min = c if not(c>max) and c<min)

在某些GPU上,如果GPU自己执行,则条件到谓词的转换可能会变慢。正如@ PaulA.Clayton指出的那样,如果您的编程语言和体系结构具有谓词条件移动操作(尤其是形式之一if (c) x = y else x = z),则您可能会做得更好。(但可能不会好得多)。

此外,将所述c < min的条件内elsec > max是不必要的。当然,这并不能为您节省任何费用,并且(考虑到GPU必须将其自动转换为谓词)将其嵌套在两个不同的条件中实际上可能会很有害。


2
(对不起,如果其中任何部分不清楚,我将在理论家将问题作为主题关闭之前尝试获得答案。)
Wandering Logic

欲了解更多基础知识,请访问:http : //developer.nvidia.com/GPUGems2/gpugems2_chapter34.html以及更多最新的解决方法:eecis.udel.edu/~cavazos/cisc879/papers/a3-han.pdf
Fizz,

从某些意义上说,某些算法无法通过SIMD并行性加速,这是一个话题。(即:工作,跨度等,以便从理论上更深入地了解原因)
Rob

1
这是关于差异基础的另一篇演讲者。maths.ox.ac.uk/ gilesm / cuda / lecs / lec3-2x2.pdf从中注意到,这个问题(无论如何在Nvidia上)仅是逐个问题。在不同的线程束上运行的代码可能会愉快地发生分歧。另一篇论文提出了一种避免这种情况的方法:hal.inria.fr/file/index/docid/649650/filename/sbiswi.pdf
Fizz,

略有不同,但与我在问题eprint.iacr.org/2012/137.pdf下写的评论一致,值得阅读:对于GPU,与预期性能相比,减速10倍可能是“正常的”,除非您停下来组装(通常使用官方不支持的工具)。以GPU为目标的编译器可能会变得更好,但我不会屏住呼吸。
Fizz
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.