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