为什么在开普勒GK107中有更多线程出现更慢的算法?

时间:2014-09-12 11:04:27

标签: c++ cuda

好吧,我有一个GeForce 740m GPU,因此它是GK107架构2xSMX,64 MaxWarps / MP,32线程/ Warp。所以我应该能够一次运行2x64x32 = 4096个线程,对不对?

我在笔记本上运行gSLIC算法(分段到超像素)。

首先,我开始使用尺寸为640x480的图像,然后将图像分割为1200个超像素。在计算之后,内核被调用1200个块和每个块256个线程,结果大约是95ms。

然后我改进了块的大小,但是计算给了我相同数量的块和每个块的线程,1200和256.唯一的区别是,算法在共享内存中分配了额外的不必要的内存,结果是大约200ms。它可能是由于额外的内存分配造成的,还是可能是其他原因?

我想问你一些关于处理这些主题的问题。

  1. 所以我有1200个块和每个块256个线程,这是307200个线程,但是我不能同时运行它们只有4096个,我是对的吗?

  2. 每个mp的最大warp是64,每个warp是32个线程,我的块大小现在是256,所以这意味着一个块就像256/32 = 8个warp,然后在一个SMX上我可以在同一时间运行64/8 = 8个街区,我是对的吗?

  3. CUDA是否开始处理整个块,或者它是否可以从256块的块开始处理32threads?例如,如果我有两个256线程块和8个warp,那么cuda是否可能从两个块中获取128个线程,或者如果可能的话,它将始终首先占用整个块?!

  4. 或者我错误地理解了线程处理。

2 个答案:

答案 0 :(得分:1)

我找到了问题的答案。

问题是共享内存被占用了。 正如我在我的问题中所说,在两种情况下,内核都是以1200个块和每个块256个线程执行的,唯一的区别在于共享内存分配量。

在第一个场景中我将MAX_BLOCK_SIZE设置为256.内核运行1200个块和每个块256个线程,在内核中我分配了两个数组,计算如下9 * 4B * 256 = 9216B = 每块9kB 。共享内存为48kB,这意味着我可以在一个SMX上运行48/9 = 5个块,即5 * 256 = 1280个线程。

在第二种情况下,我将MAX_BLOCK_SIZE设置为1024.内核运行1200个块,每个块运行256个线程(因为图像大小和段数),但在内核中我现在分配了一个更大的数组。 9 * 4B * 1024 = 每块36kB 。在这种情况下,我每个SMX只能运行48/36 = 1个块, 256个线程。

  1. 是的,SMX单元最多可以有64个warp或16个块。由于资源限制(块,扭曲,每个线程的寄存器,每个块的共享内存或障碍),数量可能会更少。

  2. 我不确定,但可能是的,但也许可以从不同的块中选择包装,所以即使在这种情况下,每个SMX甚至可以有16个块。

  3. 也许,就像我在2中写的那样。

答案 1 :(得分:-2)

我不确定你的问题陈述,但通常情况下,当更多线程导致某些事情发生的时间更长时,它可能意味着一些事情:

  • 你有很多线程。只有拥有与可用内核一样多的线程才有好处。
  • 如果您没有太多线程,则意味着您的线程过多地争用数据。

数据争用可能以两种方式发生(可能更多)。

  • 更明显的是,数据正在被共享,并且强制对数据进行互斥访问非常昂贵。
  • 不太明显的是,线程之间共享缓存行,并且缓存行中的数据碰巧彼此靠近。当各种线程修改数据时,必须通知其他线程"由于它们对同一缓存行中的数据感兴趣,因此不必要地对缓存进行了更改。这个问题的解决方案是尝试并本地化一个线程使用的数据,并且只修改"主内存"一旦并行的东西完成了。

线程减慢速度的另一个原因可能是缓存未命中。这意味着数据被缓存,但是当检索时间到来时,数据不再存在(由于其他线程正在使用缓存行)。我们的想法是尝试在同一缓存行中保持一起更改的数据。

这可以通过以下方式完成:

  • 将数据访问模式更改为行访问而不是列 访问,
  • 使用不基于节点的数据结构(因为它们的访问模式未本地化为特定内存。
  • 具有对齐字段/字节的填充。
  • 测试。