Jetson TK1 上的 FFT 速度较慢?
FFT is slower on Jetson TK1?
我已经编写了一个用于合成孔径雷达图像处理的 CUDA 程序。计算的重要部分涉及查找 FFT 和 iFFT,我为此使用了 cuFFT 库。我 运行 我的 CUDA 代码在 Jetson TK1 和一台装有 GT635M (Fermi) 的笔记本电脑上,我发现它在 Jetson 上慢了三倍。这是因为 FFT 在 Jetson 上花费了更多时间并且显示较低 GFLOPS/s。我编写的内核的 GFLOPS/s 性能在 Jetson 和 Fermi GT635M 中几乎相同。在 Jetson 上速度较慢的是 FFT。
我观察到的其他分析器参数是:
发出的控制流指令、纹理缓存 T运行sactions、本地内存存储吞吐量 (bytes/sec)、本地内存存储 T运行sactions Per Request 在 Jetson 上很高,而请求的全局负载吞吐量(bytes/sec) 和全局负载 T运行 动作在 Fermi GT635M 上很高。
杰森
GPU 时钟频率:852 Mhz
内存时钟速率:924 Mhz
费米GT635M
GPU 时钟频率:950 Mhz
内存时钟速率:900 Mhz
它们的时钟频率几乎相同。那么为什么 FFT 在 Jetson 上花费更多时间并且显示效果不佳 GFLOPS/s?
为了查看 FFT 的性能,我编写了一个简单的 CUDA 程序,它在大小为 2048 * 4912 的矩阵上执行一维 FFT。这里的数据是连续的,没有跨越。他们花费的时间和GFLOPS/s是:
杰森
3.251 GFLOPS/s 时长:1.393 秒
费米GT635M
47.1 GFLOPS/s 时长:0.211 秒
#include <stdio.h>
#include <cstdlib>
#include <cufft.h>
#include <stdlib.h>
#include <math.h>
#include "cuda_runtime_api.h"
#include "device_launch_parameters.h"
#include "cuda_profiler_api.h"
int main()
{
int numLines = 2048, nValid = 4912;
int iter1, iter2, index=0;
cufftComplex *devData, *hostData;
hostData = (cufftComplex*)malloc(sizeof(cufftComplex) * numLines * nValid);
for(iter1=0; iter1<2048; iter1++)
{
for(iter2=0; iter2<4912; iter2++)
{
index = iter1*4912 + iter2;
hostData[index].x = iter1+1;
hostData[index].y = iter2+1;
}
}
cudaMalloc((void**)&devData, sizeof(cufftComplex) * numLines * nValid);
cudaMemcpy(devData, hostData, sizeof(cufftComplex) * numLines * nValid, cudaMemcpyHostToDevice);
// ----------------------------
cufftHandle plan;
cufftPlan1d(&plan, 4912, CUFFT_C2C, 2048);
cufftExecC2C(plan, (cufftComplex *)devData, (cufftComplex *)devData, CUFFT_FORWARD);
cufftDestroy(plan);
// ----------------------------
cudaMemcpy(hostData, devData, sizeof(cufftComplex) * numLines * nValid, cudaMemcpyDeviceToHost);
for(iter1=0; iter1<5; iter1++)
{
for(iter2=0; iter2<5; iter2++)
{
index = iter1*4912 + iter2;
printf("%lf+i%lf \n",hostData[index].x, hostData[index].y);
}
printf("\n");
}
cudaDeviceReset();
return 0;
}
我的盲目猜测是,尽管 TK1 具有更现代的内核,但专供 635M 的 144 个内核使用的内存带宽明显高于 Tegra。
此外,CUDA 在 warp/thread/grid 大小上总是有点挑剔,因此 cufft 算法完全有可能针对 Fermi 的本地存储大小进行了优化,并且不能与 Keplers 一起使用.
这可能是因为您使用的是 LP(低功耗 CPU)。
检查 this document 以启用所有 4 个主要 ARM 内核(HP 集群)以利用 Hyper-Q。
我遇到了类似的问题。激活主 HP 集群后,我获得了良好的性能(从 3 GFLOPS (LP) 到 160 GFLOPS (HP))。
我已经编写了一个用于合成孔径雷达图像处理的 CUDA 程序。计算的重要部分涉及查找 FFT 和 iFFT,我为此使用了 cuFFT 库。我 运行 我的 CUDA 代码在 Jetson TK1 和一台装有 GT635M (Fermi) 的笔记本电脑上,我发现它在 Jetson 上慢了三倍。这是因为 FFT 在 Jetson 上花费了更多时间并且显示较低 GFLOPS/s。我编写的内核的 GFLOPS/s 性能在 Jetson 和 Fermi GT635M 中几乎相同。在 Jetson 上速度较慢的是 FFT。
我观察到的其他分析器参数是:
发出的控制流指令、纹理缓存 T运行sactions、本地内存存储吞吐量 (bytes/sec)、本地内存存储 T运行sactions Per Request 在 Jetson 上很高,而请求的全局负载吞吐量(bytes/sec) 和全局负载 T运行 动作在 Fermi GT635M 上很高。
杰森
GPU 时钟频率:852 Mhz
内存时钟速率:924 Mhz
费米GT635M
GPU 时钟频率:950 Mhz
内存时钟速率:900 Mhz
它们的时钟频率几乎相同。那么为什么 FFT 在 Jetson 上花费更多时间并且显示效果不佳 GFLOPS/s?
为了查看 FFT 的性能,我编写了一个简单的 CUDA 程序,它在大小为 2048 * 4912 的矩阵上执行一维 FFT。这里的数据是连续的,没有跨越。他们花费的时间和GFLOPS/s是:
杰森
3.251 GFLOPS/s 时长:1.393 秒
费米GT635M
47.1 GFLOPS/s 时长:0.211 秒
#include <stdio.h>
#include <cstdlib>
#include <cufft.h>
#include <stdlib.h>
#include <math.h>
#include "cuda_runtime_api.h"
#include "device_launch_parameters.h"
#include "cuda_profiler_api.h"
int main()
{
int numLines = 2048, nValid = 4912;
int iter1, iter2, index=0;
cufftComplex *devData, *hostData;
hostData = (cufftComplex*)malloc(sizeof(cufftComplex) * numLines * nValid);
for(iter1=0; iter1<2048; iter1++)
{
for(iter2=0; iter2<4912; iter2++)
{
index = iter1*4912 + iter2;
hostData[index].x = iter1+1;
hostData[index].y = iter2+1;
}
}
cudaMalloc((void**)&devData, sizeof(cufftComplex) * numLines * nValid);
cudaMemcpy(devData, hostData, sizeof(cufftComplex) * numLines * nValid, cudaMemcpyHostToDevice);
// ----------------------------
cufftHandle plan;
cufftPlan1d(&plan, 4912, CUFFT_C2C, 2048);
cufftExecC2C(plan, (cufftComplex *)devData, (cufftComplex *)devData, CUFFT_FORWARD);
cufftDestroy(plan);
// ----------------------------
cudaMemcpy(hostData, devData, sizeof(cufftComplex) * numLines * nValid, cudaMemcpyDeviceToHost);
for(iter1=0; iter1<5; iter1++)
{
for(iter2=0; iter2<5; iter2++)
{
index = iter1*4912 + iter2;
printf("%lf+i%lf \n",hostData[index].x, hostData[index].y);
}
printf("\n");
}
cudaDeviceReset();
return 0;
}
我的盲目猜测是,尽管 TK1 具有更现代的内核,但专供 635M 的 144 个内核使用的内存带宽明显高于 Tegra。
此外,CUDA 在 warp/thread/grid 大小上总是有点挑剔,因此 cufft 算法完全有可能针对 Fermi 的本地存储大小进行了优化,并且不能与 Keplers 一起使用.
这可能是因为您使用的是 LP(低功耗 CPU)。
检查 this document 以启用所有 4 个主要 ARM 内核(HP 集群)以利用 Hyper-Q。
我遇到了类似的问题。激活主 HP 集群后,我获得了良好的性能(从 3 GFLOPS (LP) 到 160 GFLOPS (HP))。