分配两个调用cudaMalloc的数组

时间:2012-12-03 14:37:50

标签: c++ c memory-management cuda gpu

内存分配是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一次为两个数组分配内存)工作?关于这是否是一种好方法的任何意见/答案也是受欢迎的。

更新
由于Robertdreamcrash的答案提示我必须向指针d_M添加元素数(numElements),而不是字节数的大小。仅供参考,没有可观察到的加速。

1 个答案:

答案 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你的无效参数