简体   繁体   中英

Pointer arithmetic on void* pointers

I am using the CUDA API / cuFFT API. In order to move data from host to GPU I am usign the cudaMemcpy functions. I am using it like below. len is the amount of elements on dataReal and 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.
}

I am aware, that pointer arithmetic on void pointers is actually not possible. the second cudaMemcpy2D does still work though. I still get a warning by the compiler, but it works correctly.

I tried using static_cast< char* > but that doesn't work as cuffDoubleComplex* cannot be static casted to char*.

I am a bit confused why the second cudaMemcpy with the pointer arithmetic on void is working, as I understand it shouldn't. Is the compiler implicitly assuming that the datatype behind void* is one byte long?

Should I change something there? Use a reinterpret_cast< char* >(inputData) for example?

Also during the allocation I am using the old C-style (void**) cast. I do this because I am getting a "invalid static_cast from cufftDoubleComplex** to void**". Is there another way to do this correctly?

FYI: Link to cudaMemcpy2D Doc

Link to cudaMalloc Doc

You cannot do arithmetic operations on void* since arithmetic operations on pointer are based on the size of the pointed objects (and sizeof(void) does not really mean anything).

Your code compiles probably thanks to a compiler extension that treats arithmetic operations on void* as arithmetic operation on char* .

In your case, you probably do not need arithmetic operations, the following should work (and be more robust):

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

Since cufftDoubleComplex is simply:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM