CUDA - 对矩阵的单个元素的操作 - 获得想法

时间:2011-04-04 13:30:53

标签: c++ matrix cuda

我是在编写一个CUDA内核,对矩阵的每个元素执行单个操作(例如,对每个元素进行平方根,或取幂,或者如果所有数字都在[-1; 1]之间,则计算正弦/余弦等等。)

我选择了块/线程网格尺寸,我认为代码非常简单明了,但我问自己......我能做些什么来最大化合并/ SM占用?

我的第一个想法是:让所有半整数(16个线程)从全局内存加载数据集合,然后将它们全部计算,但它发现没有足够的内存传输/计算并行化。我的意思是所有线程加载数据,然后计算,然后重新加载数据,然后再次计算......这听起来在性能方面确实很差。

我认为使用共享内存会很棒,也许使用某种局部性来使线程加载的数据超过实际需要的其他线程的工作量,但这听起来也很愚蠢,因为第二个会等待前者在开始工作之前完成加载数据。

我不确定我是否对我的问题提出了正确的想法,我只是在开始研究具体事情之前得到了想法。

每个评论/建议/评论都被广泛接受,谢谢。

3 个答案:

答案 0 :(得分:1)

在我看来,你的问题是这个

load data ensemble from global memory

您的算法想法似乎是:

  1. 在cpu上做点什么 - 有一些矩阵
  2. 将矩阵从全局传输到设备内存
  3. 对每个元素执行操作
  4. 将矩阵从设备传输回全局存储器
  5. 在cpu上做一些其他事情 - 有时回到1。
  6. 这种计算几乎每次I / O带宽有限(IO =内存IO),而不是计算能力有限。 GPGPU计算可以维持非常高的内存带宽 - 但仅从设备内存到gpu - 从全局内存传输始终通过非常慢的PCIe(与设备内存连接相比,可以提供高达160 GB / s +的速度)快卡)。因此,获得良好结果的一个主要方面是将数据(矩阵)保存在设备内存中 - 如果可能,最好生成它(取决于您的问题)。永远不要尝试在cpu和gpu之间迁移数据,因为传输开销会占用你所有的加速。还要记住,你的矩阵必须有一定的大小来分摊转移开销,你不能避免(计算一个10 x 10元素的矩阵几乎不会带来什么,哎它甚至会花费更多)

    交换传输/计算/传输完全正常,这就是这种gpu算法的工作方式 - 但前提是传输是来自设备内存。

答案 1 :(得分:1)

如果您已经定义了网格,以便线程沿着包含矩阵的数组的主要维度读取,那么您已经保证了合并的内存访问,并且几乎没有其他工作可以提高性能。这些O(N)复杂度操作实际上不包含足够的算术强度,以便在优化的CPU实现上提供良好的并行加速。通常,最好的策略是将多个O(N)操作融合到一个内核中,以提高FLOP到内存的事务比率。

答案 2 :(得分:0)

对于这个微不足道的东西来说,GPU太过分了,并且比将它保留在CPU上更慢。特别是如果你有一个多核CPU。

我已经看到很多项目显示了GPU在CPU上的“巨大”优势。他们很少经受审查。当然,想要给经理留下深刻印象的傻瓜经理想要展示他的团队是如何“领先”的。

该部门有人花了好几个月的时间来优化愚蠢的GPU代码(通常比同等的CPU代码读取难度高8倍),然后有一些印度汗水商店编写的“等效”CPU代码(程序员的最后一个项目是PGP),用他们可以找到的最慢版本的gcc编译它,没有优化,然后宣传他们的2倍速度提升。而顺便说一下,很多人都忽略了I / O的速度,因为它们并不重要。