【问题标题】:Why is this simple CUDA kernel getting a wrong result?为什么这个简单的 CUDA 内核会得到错误的结果?
【发布时间】:2021-07-27 23:27:39
【问题描述】:

我是 CUDA 的新手。我正在学习一些基本的东西,因为我想在其他项目中使用 CUDA。我编写此代码是为了将 8x8 方阵中的所有元素相加,该方阵已填充 1,因此结果必须为 64。

#include <stdio.h>
#include <stdlib.h>
#include <iostream>

const int SIZE = 64;


__global__ void add_matrix_values(int* matrix, int sum, int c)
{

    int i = threadIdx.x + blockIdx.x * blockDim.x;
    int j = threadIdx.y + blockIdx.x * blockDim.x;

    sum += matrix[i*c+j];

}



int main()
{
    
    int* device_matrix;
    int* host_matrix;
    int c = 8;      //Squared matrix cxc
    int device_c = 8;
    int device_sum =  0;
    int host_sum  = 0;

    //Allocate host memory
    host_matrix = (int*)malloc(sizeof(int)*SIZE);
    //Fill the matrix values with 1's
    for(auto i = 0; i < SIZE; i++)
        host_matrix[i] = 1;
    
    //Allocate device memory
    cudaMalloc((void**) &device_matrix,sizeof(int)*SIZE);
    cudaMalloc((void**) &device_sum, sizeof(int));
    cudaMalloc((void**) &device_c,sizeof(int));

    //Fill device_matrix with host_matrix values
    cudaMemcpy(&device_matrix,&host_matrix,sizeof(int)*SIZE,cudaMemcpyHostToDevice);
    //Initialize device_sum with a 0 
    cudaMemcpy(&device_sum,&host_sum,sizeof(int),cudaMemcpyHostToDevice);
    //Initialize device_c with the correct value
    cudaMemcpy(&device_c,&c,sizeof(int),cudaMemcpyHostToDevice);


    //4 blocks with 16 threads every single block ¿Is this correct?
    add_matrix_values<<<4,16>>>(device_matrix, device_sum,device_c);

    cudaMemcpy(&host_sum,&device_sum,sizeof(int),cudaMemcpyDeviceToHost);

    std::cout<<"The value is: "<<host_sum<<std::endl;


    cudaFree(device_matrix);
    free(host_matrix);

    return 0;




}


结果必须是 64,但我得到了错误的数字。

 migue@migue  ~/Escritorio  ./program
The value is: 32762
 migue@migue  ~/Escritorio  ./program
The value is: 32608
 migue@migue  ~/Escritorio  ./program
The value is: 32559

我不知道我做错了什么。可能是 gridSize 和 blockSize ?或者它可能是 cuda 内核中的 i 和 j 操作?

我不太了解这些术语。

【问题讨论】:

    标签: c++ c cuda


    【解决方案1】:

    有很多问题:

    • 您正在创建一维网格(网格配置、块配置),因此内核代码(i、j 或 x、y)中的二维索引没有任何意义
    • 您正在通过值传递sum。您无法以这种方式检索结果。内核中对sum 的更改不会反映在调用环境中。这是一个 C++ 概念,并非特定于 CUDA。请改用正确分配的指针。
    • 在 CUDA 多线程环境中,您不能让多个线程在没有任何控制的情况下更新相同的位置/值。 CUDA 不会为您整理出这种访问权限。您必须使用并行归约技术,这里最简单的方法可能是使用原子。您可以在 cuda 标签上找到许多讨论并行缩减的问题。
    • 您通常会混淆按值传递和按指针传递。按值传递的项目可以是普通的主变量。您通常不需要为这些分配cudaMalloc。您也不要在除指针之外的任何类型的变量上使用cudaMalloc
    • 您对cudaMemcpy 的使用不正确。不需要获取指针的地址。

    以下代码解决了上述项目:

    $ cat t135.cu
    #include <stdio.h>
    #include <stdlib.h>
    #include <iostream>
    
    const int SIZE = 64;
    
    
    __global__ void add_matrix_values(int* matrix, int *sum, int c)
    {
    
        int i = threadIdx.x + blockIdx.x * blockDim.x;
        atomicAdd(sum, matrix[i]);
    
    }
    
    
    
    int main()
    {
    
        int* device_matrix;
        int* host_matrix;
        int device_c = 8;
        int *device_sum;
        int host_sum  = 0;
    
        //Allocate host memory
        host_matrix = (int*)malloc(sizeof(int)*SIZE);
        //Fill the matrix values with 1's
        for(auto i = 0; i < SIZE; i++)
            host_matrix[i] = 1;
    
        //Allocate device memory
        cudaMalloc((void**) &device_matrix,sizeof(int)*SIZE);
        cudaMalloc((void**) &device_sum, sizeof(int));
    
        //Fill device_matrix with host_matrix values
        cudaMemcpy(device_matrix,host_matrix,sizeof(int)*SIZE,cudaMemcpyHostToDevice);
        //Initialize device_sum with a 0
        cudaMemcpy(device_sum,&host_sum,sizeof(int),cudaMemcpyHostToDevice);
    
    
        //4 blocks with 16 threads every single block ¿Is this correct?
        add_matrix_values<<<4,16>>>(device_matrix, device_sum,device_c);
    
        cudaMemcpy(&host_sum,device_sum,sizeof(int),cudaMemcpyDeviceToHost);
    
        std::cout<<"The value is: "<<host_sum<<std::endl;
    
    
        cudaFree(device_matrix);
        free(host_matrix);
    
        return 0;
    
    }
    $ nvcc -o t135 t135.cu
    $ cuda-memcheck ./t135
    ========= CUDA-MEMCHECK
    The value is: 64
    ========= ERROR SUMMARY: 0 errors
    $
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-22
      • 2014-08-08
      • 2016-10-13
      • 1970-01-01
      • 1970-01-01
      • 2023-03-11
      • 2019-01-25
      相关资源
      最近更新 更多