【发布时间】:2016-06-27 07:13:46
【问题描述】:
我正在使用 CUDA API / cuFFT API。为了将数据从主机移动到 GPU,我使用了 cudaMemcpy 函数。我正在使用它,如下所示。 len 是 dataReal 和 dataImag 上的元素数量。
void foo(const double* dataReal, const double* dataImag, size_t len)
{
cufftDoubleComplex* inputData;
size_t allocSizeInput = sizeof(cufftDoubleComplex)*len;
cudaError_t allocResult = cudaMalloc((void**)&inputData, allocSizeInput);
if (allocResult != cudaSuccess) return;
cudaError_t copyResult;
coypResult = cudaMemcpy2D(static_cast<void*>(inputData),
2 * sizeof (double),
static_cast<const void*>(dataReal),
sizeof(double),
sizeof(double),
len,
cudaMemcpyHostToDevice);
coypResult &= cudaMemcpy2D(static_cast<void*>(inputData) + sizeof(double),
2 * sizeof (double),
static_cast<const void*>(dataImag),
sizeof(double),
sizeof(double),
len,
cudaMemcpyHostToDevice);
//and so on.
}
我知道,对 void 指针的指针运算实际上是不可能的。第二个 cudaMemcpy2D 仍然有效。我仍然收到编译器的警告,但它可以正常工作。
我尝试使用 static_cast 但这不起作用,因为 cuffDoubleComplex* 不能静态转换为 char*。
我有点困惑,为什么第二个 cudaMemcpy 在 void 上使用指针算术正在工作,据我所知它不应该。编译器是否隐式假设 void* 后面的数据类型是一个字节长?
我应该在那里改变一些东西吗?例如使用 reinterpret_cast(inputData) ?
在分配过程中,我使用的是旧的 C 风格 (void**) 演员表。我这样做是因为我得到“从 cufftDoubleComplex** 到 void** 的无效 static_cast”。还有其他方法可以正确执行此操作吗?
【问题讨论】:
-
尝试
static_cast<void*>(&(inputData->y))(而不是+ ...)并使用sizeof(cufftDoubleComplex)而不是2 * sizeof(cufftDoubleComplex)(即使是相同的值,第一个更通用)。 -
不清楚为什么你觉得需要投射任何东西。
cudaMalloc不要求您转换为void **,cudaMemcpy2D也不要求您转换为void *。 -
cudaMalloc 需要一个 void** 而 cudaMemcpy2D 需要一个 void*。我知道一个事实,它们都适用于字节而不是类型。我实际上想要一个 char* 但这不是 CUDA API 想要我做的。
-
你不需要做任何转换。 (试试看。)只需将您计算的任何指针或计算指针(例如
&(double *))传递给cudaMalloc。同样对于cudaMemcpy(即double *)即使您要使用强制转换(再次,不必要)您应该首先执行所有指针运算,无论是相关类型(例如@987654336 @) 然后作为最后一步。这将完全避免使用void *进行任何指针运算。 -
在这种情况下,指针是隐式转换的,不是吗?老实说,我更喜欢手动操作,以便在我的代码中清楚地显示所有类型,这样任何人看到它,都可以立即看到所做的事情。同时,在强制转换之前做算术确实是有意义的。
标签: c++ pointers cuda pointer-arithmetic