c++ - 当我尝试从设备复制时,cudaMemcpy 返回 cudaErrorInvalidValue
问题描述
我是 C++ 和 CUDA 的初学者。我试图编写一个计算素数的程序。该算法本身有效,但我无法从 GPU 获得结果:内核停止计算后,我尝试使用 将数据复制回主机cudaMemcpy
,但它会抛出cudaErrorInvalidValue
.
我做什么:因为我不知道究竟会返回多少质数,所以我决定创建一个结构来分配内存,存储指向内存/已用大小的指针,并Add
为内核提供一个函数。
template <typename T>
struct KernelArray
{
T* array = nullptr;
int* size = nullptr;
const int capacity;
KernelArray(const int &capacity)
: capacity(capacity)
{
checkCudaErrors(cudaMalloc(&array, capacity * sizeof(T))); // this all works
checkCudaErrors(cudaMalloc(&size, sizeof(int)));
checkCudaErrors(cudaDeviceSynchronize());
}
~KernelArray()
{
checkCudaErrors(cudaFree(array));
checkCudaErrors(cudaFree(size));
}
void CopyToDevice(const T* arr, const int &size) // this works too
{
if (size > capacity) throw std::invalid_argument("argument 'size' is bigger than allocated memory size");
checkCudaErrors(cudaMemcpy(array, arr, size * sizeof(T), cudaMemcpyHostToDevice));
checkCudaErrors(cudaMemcpy(this->size, &size, sizeof(int), cudaMemcpyHostToDevice));
checkCudaErrors(cudaDeviceSynchronize());
}
int GetSizeFromDevice() const
{
int* toReturn = (int*)malloc(sizeof(int));
checkCudaErrors(cudaMemcpy(toReturn, size, sizeof(int), cudaMemcpyDeviceToHost)); // there is an error
checkCudaErrors(cudaDeviceSynchronize());
int ret = *toReturn;
free(toReturn);
return ret;
}
/* ... */
__device__ void dAdd(const T &a)
{
if (*size == capacity) return;
array[(*size)++] = a;
}
};
在main
我预先计算了一些素数以将它们推送到 GPU,并将它们传递到结构内部的内核中。
KernelArray<int> devPrimes(N / 4);
devPrimes.CopyToDevice(firstPrimes.data(), firstPrimes.size()); //from vector
findPrimesKernel <<<1, 1>>> (nSqrt, N, devPrimes);
auto cudaStatus = cudaGetLastError();
if (cudaStatus != cudaSuccess) {
fprintf(stderr, "addKernel launch failed: %s\n", cudaGetErrorString(cudaStatus));
}
checkCudaErrors(cudaDeviceSynchronize());
int arrivedSize = devPrimes.GetSizeFromDevice(); // error when it steps inside here
int* arrivedArray = (int*)malloc(arrivedSize*sizeof(int));
devPrimes.CopyFromDevice(arrivedArray);
printf("last device primes: %d %d %d", arrivedArray[arrivedSize-3], arrivedArray[arrivedSize - 2], arrivedArray[arrivedSize - 1]);
内核代码检查数字,但仅使用KernelArray::dAdd
函数更改素数数组。内核完成没有错误。
所以导致错误的代码是这样的(唯一发生的错误):
int GetSizeFromDevice() const
{
int* toReturn = (int*)malloc(sizeof(int));
checkCudaErrors(cudaMemcpy(toReturn, size, sizeof(int), cudaMemcpyDeviceToHost)); // this line
// CUDA error at .../kernel.cu:46 code=11(cudaErrorInvalidValue) "cudaMemcpy(toReturn, size, sizeof(int), cudaMemcpyDeviceToHost)"
checkCudaErrors(cudaDeviceSynchronize());
int ret = *toReturn;
free(toReturn);
return ret;
}
内核功能:
_global__ void findPrimesKernel(int from, int to, KernelArray<int> primes)
{
printf("Start..\n");
for (int i = from+threadIdx.x; i <= to; i+=blockDim.x)
{
for (int p = 0; p < *primes.size; ++p)
{
auto prime = primes.array[p];
if (i % prime == 0) {
break;
}
if (i < prime*prime)
{
printf("[%d] found prime %d (size: %d, prime^2: %d^2)\n",threadIdx.x, i, *primes.size, prime);
primes.dAdd(i);
break;
}
}
}
printf("Done from %d to %d)\n", from, to);
}
任何想法为什么它不起作用,或者我应该修复什么才能使它起作用?
提前致谢!
解决方案
推荐阅读
- laravel - 是否可以在创建授权资源中添加一些参数?
- android - 如何在andoird中使用MaterialDatePicker
- scichart - SciChart 3.1 异常
- go - 无法使用 protobuf 包
- java - 我的成本函数无法最小化到 0.2 以下。我正在使用 IRIS 数据集来测试我的网络
- android - 创建“重定向”身份验证活动
- wordpress - 增加 Google Cloud 中的上传文件大小限制
- docker - UUID 的默认 Docker 参数
- postgresql - PostgreSQL - 创建随机百分比?
- javascript - 在 jquery ajax 中使用 django url 标签