繁体   English   中英

为什么这个简单的 CUDA kernel 会得到错误的结果?

[英]Why is this simple CUDA kernel getting a wrong result?

我是 CUDA 的新手。 我正在学习一些基本的东西,因为我想在其他项目中使用 CUDA。 我编写了这段代码,以便从已填充 1 的 8x8 方阵中添加所有元素,因此结果必须为 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 Kernel 中的 i 和 j 操作?

我不太了解这些条款。

有很多问题:

  • 您正在创建一维网格(网格配置、块配置),因此 kernel 代码(i、j 或 x、y)中的二维索引没有任何意义
  • 您正在按值传递sum 您无法以这种方式检索结果。 kernel 对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
$

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM