访问定义为指针 (C++) 的(复杂)变量数据的棘手问题
Tricky issue with accessing the data of a (complex) variable, defined as pointer (C++)
这是我假设知道的:在控制台中打印变量“i”时,通常使用命令“std::cout << i”。如果“i”指的是一个指针,我会做“std::cout << *i”。到目前为止一切顺利。
但在下面的(经典 CUDA FFT)C++ 示例中,这不起作用,我不知道为什么。这是代码片段(为了清楚起见,我不想 post 整个代码):
cufftExecR2C(fftPlanFwd, (cufftReal *)d_PaddedData, (cufftComplex *)d_DataSpectrum);
for (int i = 0; i < 8; i++)
{
std::cout << (cufftComplex*)d_DataSpectrum << '\n';
}
"cufftExecR2C"是'real to complex'命令对变量"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
为什么“&”现在起作用了?
which seems to me the address and not the data of the variable?
是的,这是一个地址,很可能是您的实数或复数数组的(起始)地址 d_DataSpectrum(请提供声明!)。您在这里没有取消引用,您只是尝试转换为 cufftComplex 的指针。请记住,您想要打印出一个复杂的值,而不是像 float 或 double 这样的单个默认可打印值!
cufftComplex 是(通常)这样定义的:
typedef cuComplex cufftComplex;
所以,在你的初始数组d_DataSpectrum是'compatible'到cuComplex的前提下,你应该可以通过john在评论中提到的方式打印你的复数(分开访问真实和复杂的部分):
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
主机与设备数组使用和打印值的一般最小示例:
这是我假设知道的:在控制台中打印变量“i”时,通常使用命令“std::cout << i”。如果“i”指的是一个指针,我会做“std::cout << *i”。到目前为止一切顺利。
但在下面的(经典 CUDA FFT)C++ 示例中,这不起作用,我不知道为什么。这是代码片段(为了清楚起见,我不想 post 整个代码):
cufftExecR2C(fftPlanFwd, (cufftReal *)d_PaddedData, (cufftComplex *)d_DataSpectrum);
for (int i = 0; i < 8; i++)
{
std::cout << (cufftComplex*)d_DataSpectrum << '\n';
}
"cufftExecR2C"是'real to complex'命令对变量"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
为什么“&”现在起作用了?
which seems to me the address and not the data of the variable?
是的,这是一个地址,很可能是您的实数或复数数组的(起始)地址 d_DataSpectrum(请提供声明!)。您在这里没有取消引用,您只是尝试转换为 cufftComplex 的指针。请记住,您想要打印出一个复杂的值,而不是像 float 或 double 这样的单个默认可打印值!
cufftComplex 是(通常)这样定义的:
typedef cuComplex cufftComplex;
所以,在你的初始数组d_DataSpectrum是'compatible'到cuComplex的前提下,你应该可以通过john在评论中提到的方式打印你的复数(分开访问真实和复杂的部分):
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
主机与设备数组使用和打印值的一般最小示例: