【问题标题】:matrix multiplication in cudacuda中的矩阵乘法
【发布时间】:2011-04-21 02:31:56
【问题描述】:

假设我想将两个矩阵相乘,50 乘以 50。我有 2 种方法来排列线程和块。

a) 一个线程来计算结果矩阵的每个元素。所以我在线程中有一个循环乘以一行和一列。

b) 一个线程来做每个乘法。结果矩阵的每个元素需要 50 个线程。乘法完成后,我可以使用二进制归约来对结果求和。

我不知道该走哪条路,所以我选择了b。这并不理想。事实上它很慢。知道为什么吗?我的猜测是线程太多了,而且它们大部分时间都在等待资源,这是真的吗?

【问题讨论】:

    标签: cuda


    【解决方案1】:

    与高性能计算中的许多事情一样,这里理解性能的关键是理解内存的使用。

    如果您使用一个线程做一次乘法,那么对于该线程,您必须从内存中提取两条数据,将它们相乘,然后进行一些对数相加。这是一个 mult 和一个 add 和一个位的三个内存访问 - 算术强度非常低。好消息是这种方式有很多线程值得任务,每个只需要一点点内存/寄存器,这对占用有好处;但是内存访问工作比很差。

    简单的一个线程做一个点积的方法也有同样的问题——每次乘法都需要两次内存访问才能加载。好消息是整个点积只有一个存储到全局内存中,并且您避免了无法扩展且需要大量同步的二进制归约;不利的一面是现在线程更少了,至少您的 (b) 方法对您有用。

    现在您知道应该有某种方法可以在每次内存访问时执行比这更多的操作;对于平方 NxN 矩阵,有 N^3 工作来进行乘法运算,但只有 3xN^2 个元素 - 因此您应该能够找到一种方法,每次 2ish 内存访问进行超过 1 次计算。

    在 CUDA SDK 中采用的方法是最好的方法 - 矩阵被分成小块,并且您的 (b) 方法 - 每个输出元素一个线程 - 被使用。但关键在于线程的排列方式。通过将整个小子矩阵从慢速全局内存中拉入共享内存,并从那里进行计算,可以对从内存中读入的每个数字进行多次乘法和加法。这种方法在许多应用程序中是最成功的方法,因为获取数据——无论是通过网络,还是从 CPU 的主存储器,或 GPU 的片外访问——通常比处理数据需要更长的时间。

    在 NVidia 的 CUDA 页面(尤其是 http://developer.nvidia.com/object/cuda_training.html)中有文档很好地描述了他们的 SDK 示例。

    【讨论】:

      【解决方案2】:

      您是否查看过 CUDA 文档:Cuda Programming Model

      另外,示例源代码:Matrix Multiplication

      【讨论】:

        【解决方案3】:

        你看了吗

        $SDK/nvidia-gpu-sdk-3.1/C/src/matrixMul
        

        即SDK中的矩阵乘法示例?

        【讨论】:

          【解决方案4】:

          如果您不需要自己实现,只需使用库——CUBLAS、MAGMA 等,提供调整后的矩阵乘法实现。

          【讨论】:

            猜你喜欢
            • 2012-05-06
            • 2011-09-07
            • 2012-12-09
            • 1970-01-01
            • 2013-04-16
            • 2011-05-02
            • 2012-02-07
            • 2012-12-13
            相关资源
            最近更新 更多