3 回答
TA贡献1815条经验 获得超6个赞
如果这是您需要使用此数据进行操作的范围(汇总行),那么我预计GPU不会带来可观的收益。每个数据元素只有一个算术运算,为此您要付出将数据元素传输到GPU的费用。除了一定的问题大小(无论机器忙什么),由于算术强度为O(n),因此无法从更大的问题大小中获得更多好处。
因此,这不是在GPU上解决的特别令人兴奋的问题。
但是,正如前言所表明的那样,您在制作工艺上存在一个合并问题,这将进一步降低速度。让我们看一个小例子:
C1 C2 C3 C4
R1 11 12 13 14
R2 21 22 23 24
R3 31 32 33 34
R4 41 42 43 44
上面是矩阵一小部分的简单图示示例。机器数据存储应将元素(11),(12),(13)和(14)存储在相邻的存储位置中。
对于合并访问,我们需要一种访问模式,以便从同一条指令中请求相邻的内存位置,并在扭曲中执行。
我们需要从warp的角度考虑代码的执行,即warp地执行32个线程。您的代码在做什么?在每个步骤/指令中都检索(要求)哪些元素?让我们看一下这行代码:
sum+=m[rowIdx*ncol+k];
rowIdx创建变量时,经线中的相邻线程具有相邻(即连续)的值。因此,当k= 0时,当我们尝试检索值时,每个线程都在请求哪个数据元素m[rowIdx*ncol+k]?
在块0中,线程0的a rowIdx为0。线程1的a rowIdx为1,依此类推。因此,每个线程在此指令中要求的值是:
Thread: Memory Location: Matrix Element:
0 m[0] (11)
1 m[ncol] (21)
2 m[2*ncol] (31)
3 m[3*ncol] (41)
但这不是合并访问!元素(11),(21)等在内存中不相邻。对于合并访问,我们希望“矩阵元素”行的内容如下:
Thread: Memory Location: Matrix Element:
0 m[?] (11)
1 m[?] (12)
2 m[?] (13)
3 m[?] (14)
如果您随后进行反向操作以确定?应该是什么值,那么您将得出如下指示:
sum+=m[k*ncol+rowIdx];
这将提供合并的访问权限,但不会为您提供正确的答案,因为我们现在正在汇总矩阵列而不是矩阵行。我们可以通过将您的数据存储重新组织为列优先顺序而不是行优先顺序来解决此问题。(您应该可以在Google上搜索到它的想法,对吗?)从概念上讲,这等效于转换矩阵m。如我所见,这是否方便您在我的问题范围之外,而实际上不是CUDA问题。在主机上创建矩阵或将矩阵从主机传输到设备时,这可能对您来说很简单。但总而言之,如果矩阵以行优先顺序存储,我不知道用100%合并访问来对矩阵行求和的方法。(您可以采用一系列的行减少操作,但这对我来说很痛苦。)
当我们正在考虑在GPU上加速代码的方式时,考虑重新组织数据存储以方便GPU的情况并不少见。这是一个例子。
而且,是的,我在这里概述的内容仍然在内核中保留了一个循环。
作为补充说明,我建议分别对数据复制部分和内核(计算)部分进行计时。从您的问题中我无法确定您是在计时内核还是整个(GPU)操作,包括数据副本。如果单独对数据复制计时,则可能会发现仅数据复制时间超过了CPU时间。优化CUDA代码所做的任何努力都不会影响数据复制时间。在花费大量时间之前,这可能是有用的数据点。
- 3 回答
- 0 关注
- 583 浏览
添加回答
举报