0

我有这个代码,它每 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);
}
4

3 回答 3

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

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

于 2012-05-17T05:44:29.287 回答
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。


该文档提供了有关cudaMallocHostvsmalloc用法的提示:

cudaError_t cudaMallocHost ( void ** ptr, size_t size )

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

于 2012-05-17T04:46:10.283 回答
0

If you are on Linux, try running running your app under the CUDA debugger, with memory checking turned on:

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

If you are on Windows, select Nsight | Enable CUDA Memory Checker and run your code from the built-in CUDA debugger. Nsight | Start CUDA Debugging.

Also, add code to your app to check the return values from each of the CUDA calls.

See for more information about the CUDA Memchecker:

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

于 2012-05-17T04:13:45.980 回答