CUDA代码中cudaMemset(d_arr,10,10*sizeof(int))调用错误原因咨询
问题原因分析:cudaMemset初始化int数组出现异常值
核心原因
cudaMemset和C标准库的memset逻辑完全一致:它是按单个字节填充内存区域的,而非按你要存储的int类型来设置每个元素的值。
你传入的第二个参数是10(十六进制0xA),cudaMemset会把目标内存的每一个字节都设为0xA。而一个int通常占4字节(32位系统),所以每个int元素的十六进制值为0x0A0A0A0A,转换成十进制是168430090,经过核函数的加1操作后,就变成了你看到的168430091。
至于设0时结果正常,是因为每个字节都设为0的话,组成的int值也是0,加1后自然是1,符合预期。
修正方案
如果要给int数组设置非0的统一初始值,不能用cudaMemset,可以用以下几种方法:
方法1:主机端初始化后拷贝到设备
在主机内存里先把数组元素都设为目标值,再用cudaMemcpy拷贝到设备端:
#include <stdio.h> #include <stdlib.h> __global__ void add1InGPU( int *devArr ) { int i = threadIdx.x; devArr[i] += 1; } int main( void ) { int *h_arr = (int*)malloc( 10 * sizeof( int ) ); // 主机端初始化每个元素为10 for(int i = 0; i < 10; i++){ h_arr[i] = 10; } int *d_arr = NULL; cudaMalloc( &d_arr, 10 * sizeof( int ) ); // 拷贝主机数组到设备 cudaMemcpy(d_arr, h_arr, 10 * sizeof(int), cudaMemcpyHostToDevice); add1InGPU <<<1, 10>>> ( d_arr ); cudaDeviceSynchronize(); cudaMemcpy(h_arr, d_arr, 10 * sizeof(int), cudaMemcpyDeviceToHost); cudaFree(d_arr); for (int i = 0; i < 10; i++) { printf("%d\n", h_arr[i]); } free( h_arr ); return 0; }
方法2:用核函数初始化设备数组
写一个简单的初始化核函数,让每个线程给对应位置的元素赋值:
#include <stdio.h> #include <stdlib.h> __global__ void add1InGPU( int *devArr ) { int i = threadIdx.x; devArr[i] += 1; } // 新增初始化核函数 __global__ void initDeviceArr(int *devArr, int val) { int i = threadIdx.x; devArr[i] = val; } int main( void ) { int *h_arr = (int*)malloc( 10 * sizeof( int ) ); int *d_arr = NULL; cudaMalloc( &d_arr, 10 * sizeof( int ) ); // 调用初始化核函数设置每个元素为10 initDeviceArr<<<1, 10>>>(d_arr, 10); cudaDeviceSynchronize(); add1InGPU <<<1, 10>>> ( d_arr ); cudaDeviceSynchronize(); cudaMemcpy(h_arr, d_arr, 10 * sizeof(int), cudaMemcpyDeviceToHost); cudaFree(d_arr); for (int i = 0; i < 10; i++) { printf("%d\n", h_arr[i]); } free( h_arr ); return 0; }
内容的提问来源于stack exchange,提问作者PkDrew
相关产品推荐
相关产品推荐

