CUFFT 1-D FFT期间发生奇怪的崩溃

时间:2012-05-17 03:14:39

标签: c++ c memory-management cuda fft

我有这个代码,它每1-2次发布就会崩溃。 我尝试过使用malloc / cudaMallocHost / cudeMalloc但它没用。它认为它发生是由于手动cufftComplex初始化但证明它不能,因为没有数据我不能得到fft。你能帮我消除这次崩溃吗?

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <conio.h>
#include <cuda.h>
#include <cufft.h>

using namespace std;

int main(int argc, char **argv)
{
cufftHandle plan;
cufftComplex *data;
cufftComplex *digits;
cufftComplex *h_data;

cudaMallocHost((void**)&digits, sizeof(cufftComplex)*8);
digits[0].x = 12.5f; digits[0].y = 0.0f;
digits[1].x = 66.23f; digits[1].y = 0.0f;
digits[2].x = 35.1f; digits[2].y = 0.0f;
digits[3].x = 16.7f; digits[3].y = 0.0f;
digits[4].x = 14.83f; digits[4].y = 0.0f;
digits[5].x = 55.1f; digits[5].y = 0.0f;
digits[6].x = 11.7f; digits[6].y = 0.0f;
digits[7].x = 18.83f; digits[7].y = 0.0f;

cudaMalloc((void**)&data, sizeof(cufftComplex)*8);

cudaMemcpy(data, digits, sizeof(cufftComplex)*8, cudaMemcpyHostToDevice);

if (cufftPlan1d(&plan, 8, CUFFT_C2C, 1) != CUFFT_SUCCESS) {
    fprintf(stderr, "Cuda: cufftPlan1d CUFFT_C2C failed\n");
    return 1;
}

if (cufftExecC2C(plan, data, data, CUFFT_FORWARD) != CUFFT_SUCCESS) {
    fprintf(stderr, "Cuda: cufftExecC2C CUFFT_FORWARD failed\n");
    return 1;
}

if (cudaMalloc((void**)&h_data, sizeof(cufftComplex)*8) != cudaSuccess) {
    fprintf(stderr, "Cuda: cudaMalloc((void**)&h_data failed\n");
    return 1;
}

cudaMemcpy(h_data, data, sizeof(cufftComplex)*8, cudaMemcpyDeviceToHost);


printf("\nOriginal:\n");
for(int i = 0; i < 8; ++i){
    printf("\nRe:%2.5f   Im:%2.5f", digits[i].x, digits[i].y);
} 

printf("\n\n1D-FFT:\n");
for(int i = 0; i < 8; ++i){
    printf("\nRe:%2.5f   Im:%2.5f", h_data[i].x, h_data[i].y);
} 

cudaFree(digits);
cudaFree(data);
cudaFree(h_data);
cufftDestroy(plan);
}

3 个答案:

答案 0 :(得分:1)

而不是:

if (cudaMalloc((void**)&h_data, sizeof(cufftComplex)*8) != cudaSuccess) {
    fprintf(stderr, "Cuda: cudaMalloc((void**)&h_data failed\n");
    return 1;
}

尝试:

if (cudaMallocHost((void**)&h_data, sizeof(cufftComplex)*8) != cudaSuccess) {
    fprintf(stderr, "Cuda: cudaMalloc((void**)&h_data failed\n");
    return 1;
}


因为你要将字节复制回cpu。


该文档提供了cudaMallocHost vs malloc用法的提示:

  

cudaError_t cudaMallocHost(void ** ptr,size_t size)

     

分配页面锁定且可访问的主机内存的大小字节   到设备。驱动程序跟踪分配的虚拟内存范围   使用此功能并自动加速对函数的调用   例如cudaMemcpy *()。由于可以直接访问内存   该设备可以读取或写入比带宽更高的带宽   使用malloc()等函数获得的可分页内存。分配   cudaMallocHost()过多的内存可能会降低系统性能   性能,因为它减少了可用的内存量   寻呼系统。因此,最好谨慎使用此功能   为主机和设备之间的数据交换分配暂存区域。

答案 1 :(得分:1)

您的基本问题是主机和设备内存指针混合不当。您已将设备内存分配的地址(使用cudaMalloc)分配给h_data,但正尝试将其用作指向主机内存中地址的指针。这将无法正常工作,并产生您看到的主机分段错误。您的示例应该类似于:

#include <cstdlib>
#include <cuda_runtime.h>
#include <cufft.h>

int main(int argc, char **argv)
{
    cufftHandle plan;
    cufftComplex *data, *digits, *h_data;

    digits = (cufftComplex *)malloc(sizeof(cufftComplex)*8);
    digits[0].x = 12.5f; digits[0].y = 0.0f;
    digits[1].x = 66.23f; digits[1].y = 0.0f;
    digits[2].x = 35.1f; digits[2].y = 0.0f;
    digits[3].x = 16.7f; digits[3].y = 0.0f;
    digits[4].x = 14.83f; digits[4].y = 0.0f;
    digits[5].x = 55.1f; digits[5].y = 0.0f;
    digits[6].x = 11.7f; digits[6].y = 0.0f;
    digits[7].x = 18.83f; digits[7].y = 0.0f;

    cudaMalloc((void**)&data, sizeof(cufftComplex)*8);
    cudaMemcpy(data, digits, sizeof(cufftComplex)*8, cudaMemcpyHostToDevice);

    if (cufftPlan1d(&plan, 8, CUFFT_C2C, 1) != CUFFT_SUCCESS) {
        fprintf(stderr, "Cuda: cufftPlan1d CUFFT_C2C failed\n");
        return 1;
    }

    if (cufftExecC2C(plan, data, data, CUFFT_FORWARD) != CUFFT_SUCCESS) {
        fprintf(stderr, "Cuda: cufftExecC2C CUFFT_FORWARD failed\n");
        return 1;
    }

    h_data = (cufftComplex *)malloc(sizeof(cufftComplex)*8);
    cudaMemcpy(h_data, data, sizeof(cufftComplex)*8, cudaMemcpyDeviceToHost);

    printf("\nOriginal:\n");
    for(int i = 0; i < 8; ++i){
        printf("\nRe:%2.5f   Im:%2.5f", digits[i].x, digits[i].y);
    } 

    printf("\n\n1D-FFT:\n");
    for(int i = 0; i < 8; ++i){
        printf("\nRe:%2.5f   Im:%2.5f", h_data[i].x, h_data[i].y);
    } 

    free(digits);
    free(h_data);
    cudaFree(data);
    cufftDestroy(plan);
}

请注意,您应该使用普通malloc或C ++ new运算符来分配主机端内存而不是cudaMallocHost,除非您非常了解后者API的作用以及为什么使用它。

答案 2 :(得分:0)

如果您使用的是Linux,请尝试在CUDA调试器下运行您的应用程序,并启用内存检查:

nvcc –g –G myapp.cu –o myapp
cuda-gdb myapp
(cuda-gdb) set cuda memcheck on 
(cuda-gdb) run

如果您使用的是Windows,请选择Nsight | Enable CUDA Memory Checker并从内置CUDA调试程序运行代码。 Nsight | Start CUDA Debugging

此外,在您的应用中添加代码以检查每个CUDA调用的返回值。

有关CUDA Memchecker的更多信息,请参阅:

http://developer.nvidia.com/nvidia-gpu-computing-documentation#CUDA-MemcheckUserManual