void *指针的指针算法

时间:2016-06-27 07:13:46

标签: c++ pointers cuda pointer-arithmetic

我正在使用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&lt; char *&gt;但这不起作用,因为cuffDoubleComplex *不能静态转换为char *。

我有点困惑为什么带有void指针算法的第二个cudaMemcpy正在工作,据我所知它不应该。编译器是否隐式假设void *后面的数据类型是一个字节长?

我应该在那里换一些东西吗?使用reinterpret_cast&lt; char *&gt;(inputData)例如?

同样在分配期间,我使用旧的C风格(void **)演员。我这样做是因为我收到了“从cufftDoubleComplex **到void **的无效static_cast”。有没有其他方法可以正确地做到这一点?

仅供参考:Link to cudaMemcpy2D Doc

Link to cudaMalloc Doc

1 个答案:

答案 0 :(得分:1)

你不能对void*进行算术运算,因为对指针的算术运算是基于指向对象的大小的(并且sizeof(void)并不意味着什么)。

您的代码编译可能归功于编译器扩展,该扩展将void*上的算术运算视为char*上的算术运算。

在您的情况下,您可能不需要算术运算,以下应该可以工作(并且更加健壮):

coypResult &= cudaMemcpy2D(static_cast<void*>(&inputData->y),
                           sizeof (cufftDoubleComplex),

由于cufftDoubleComplex只是:

struct __device_builtin__ __builtin_align__(16) double2
{
    double x, y;
};