2012-05-17 55 views
0

我有這段代碼,每次啓動都會崩潰。 我曾嘗試使用malloc/cudaMallocHost/cudeMalloc但它沒用。它認爲這是由於手動cufftComplex初始化發生的,但證明它不能,因爲沒有數據我不能得到fft。你能幫我消除這種崩潰嗎?在CUFFT 1-D 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); 
} 

回答

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做什麼,爲什麼你正在使用它。

+0

謝謝澄清! –

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

+0

他正在收到主機端分段錯誤錯誤,cuda-gdb對此是完全矯枉過正。 – talonmies

+0

@talonmies:你發現的錯誤會導致程序每次都會崩潰,而不是每個「1-2次發佈」都如問題中所述。此外,錯誤的類型不包括在問題中。我認爲建議CUDA初學者嘗試在調試器中運行他們的程序作爲排除故障的第一步時,這並不是一件多餘的事情。在那裏有一個「免費」的巨大信息,初學者通常不會使用它。因此,我決定添加一個答覆,告訴他如何釣魚,而不是給他魚。 –

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(無效** PTR,爲size_t大小)

主機存儲器的

分配大小字節來是頁面鎖定的,並且可以通過 訪問設備。驅動程序使用此功能跟蹤分配爲 的虛擬內存範圍,並自動加速對函數 (如cudaMemcpy *())的調用。由於可以通過設備直接訪問內存,因此可以使用比使用malloc()等函數獲得的可分頁內存高得多的帶寬讀取或寫入內存。使用cudaMallocHost()分配 過量的內存可能會降低系統性能,因爲它會減少 系統可用於分頁的內存量。因此,最好使用此功能,以便爲主機和設備之間的數據交換分配暫存區域。

+0

感謝您的建議。 –