内存分配是GPU中最耗时的操作之一,所以我想通过使用以下代码调用cudaMalloc
来分配2个数组:
int numElements = 50000;
size_t size = numElements * sizeof(float);
//declarations-initializations
float *d_M = NULL;
err = cudaMalloc((void **)&d_M, 2*size);
//error checking
// Allocate the device input vector A
float *d_A = d_M;
// Allocate the device input vector B
float *d_B = d_M + size;
err = cudaMemcpy(d_A, h_A, size, cudaMemcpyHostToDevice);
//error checking
err = cudaMemcpy(d_B, h_B, size, cudaMemcpyHostToDevice);
//error checking
原始代码位于cuda工具包的samples文件夹中,名为vectorAdd.cu,因此您可以假设h_A,h_B已正确启动且代码无需修改即可正常工作。
结果是第二个cudaMemcpy返回错误消息无效参数。
似乎操作“d_M + size”没有返回某人所期望的设备内存行为不同但我不知道如何。
是否可以使我的方法(调用cudaMalloc一次为两个数组分配内存)工作?关于这是否是一种好方法的任何意见/答案也是受欢迎的。
更新
由于Robert和dreamcrash的答案提示我必须向指针d_M添加元素数(numElements),而不是字节数的大小。仅供参考,没有可观察到的加速。
答案 0 :(得分:4)
你只需要替换它:
float *d_B = d_M + size;
的
float *d_B = d_M + numElements;
这是指针算法,如果你有一个浮点数组R = [1.0,1.2,3.3,3.4]
你可以通过printf("%f",*R);
打印第一个位置,如果你想打印第二个?
你必须做printf("%f\n",*(++R));
因此r [0] + 1.你没有像你一样做r[0] + sizeof(float)
。
执行r[0] + sizeof(float)
时,您将访问位置r [4]中的元素,因为size(float)= 4。
执行此操作float *d_B = d_M + numElements;
时,编译器会假设d_b将在内存中分配continuos,并且每个元素的大小都为float。所以你不需要用字节来表示距离,你只需要用元素来表示距离,编译器就会为你做数学运算。这种方法使人们更容易,因为它更直观地用元素而不是字节来表达指针算法。
你说结果是第二个cudaMemcpy返回错误,消息无效参数:
如果您打印与此错误相对应的数字,它将打印11您检查CUDA API您看到此错误对应于:
cudaErrorInvalidValue
这表示传递给API的一个或多个参数 电话不在可接受的价值范围内。
在您的示例中,表示浮动*d_B = d_M + size;
超出范围。
您已为100000
个浮点数分配空间,d_a将从0到50000开始,但根据您的代码,d_b将从numElements * sizeof(float);
50000 * 4 = 200000开始,因为200000> 100000你的无效参数。