OpenCL矩阵乘法:内积与外积

时间:2014-06-25 23:33:18

标签: opencl matrix-multiplication

我希望每个人都熟悉将两个(n x n平方为简单)矩阵相乘的标准“天真”方法。在C中,这是:

for(int i = 0; i < n; ++i)
    for(int j = 0; j < n; ++j)
        for(int k = 0; k < n; ++k)
            C[i*n + j] += A[i*n + k] * B[k*n + j];

上述方法计算A行的一个点(内部)乘积,其列为B,并且易于在OpenCL中实现,如下所示:

__kernel void matmul_ocl(
                        __global const float *A,
                        __global const float *B,
                        __global       float *C,
                                 const int n
                        )
{
    const int row = get_global_id(1); // row
    const int col = get_global_id(0); // col

    for(int i = 0; i < n; i++)
        C[row*n + col] += A[row*n + i]*B[i*n + col];
}

交换原始C实现的两个最内层循环会产生一个计算外部产品的方法,即它计算{{行}的排名-1更新1}}矩阵:

C

有人知道如何在OpenCL中正确实现上述外部产品方法吗?我在下面粘贴了两次尝试,但我似乎无法指出它

尝试1

for(int i = 0; i < n; ++i)
    for(int k = 0; k < n; ++k)
        for(int j = 0; j < n; ++j)
            C[i*n + j] += A[i*n + k] * B[k*n + j];

尝试2

__kernel void matmul_ocl(
                        __global const float *A,
                        __global const float *B,
                        __global       float *C,
                                 const int n
                        )
{
    const int row = get_global_id(1); // row
    const int col = get_global_id(0); // col

    __local float r;

    r = A[row*n + col];
    barrier(CLK_LOCAL_MEM_FENCE);

    for(int i = 0; i < n; ++i)
        C[row*n + i] += r * B[col*n + i];

}

1 个答案:

答案 0 :(得分:1)

通用算法的OpenCL实现将外部两个循环映射到OpenCL NDRange隐式循环。这是有效的,因为外部的两个循环可以安全地并行运行。

尝试1有一些问题:

  • __local变量r同时分配来自多个工作项的不同值。这里存在竞争条件,r的值未定义。这可以通过将r改为私有变量来解决。
  • 更严重的问题是在C的赋值中存在竞争条件.col的每个值(NDRange维度0)将并行地在i上运行它自己的循环。

围绕第二个问题没有一个简单的方法。 k上的循环(在转置版本中)不能并行运行。您只能将外循环或内循环映射到OpenCL中的单维NDRange。