如何正确地将复数从向量向量复制到 GPU 设备内存并使用 CUDA 执行 FFT?

问题描述 投票:0回答:1

我正在开发一个 C++ Windows 项目,该项目涉及使用 CUDA 10.1 库在设备上进行 FFT 计算。 我有一个向量向量

std::vector<std::vector<std::complex<float>>> unitedVector
,我需要将其内容复制到设备内存以在 GPU 上执行 FFT。 我有一个
std::complex<float>* gpu_data
指针,它使用
cudaMalloc
指向设备上分配的内存。

要初始化 cuFFT 计划,我使用以下代码:

cufftHandle plan;
int data_size = unitedVector[0].size();  // Size of data in each vector
int num_channels = unitedVector.size();  // Number of vectors (or channels with data)
std::complex<float>* gpu_data;

cufftPlan1d(&plan, data_size, CUFFT_C2C, num_channels); // Create FFT plan
cudaMalloc((void**)&gpu_data, num_channels * data_size * sizeof(std::complex<float>)); // Allocation of memory on the GPU

计划初始化后,我像这样复制数据:

cudaMemcpy(gpu_data, unitedVector[0].data(), num_channels * data_size * sizeof(std::complex<float>), cudaMemcpyHostToDevice);

接下来,我执行FFT如下:

cufftResult result = cufftExecC2C(plan, reinterpret_cast<cufftComplex*>(gpu_data), reinterpret_cast<cufftComplex*>(gpu_data), CUFFT_FORWARD);

// Rotate the spectrum (fftshift)
int half_size = data_size / 2;
    for (int i = 0; i < num_channels; ++i) {
        cudaMemcpy(unitedVector[i].data(), gpu_data + i * data_size + half_size, half_size * sizeof(std::complex<float>), cudaMemcpyDeviceToHost);
        cudaMemcpy(unitedVector[i].data() + half_size, gpu_data + i * data_size, half_size * sizeof(std::complex<float>), cudaMemcpyDeviceToHost);
    }

// unitedVector now contains the FFT results for each vector

我的 FFT 实现在设备上运行,并使用 cuFFT 库来实现此目的。

问题:如何正确地将数据从unitedVector复制到gpu_data,以及如何使用CUDA对设备上的每个向量进行FFT?您能否提供此任务的示例代码?

我使用上面的代码复制数据并进行FFT。但是,我在 FFT 结果方面遇到问题:前 3-4 次 FFT 计算正确(如在 Matlab 中),然后出现异常。我怀疑问题可能出在数据副本错误或我的 FFT 实现上。我该如何解决这种情况?

c++ windows cuda fft
1个回答
0
投票

尝试使用

reinterpret_cast
来浮动指针并利用
std::complex<float>
是两个连续浮点数的约定。

int n_bytes = data_size * 2 * sizeof(float);// 2 floats per complex<float>
cudaError_t status;
for (int i = 0; i < num_channels; ++i) {
  float *to = reinterpret_cast<float*>( gpu_data ) + (2 * i * data_size);
  float *from = reinterpret_cast<float*>( unitedVector[i].data() );
  status = cudaMemcpy((void *)to, (void *)from, (size_t)n_bytes, cudaMemcpyDeviceToDevice);
  if (status != cudaSuccess)
    std::cout<<"CudaMemcpy failed!"<<std::endl;;
}
© www.soinside.com 2019 - 2024. All rights reserved.