为什么这个简单的 CUDA 内核会得到错误的结果?
Why is this simple CUDA kernel getting a wrong result?
我是 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 操作?
我不是很明白这些条款。
存在一些问题:
- 您正在创建一维网格(网格配置、块配置),因此内核代码中的二维索引(i、j 或 x、y)没有任何意义
- 您正在按值传递
sum
。您无法以这种方式检索结果。内核中对 sum
的更改不会反映在调用环境中。这是一个 C++ 概念,并非特定于 CUDA。请改用正确分配的指针。
- 在 CUDA 多线程环境中,您不能让多个线程在没有任何控制的情况下更新同一个 location/value。 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
$
我是 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 操作?
我不是很明白这些条款。
存在一些问题:
- 您正在创建一维网格(网格配置、块配置),因此内核代码中的二维索引(i、j 或 x、y)没有任何意义
- 您正在按值传递
sum
。您无法以这种方式检索结果。内核中对sum
的更改不会反映在调用环境中。这是一个 C++ 概念,并非特定于 CUDA。请改用正确分配的指针。 - 在 CUDA 多线程环境中,您不能让多个线程在没有任何控制的情况下更新同一个 location/value。 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
$