将设备端复杂 * 转换为 double * 或 float * 用于 cublas

Posted

技术标签:

【中文标题】将设备端复杂 * 转换为 double * 或 float * 用于 cublas【英文标题】:Casting device-side complex * to double * or float * for cublas 【发布时间】:2021-06-13 00:43:44 【问题描述】:

问题

使用reinterpret_cast()complex * 转换为float *double * 指针是否安全

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

如果没有,有没有聪明的方法来解决这个问题?

限制

obj 是一个 C 结构体(因此不能直接重载运算符) 我无法将devicePtr 存储为float *objdevicePtr 只保存一个指向单个值的指针。考虑到 reinterpret_cast 的诡计,这可能是相关的,但在幕后 devicePtr 是池的一部分:
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;
  

cublas 调用是在流上异步进行的,因此要避免将devicePtr 的内容复制到主机和同步流以执行转换。 同样,启动微内核也不理想,但也许是不可避免的。

我见过many questions 将double *float * 转换为complex *,但反之则不多。

【问题讨论】:

为了清楚起见,请注意:您链接到的问题是关于std::complex,而不是thrust::complex。虽然有意与std::complex 兼容,但我的理解是reinterpret_casts 的指定相当差,因此很难做出具体保证。 啊抱歉,这是因为我忘记添加thrust::complex 也可能是std::complex 的问题,我将编辑问题以反映这一点。感谢您指出这一点。 【参考方案1】:

在底层,CUDA 中可用的复杂类型通常应该是两个值的结构。作为一个可能的例子,你可以通过查看 cuComplex.h 头文件来了解我的意思。

将指向此类的指针转换为与该结构中的值一致的指针类型,通常应该比其他方式更少风险(相反,除了基数之外还有额外的对齐要求类型)。

如果您准确地提出您正在讨论的类型,那么我声称这个问题与 CUDA 无关,实际上只是一个 c++ 问题。

如果您进行这样的转换,然后将其提供给 cublas 函数,在一般情况下,我认为您将同时计算实部和虚部,这对我来说似乎很奇怪。但是,对于您所展示的情况,这应该不是问题。

您似乎也对设备指针所在的位置有些困惑:

将 devicePtr 复制到主机

任何可用于 CUBLAS 调用的最新版本 CUBLAS 的设备指针都存在于主机内存中。

【讨论】:

> “您似乎也对设备指针所在的位置有些困惑:”。我的意思是把设备指针的内容复制到主机上,而不是指针本身。我将编辑问题以反映这一点。【参考方案2】:

根据文档,这在理论上应该是可能的,尽管它并不明确。

如果您与std::complex&lt;T&gt; 打交道,答案将是肯定的“是”。根据cppreference,指向std::complex&lt;T&gt;数组的指针可以是reinterpret_cast指向T数组的指针,具有直观的语义。这是为了与 C 的复数兼容。

现在 thrust::complex&lt;T&gt;, the documentation states, “它在功能上与它相同,但也可以用于 std::complex 目前无法使用的设备代码。” “功能相同”是否包括与 C 的复杂类型的兼容性并不明确。也就是说,结构的布局与人们期望的 std::complex&lt;T&gt; 的布局相同,这意味着(在实际意义上)这样的演员阵容很可能会像 std::complex&lt;T&gt; 一样工作。

【讨论】:

以上是关于将设备端复杂 * 转换为 double * 或 float * 用于 cublas的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Python Decimal 实例转换为 C++ double?

C或C++中如何把一个double型的数转换成字符串?

在java中,两个子类可否互相转换?

如何将 double 类型转换为 DWORDLONG 或 DWORD 转换为 DWORDLONG 或 DWORD_PTR 转换为 DWORDLONG

通过 cast 或 Convert.ToSingle() 将 double 转换为 float?

共读Primer58.[6.5]参数匹配 Page217