可变矩阵大小的CUDA中的矩阵乘法和共享内存的使用

时间:2016-11-15 19:05:42

标签: c++ matrix cuda shared-memory

我想在CUDA中实现一个简单的矩阵乘法。矩阵的维度在运行时确定,我也想使用共享内存以获得性能提升。我已经实现了这样的功能,但每次运行它时,我都会收到此错误:

mulKernel launch failed: an illegal memory access was encountered

我也不确定是否可以使用malloc来分配共享内存。但是,如果我想使用这样的东西

__shared__ float matrM_sm[tile_width][tile_width];

编译器抱怨必须在运行时知道tile_width ...

我已经尝试了所有我能想到的东西,并尝试了各种建议,但没有一个有效。这是函数(可以找到完整的工作文件HERE):

__global__ void mulKernelSM(float *matrR, const float *matrM, const float *matrN,
   const int m_x, const int m_y, const int n_x, const int n_y, const int tile_width)
{
    int i, j;
    extern __shared__ float shared[];
    float *matrM_sm = shared;
    float *matrN_sm = &shared[tile_width * tile_width];

    int bx = blockIdx.x;
    int by = blockIdx.y;
    int tx = threadIdx.x;
    int ty = threadIdx.y;

    int row = by * tile_width + ty;
    int col = bx * tile_width + tx;

    float tmp;
    int limit = ceil(m_y / (float) tile_width);
    for (i = 0; i < limit; i++)
    {
        tmp = 0.0;

        if (i * tile_width + tx < m_y && row < m_x)
            matrM_sm[ty * tile_width + tx] = matrM[row * m_y + (i * tile_width + tx)];
        else
            matrM_sm[ty * tile_width + tx] = 0.0;

        if (i * tile_width + ty < n_x && col < n_y)
            matrN_sm[ty * tile_width + tx] = matrN[col + (i * tile_width + ty) * n_y];
        else
            matrN_sm[ty * tile_width + tx] = 0.0;

        __syncthreads();

        for (j = 0; j < tile_width; j++)
            tmp += matrM_sm[ty * tile_width + j] * matrN_sm[j * tile_width + tx];

        __syncthreads();
    }

    if (row < m_x && col < n_y)
        matrR[row * n_y + col] = tmp;
}

基本布局应该工作,因为我还实现了没有共享内存的版本,工作得很好。下面列出了没有共享内存的功能:

__global__ void mulKernel(float *matrR, const float *matrM, const float *matrN,
    const int m_x, const int m_y, const int n_x, const int n_y)
{
    int row = blockIdx.y * blockDim.y + threadIdx.y;
    int col = blockIdx.x * blockDim.x + threadIdx.x;
    int i;

    if ((row < m_x) && (col < n_y))
    {
        float tmp = 0.0;
        for (i = 0; i < m_y; i++)
        {
            tmp += matrM[row * m_y + i] * matrN[col + n_y * i];
        }

        matrR[row * n_y + col] = tmp;
    }
}

如果缺少任何信息,我会立即提供。

1 个答案:

答案 0 :(得分:-1)

您换了row, col。此外,我相信要获取全局线程索引,您应该执行此操作int x_global = threadIdx.x + blockDim.x * threadIdx.y