Reputation: 1130
Is it safe to cast a complex *
to a float *
or double *
pointer using reinterpret_cast()
thrust::complex<float> *devicePtr; // only to show type, devicePtr otherwise lives in an object
/* OR */
float _Complex *devicePtr;
/* OR */
std::complex<float> *devicePtr;
cublasScnrm2(cublasv2handle,n,(cuComplex*)xarray,1,reinterpret_cast<float *>(obj->devicePtr));
If not, are there clever ways to solve this problem?
obj
is a C struct (so no direct operator overloading possible)devicePtr
as a float *
within obj
devicePtr
only ever holds a pointer to a single value. It may be relevant given the reinterpret_cast
trickery but behind the scenes devicePtr
is part of a pool:static thrust::complex<float> *pool;
/* OR */
static float _Complex *pool;
/* OR */
std::complex<float> *pool;
void giveObjectDevicePtr(object obj)
{
for (int i = 0; i < poolSize; ++i) {
if (poolEntryIsFree(pool,i)) obj->devicePtr = pool+i;
}
}
devicePtr
up to host and syncing stream to perform conversion is to be avoided.
I have seen many questions about casting double *
or float *
to complex *
but not many the other way around.
Upvotes: 0
Views: 673
Reputation: 19349
According to the documentation, this should theoretically be possible, though it is not explicit.
If you were dealing with std::complex<T>
, the answer would be a definitive "yes". According to cppreference, a pointer to a std::complex<T>
array can be reinterpret_cast
to a pointer to a T
array, with the intuitive semantics. This is for compatibility with C's complex numbers.
Now thrust::complex<T>
, the documentation states, "It is functionally identical to it, but can also be used in device code which std::complex currently cannot." Whether or not "functionally identical" includes compatibility with C's complex types is not explicit. That said, the structure is laid out as one would expect std::complex<T>
to be laid out, which means (in a practical sense) it's likely that such a cast will work just like for std::complex<T>
.
Upvotes: 1
Reputation: 152103
Underneath the hood, complex types usable in CUDA should generally be a struct of two values. You can see what I mean by looking at the cuComplex.h header file, as one possible example.
Casting a pointer to such, to a pointer type consistent with the values in that struct, should generally be less risky than the other way around (the other way around has additional alignment requirements beyond the base type).
If you posit the type you are discussing, exactly, then I claim this question has nothing to do with CUDA, and is really just a c++ question.
If you do such a cast, then provide that to a cublas function, in the general case I think you're going to be computing over both real and imaginary components, which seems weird to me. It should not be an issue for the case you have shown, however.
You also seem to have some confusion about where a device pointer lives:
copying devicePtr up to host
Any device pointer usable in a CUBLAS call for recent versions of CUBLAS lives in host memory.
Upvotes: 2