VS2013/Cuda7.0 中的 CUFFT 比 VS2010/Cuda4.2 慢 1000 倍

Posted

技术标签:

【中文标题】VS2013/Cuda7.0 中的 CUFFT 比 VS2010/Cuda4.2 慢 1000 倍【英文标题】:CUFFT is 1000x slower in VS2013/Cuda7.0 compared to VS2010/Cuda4.2 【发布时间】:2015-09-09 20:26:47 【问题描述】:

这个简单的 CUFFT 代码在两个 IDE 上运行 -

    VS 2013 与 Cuda 7.0 VS 2010 与 Cuda 4.2

我发现带有 Cuda 7.0 的 VS 2013 大约慢了1000 倍。代码在 VS 2010 中以 0.6 ms 执行,在 VS 2013 中以 520 ms 执行,平均而言。

#include "stdafx.h"
#include "cuda.h"
#include "cuda_runtime_api.h"
#include "cufft.h"
typedef cuComplex Complex;
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])

    cudaEvent_t start, stop;
    cudaEventCreate(&start);
    cudaEventCreate(&stop);
    cudaEventRecord(start);
    const int SIZE = 10000;
    Complex *h_col = (Complex*)malloc(SIZE*sizeof(Complex));
    for (int i = 0; i < SIZE; i++)
    
        h_col[i].x = i;
        h_col[i].y = i;
    
    Complex *d_col;
    cudaMalloc((void**)&d_col, SIZE*sizeof(Complex));
    cudaMemcpy(d_col, h_col, SIZE*sizeof(Complex), cudaMemcpyHostToDevice);

    cufftHandle plan;
    const int BATCH = 1;
    cufftPlan1d(&plan, SIZE, CUFFT_C2C, BATCH);
    cufftExecC2C(plan, d_col, d_col, CUFFT_FORWARD);

    cudaMemcpy(h_col, d_col, SIZE*sizeof(Complex), cudaMemcpyDeviceToHost);

    cudaEventRecord(stop);
    cudaEventSynchronize(stop);
    float milliseconds = 0;
    cudaEventElapsedTime(&milliseconds, start, stop);
    cufftDestroy(plan);
    cout << milliseconds;

    return 0;

代码在同一台计算机上运行,​​具有相同的操作系统、相同的显卡,并且一个接一个地运行。两种情况下的配置都是 x64 Release。您可以选择是使用 C++ 编译器还是 CUDA C/C++ 编译文件。我在两个项目上都尝试了这两种选择,但没有任何区别。

有解决这个问题的想法吗?

FWIW,我在 VS 2013 上使用 Cuda 6.5 得到与 Cuda 7 相同的结果

【问题讨论】:

创建 CUDA 上下文会产生开销,我相信这就是您要测量的内容(我不确定,因为我目前无法访问编译器)。如果您在开始计时以初始化上下文之前放置 cudaFree(0); 行,它的行为是否与预期一致? @Jez,我在cudaEventRecord(start); 之前添加了cudaFree(0),它并没有改变我的时间安排。仍然得到500 ms 大约 【参考方案1】:

cufft 库从 4.2 到 7.0 变得相当大,这导致初始化时间大大增加。如果你去掉这个初始化时间这个因素,我想你会发现执行时间的差异远小于 1000 倍。

这是一个修改后的代码,展示了这一点:

$ cat t807.cu
#include <cufft.h>
#include <cuComplex.h>
typedef cuComplex Complex;
#include <iostream>
using namespace std;
int main(int argc, char* argv[])

    cudaEvent_t start, stop;
    cudaEventCreate(&start);
    cudaEventCreate(&stop);
    cudaEventRecord(start);
    const int SIZE = 10000;
    Complex *h_col = (Complex*)malloc(SIZE*sizeof(Complex));
    for (int i = 0; i < SIZE; i++)
    
        h_col[i].x = i;
        h_col[i].y = i;
    
    Complex *d_col;
    cudaMalloc((void**)&d_col, SIZE*sizeof(Complex));
    cudaMemcpy(d_col, h_col, SIZE*sizeof(Complex), cudaMemcpyHostToDevice);

    cufftHandle plan;
    const int BATCH = 1;
    cufftPlan1d(&plan, SIZE, CUFFT_C2C, BATCH);
    cufftExecC2C(plan, d_col, d_col, CUFFT_FORWARD);

    cudaMemcpy(h_col, d_col, SIZE*sizeof(Complex), cudaMemcpyDeviceToHost);

    cudaEventRecord(stop);
    cudaEventSynchronize(stop);
    float milliseconds = 0;
    cudaEventElapsedTime(&milliseconds, start, stop);
    cufftDestroy(plan);
    cout << milliseconds << endl;

    cudaEventRecord(start);
    for (int i = 0; i < SIZE; i++)
    
        h_col[i].x = i;
        h_col[i].y = i;
    
    cudaMemcpy(d_col, h_col, SIZE*sizeof(Complex), cudaMemcpyHostToDevice);

    cufftPlan1d(&plan, SIZE, CUFFT_C2C, BATCH);
    cufftExecC2C(plan, d_col, d_col, CUFFT_FORWARD);

    cudaMemcpy(h_col, d_col, SIZE*sizeof(Complex), cudaMemcpyDeviceToHost);

    cudaEventRecord(stop);
    cudaEventSynchronize(stop);
    milliseconds = 0;
    cudaEventElapsedTime(&milliseconds, start, stop);
    cufftDestroy(plan);
    cout << milliseconds << endl;

    return 0;

$ nvcc -o t807 t807.cu -lcufft
$ ./t807
94.8298
1.44778
$

上面的第二个数字代表基本上相同的代码,但移除了袖带初始化(因为它是在第一次通过时完成的)。

【讨论】:

太棒了!谢谢克罗维拉先生。这确实使它变得更好。与 Cuda 4.2 相比,它仍然慢约 10-20 倍。这是意料之中的吗? 另外,我看到你的代码执行速度比我的快 5 倍,你能告诉我是怎么做到的吗?我有 GTX Titan,我不知道有任何其他显卡比 Titan 快 5 倍。 准确(也许我应该说可理解)基准测试有时非常棘手,就像剥离层一样。第一大层是袖带初始化时间。下一步可能是了解您的计时区域中每一行代码的贡献——我怀疑实际cufftExecC2C 调用的持续时间并没有太大变化。关于你的时间和我的时间之间的差异,我的猜测是平台差异(windows vs. linux)是问题的症结所在。您的 GTX Titan 是否在托管显示器? WDDM 会使基准测试变得相当棘手。 不,GTX Titan 没有驱动我的显示器。显示器连接到板载图形。那只剩下Windows vs Linux了。 5 倍的差异是惊人的。 与其费力地检查每一行代码以了解差异,不如使用profilers 之一来详细了解正在发生的事情,在每种情况下。例如,通过比较视觉分析器生成的时间线,可能会更清楚为什么存在差异。

以上是关于VS2013/Cuda7.0 中的 CUFFT 比 VS2010/Cuda4.2 慢 1000 倍的主要内容,如果未能解决你的问题,请参考以下文章

CUFFT 错误处理

是否可以在设备函数中调用 cufft 库调用?

为啥 cuda-memcheck racecheck 报告 cufft 错误?

CUDA:如何在 cuFFT 中使用浮点音频数据?

为啥 cufft 的输入输出与传统 fft 有很大不同?

大毕设-CUDA-cuFFT库