【问题标题】:Tricky issue with accessing the data of a (complex) variable, defined as pointer (C++)访问定义为指针(C++)的(复杂)变量的数据的棘手问题
【发布时间】:2021-05-08 10:43:31
【问题描述】:

这是我假设知道的:在控制台中打印变量“i”时,通常使用命令“std::cout

但在下面的(经典 CUDA FFT)C++ 示例中,这不起作用,我不知道为什么。这是代码sn-p(为了清楚起见,我不想发布整个代码):

cufftExecR2C(fftPlanFwd, (cufftReal *)d_PaddedData, (cufftComplex *)d_DataSpectrum);
for (int i = 0; i < 8; i++)
{
    std::cout << (cufftComplex*)d_DataSpectrum << '\n';
}

“cufftExecR2C”是“实数到复数”命令,用于将变量“d_PaddedData”中的数字 0 到 8 进行傅里叶变换到具有复数的变量“d_DataSpectrum”。我认为这些是指针。

我想检查其余代码是否按预期工作并打印出变量。问题:我得到了 9 次:“000000070CE00C00”打印在控制台中,这在我看来是地址而不是变量的数据?

我尝试了以下组合,而不是 (cufftComplex*)d_DataSpectrum:“*d_DataSpectrum”、“d_DataSpectrum”、“*d_DataSpectrum[0]”、“d_DataSpectrum[0]”。后两者很可能是复杂变量存储在两列数组中。只有“d_DataSpectrum”可以编译成功但也给我000000070CE00C00。

我想知道我是否错过了获取该指针数据的任何技巧?


编辑:

声明

fComplex *d_DataSpectrum;
cudaMalloc((void **)&d_DataSpectrum,   fftH * (fftW / 2 + 1) * sizeof(fComplex))

这两行代码都可以编译,但会导致 .exe 在此时调用时崩溃:

    std::cout << "The Original data is " << d_PaddedData[i] << '\n';
    std::cout << "The FFT'd data is" << ((cufftComplex*)d_DataSpectrum)[i].x << '\n'; //crash even with added 'd_DataSpectrum)[i].y' as recommended

编辑2:

用“&”编辑它后:

    std::cout << "The Original data is " << &d_PaddedData[i] << '\n';
    std::cout << "The FFT'd data is" << &((cufftComplex*)d_DataSpectrum)[i].x << '\n';

它运行:

The FFT'd data is000000070CE00C10
The Original data is 000000070CE0040C
The FFT'd data is000000070CE00C18
The Original data is 000000070CE00410
The FFT'd data is000000070CE00C20
The Original data is 000000070CE00414
The FFT'd data is000000070CE00C28

为什么“&”现在起作用了?

【问题讨论】:

  • 仅根据 CUDA 文档和对您的代码的一些假设进行猜测,但我会尝试 std::cout &lt;&lt; ((cufftComplex*)d_DataSpectrum)[i].x &lt;&lt; ' ' &lt;&lt; ((cufftComplex*)d_DataSpectrum)[i].y &lt;&lt; '\n';
  • 了解d_DataSpectrum 的声明方式会有所帮助。
  • 谢谢,你们俩都是金子。我添加了声明。
  • 那么崩溃是一个完全不同的问题。您的代码中有一些错误,恐怕我没有使用 CUDA 的经验,所以我不知道它是什么。
  • 我认为崩溃是由fComplexcufftComplex 之间的混淆引起的。您的代码似乎无法决定您真正想要这两种类型中的哪一种。你不能只是混合搭配不同的类型。

标签: c++ pointers cuda


【解决方案1】:

在我看来是地址而不是变量的数据?

是的,这是一个地址,很可能是您的实数或复数数组 d_DataSpectrum 的(起始)地址(请提供声明!)。您不是在这里取消引用,您只是尝试强制转换为 cufftComplex 的指针。请记住,您要打印出一个复杂的值,而不是像 float 或 double 这样的单个默认可打印值!

cufftComplex(通常)是这样定义的:

typedef cuComplex cufftComplex;

因此,在您的初始数组 d_DataSpectrum 与 cuComplex“兼容”的前提下,您应该能够通过 john 在 cmets 中提到的方式打印您的复数值(分离访问实数和复数部分):

std::cout << ((cufftComplex*)d_DataSpectrum)[i].x << ' ' << ((cufftComplex*)d_DataSpectrum)[i].y << '\n';

您观察到崩溃的原因:

fComplex *d_DataSpectrum;
cudaMalloc((void **)&d_DataSpectrum,   fftH * (fftW / 2 + 1) * sizeof(fComplex))

这是分配设备端内存缓冲区。对于正确的打印输出,您必须首先通过 cudaMemcpy 将其传输回主机,并将 cudaMemcpyDeviceToHost 传输到有效分配的主机端缓冲区。即使这也是一个问题,对于与您的非常相似的一般方案,请参阅

https://forums.developer.nvidia.com/t/cufft-cufftplan1d-and-cufftexecr2c-issues/43811

主机与设备数组使用和打印值的一般最小示例:

https://gist.github.com/dpiponi/1502434

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多