c++pointerscudastrict-aliasing

Strict aliasing, CUdeviceptr, and cuMemAllocManaged


cuMemAllocManaged requires the pointer supplied as its first argument to be of type CUdeviceptr * (technically unsigned int *), but the point of using managed memory is to be able to manipulate the data in that same memory address on both host and device. Thus, to be able to manipulate managed data on the host, either those CUdeviceptrs must be cast to the appropriate pointer type (e.g. float * or double *) before access or the host must store the properly-typed pointer and cast to CUdeviceptr. To my knowledge, the former obviously violates strict aliasing rules, but will the latter as well or is it still safe as strict aliasing issues only occur when explicitly accessing data through a type-punned pointer?

In other words, are patterns similar to the following snippet safe even with strict aliasing enabled?

float* turkey;
CUdeviceptr* goose = reinterpret_cast<CUdeviceptr*>(&turkey); // alternatively, (CUdeviceptr*)&turkey
// error checking code elided
cuMemAllocManaged(goose, sizeof(float)*10000, CU_MEM_ATTACH_GLOBAL);
// initialize turkey
// supply goose as an argument to a kernel function
cuCtxSynchronize();
// do stuff with turkey on host again

Solution

  • It looks like either behavior is fine after all. Going by http://www.cocoawithlove.com/2008/04/using-pointers-to-recast-in-c-is-bad.html

    To be clear, these bugs can only occur if you dereference both pointers (or otherwise access their shared data) within a single scope or function. Just creating a pointer should be safe.

    Given that only one of the two typed pointers will be dereferenced in any given function scope, no issues with respect to strict aliasing will occur.

    There's also the union method, but whatever.