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

C++ CUDA中可变矩阵大小的矩阵乘法和共享内存的使用,c++,matrix,cuda,gpu-shared-memory,C++,Matrix,Cuda,Gpu Shared Memory,我想在CUDA中实现一个简单的矩阵乘法。矩阵的维数是在运行时确定的,我还想使用共享内存来提高性能。我已经实现了这样一个函数,但每次运行它时,都会出现以下错误: mulKernel launch failed: an illegal memory access was encountered 我也不确定是否可以使用malloc来分配共享内存。但是,如果我想用这样的东西 __shared__ float matrM_sm[tile_width][tile_width]; 编译器抱怨在运行时必须知

我想在CUDA中实现一个简单的矩阵乘法。矩阵的维数是在运行时确定的,我还想使用共享内存来提高性能。我已经实现了这样一个函数,但每次运行它时,都会出现以下错误:

mulKernel launch failed: an illegal memory access was encountered
我也不确定是否可以使用malloc来分配共享内存。但是,如果我想用这样的东西

__shared__ float matrM_sm[tile_width][tile_width];
编译器抱怨在运行时必须知道平铺宽度

我尝试了我能想到的一切,也尝试了各种各样的建议,但都没有奏效。这是函数(可以找到完整的工作文件):

\uuuuu全局\uuuuu无效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;
外部共享浮点共享[];
float*matrM_sm=共享;
float*matrN\u sm=&shared[tile\u width*tile\u width];
int bx=blockIdx.x;
int by=blockIdx.y;
int tx=线程idx.x;
int ty=threadIdx.y;
int row=按*平铺宽度+ty;
int col=bx*瓷砖宽度+tx;
浮动tmp;
int limit=天花板(m_y/(浮动)瓷砖宽度);
对于(i=0;i
基本布局应该可以工作,因为我还实现了一个没有共享内存的版本,它工作得很好。没有共享内存的功能如下所示:

__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;
    }
}
\uuuu全局\uuuuu无效多内核(float*matrR、const float*matrM、const float*matrN、,
常量int m_x,常量int m_y,常量int n_x,常量int n_y)
{
int row=blockIdx.y*blockDim.y+threadIdx.y;
int col=blockIdx.x*blockDim.x+threadIdx.x;
int i;
如果((行

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

您交换了
行,列
。此外,,我认为要获得全局线程索引,您应该这样做
int x_global=threadIdx.x+blockDim.x*threadIdx.y

切换列和行会导致相同的错误,并且平铺宽度与blockDim.x和blockDim.ydoes
平铺宽度
匹配
blockIdx.x
blockIdx.y
不,但事实并非如此,因为每次运行时,平铺宽度始终相同,但每个运行时不同,而blockIdx.x不同。您不能使用malloc分配共享内存。《编程指南》讨论了共享内存分配,这里有许多CUDA示例代码和问题,以涵盖正确的共享内存使用。如果您想要一个运行时可分配的共享内存大小,您可以使用带有
extern
的动态共享内存分配方法,并提供共享内存大小作为内核启动参数。如果您需要调试代码的帮助,您应该提供一个。CUDA内核本身不是MCVE。谢谢您的建议。我将共享内存分配与extern集成,并更新了问题,因此新代码是最新的。我还添加了一个指向整个代码的链接,它代表了一个完整的工作示例。它位于函数开始之前的开始处。在内核调用中指定共享内存大小的参数必须以字节为单位指定。这至少是“遇到非法内存访问”错误的一个原因。修复此问题,并使用
cuda memcheck
运行代码。如果仍然报告错误,请使用描述的方法帮助将错误定位到特定的内核行。如果您需要更多信息,请使用
printf
或其他调试方法。我知道,我保留了一些内存,但忘了将其与浮点大小相乘。现在它可以正常工作了,尽管计算还不正确。关于memcheck,我已经读过好几次了,但我不知道如何在windows上的Visual Studio中使用它。我在我的电脑上找不到它的选项,也找不到可执行文件。根据手册,两者都应该是可能的,但我无法遵循其中任何一个说明…我进一步将pastebin中的代码更新到当前步骤。如果你们现在能帮我找出计算中的错误,我将非常高兴。顺便说一句,如果你对答案发表评论,罗伯特·克罗维拉,我会接受并投票,因为这解决了我最初的问题(尽管不幸的是,不是所有问题)
__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;
    }
}