Jacob Faib
Jacob Faib

Reputation: 1130

Casting device-side complex * to double * or float * for cublas

Problem

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?

Restrictions

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;
  }
}

I have seen many questions about casting double * or float * to complex * but not many the other way around.

Upvotes: 0

Views: 673

Answers (2)

Ken Wayne VanderLinde
Ken Wayne VanderLinde

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

Robert Crovella
Robert Crovella

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

Related Questions