Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 矩阵相乘在CUDA上给出错误的结果_C++_Cuda - Fatal编程技术网

C++ 矩阵相乘在CUDA上给出错误的结果

C++ 矩阵相乘在CUDA上给出错误的结果,c++,cuda,C++,Cuda,我已经用CUDA写了一小段代码来乘2个方阵。Hovewer,事实证明大部分细胞都计算错了。根据我使用的教程,一切都会很顺利 __global__ void gpuMM(int *C, int *A, int *B, int N) { int row = blockIdx.x*blockDim.x + threadIdx.x; int col = blockIdx.y*blockDim.y + threadIdx.y; int sum = 0; for (int n

我已经用CUDA写了一小段代码来乘2个方阵。Hovewer,事实证明大部分细胞都计算错了。根据我使用的教程,一切都会很顺利

__global__ void gpuMM(int *C, int *A, int *B, int N)
{
    int row = blockIdx.x*blockDim.x + threadIdx.x;
    int col = blockIdx.y*blockDim.y + threadIdx.y;
    int sum = 0;
    for (int n = 0; n < N; ++n)
        sum += A[row*N+n]*B[n*N+col];

    C[row*N+col] = sum;
}

#define ROW_SIZE 5
#define MATRIX_LENGTH ROW_SIZE*ROW_SIZE
#define BLOCK_SIZE 16

void MultiplyMatrixCUDA(int * pResult, int* pFactorA, int*pFactorB)
{
    int size = MATRIX_LENGTH*sizeof(int);
    int *dA,*dB,*dC;
    cudaMalloc(&dA,size);
    cudaMalloc(&dB,size);
    cudaMalloc(&dC,size);
    int K = 100;
    dim3 threadBlock(BLOCK_SIZE,BLOCK_SIZE);
    dim3 grid(K,K);

    printf("A:\n");
    DrawMatrix(pFactorA);
    printf("\n");

    printf("B:\n");
    DrawMatrix(pFactorB);
    printf("\n");

    // Copy matrices from the host to device
    cudaMemcpy(dA,pFactorA,size,cudaMemcpyHostToDevice);
    cudaMemcpy(dB,pFactorB,size,cudaMemcpyHostToDevice);

    //Execute the matrix multiplication kernel
    gpuMM<<<grid,threadBlock>>>(dC,dA,dB,ROW_SIZE);


    // Allocate memory to store the GPU answer on the host
    int *C;
    C = new int[MATRIX_LENGTH];

    // Now copy the GPU result back to CPU
    cudaMemcpy(C,dC,size,cudaMemcpyDeviceToHost);

    cudaFree(dA);
    cudaFree(dB);
    cudaFree(dC);

    printf("\nC from CUDA:\n");
    DrawMatrix(C);
    printf("\nC:\n");
    DrawMatrix(MultiplyWithCPU(pResult,pFactorA, pFactorB));  // the code of multiplying function is irrevelant, I'm sure it works fine (double-checked)

}
\uuuu全局\uuuuu无效gpuMM(int*C,int*A,int*B,int-N)
{
int row=blockIdx.x*blockDim.x+threadIdx.x;
int col=blockIdx.y*blockDim.y+threadIdx.y;
整数和=0;
对于(int n=0;n
结果表明,用标准CPU方法乘以矩阵是正确的,但CUDA方法是错误的:

第一行总是正确的,但所有其他部分都是完全随机的。有时是消极的,有时不是。有时它们接近真实值,有时它们完全不同

我犯了什么错?我不知道失败在哪里。算法看起来很好,变量似乎传递正确,但有些东西不起作用

---编辑


所有变量(PRESLT和两个PFactor)都在代码的其他部分初始化(稍后删除)。

因为每个块的线程数不等于输出矩阵中的元素数(您正在映射16x16块上的5x5矩阵),所以一些线程正在访问/写入无效的内存位置

解决方案包括双重边界检查,以解决问题。这将导致某些线程处于空闲状态。内核应该如下所示:

__global__ void gpuMM(int *C, int *A, int *B, int N)
{
    int row = blockIdx.x*blockDim.x + threadIdx.x;
    int col = blockIdx.y*blockDim.y + threadIdx.y;

    if( (row < N) && (col < N))
    {
        int sum = 0;
        for (int n = 0; n < N; ++n){
            sum += A[row*N+n]*B[n*N+col];       
        }
        C[row*N+col] = sum;
    }
}
\uuuu全局\uuuuu无效gpuMM(int*C,int*A,int*B,int-N)
{
int row=blockIdx.x*blockDim.x+threadIdx.x;
int col=blockIdx.y*blockDim.y+threadIdx.y;
如果((行

另一个解决方案——更有效,取决于你的设备——是每个块启动更少的线程(本例中为25个)

由于每个块的线程数不等于输出矩阵中的元素数(您正在16x16块上映射5x5矩阵),因此某些线程正在访问/写入无效的内存位置

解决方案包括双重边界检查,以解决问题。这将导致某些线程处于空闲状态。内核应该如下所示:

__global__ void gpuMM(int *C, int *A, int *B, int N)
{
    int row = blockIdx.x*blockDim.x + threadIdx.x;
    int col = blockIdx.y*blockDim.y + threadIdx.y;

    if( (row < N) && (col < N))
    {
        int sum = 0;
        for (int n = 0; n < N; ++n){
            sum += A[row*N+n]*B[n*N+col];       
        }
        C[row*N+col] = sum;
    }
}
\uuuu全局\uuuuu无效gpuMM(int*C,int*A,int*B,int-N)
{
int row=blockIdx.x*blockDim.x+threadIdx.x;
int col=blockIdx.y*blockDim.y+threadIdx.y;
如果((行

另一个解决方案——更有效,取决于你的设备——是每个块启动更少的线程(本例中为25个)

preslt
在哪里初始化?@PaulMcKenzie在我调用
main()
中的
multipleMatrixCuda
之前,它们已初始化。我已编辑了我的问题。您正在处理5x5矩阵,但块大小为16x16。这意味着,除了一个线程试图处理非常真实的(行,列)=(1,0)之外,还有一个线程试图处理不存在的(行,列)=(0,5)-但是这两个项目重叠(0*N+5=1*N+0=5)。因此,有多个工作项写入C的同一个元素,其中一些正在访问内存的无效部分,从而产生无意义的结果。在gpuMM中,您应该测试该行在哪里预设
得到初始化?@PaulMcKenzie在我调用
MultipleMatrix xCuda
之前,它们被初始化,在my
main()
中。我已编辑了我的问题。您正在处理5x5矩阵,但块大小为16x16。这意味着,除了一个线程试图处理非常真实的(行,列)=(1,0)之外,还有一个线程试图处理不存在的(行,列)=(0,5)-但是这两个项目重叠(0*N+5=1*N+0=5)。因此,有多个工作项写入C的同一个元素,其中一些正在访问内存的无效部分,从而产生无意义的结果。在gpuMM中,您应该测试该行