CPU与GPU计算能力比较

本文对比几个算法分别在CPU上计算,与GPU上计算的耗时。

测试环境:

CPU: Intel(R)_Core(TM)_i7-7700_CPU_@_3.60GHz x 8

GPU: NVIDIA GeForce GTX 1050

一,FFT计算的性能分析。

1,dft离散傅里叶变换的公式如下。

X为源数据,一个复数数组。Y = dft(X) 和 X = ifft(Y) 分别表示傅里叶变换和傅里叶逆变换。假设X的数据个数为n, 那么Y的数据个数也是n,计算公式如下:

正变换:Y(k)=\sum_{j=1}^{n}X(j)W_{n}^{(j-1)(k-1)}

逆变换:X(j)=\frac{1}{n}\sum_{k=1}^{n}Y(k)W_{n}^{-(j-1)(k-1)}

其中,W_{n}=e^{-(2\pi i)/n}=cos(2\pi i/n)-sin(2\pi i/n)

 

2,对于1024个浮点复数,进行一维DFT变换。在保证计算结果正确一致的前提下,比较计算速度。

计算20次,将运行时间累加再计算平均值。得出如下统计结果:

其中,opencv是在CPU上进行多核并行计算的。cufftlib在GPU上计算,但是没有将数据拷贝耗时计算在内。可以看出,GPU上计算的花费时间,是CPU上的一半。

3,对于1024x1024的图像数据,进行2维DFT计算。在确保计算结果正确一致的前提下,比较计算速度(计算耗时)。

计算20次,将运行时间累加再计算平均值。得出如下统计结果:

可以看出,cufftlib 计算的耗时远远小于opencv的计算耗时,15us vs. 6ms,相差400倍,这个性能提升还是很可观的。

测试代码可以参考:https://gitee.com/yt2014/cuda-programs/tree/master/fft

4,这个里面有个问题,cufftPlan1d 和cufftPlan2d,这两个函数的运行都很耗时。对于1024x1024大小的计算来说,cufftPlan2d耗时可达168ms。这个操作,在fft的长度确定之后,只需要运行一次,所以对于特定的应用程序来说,可以在应用运行起来之时,执行一次,后面运行就很快了。

 

二,最大最小值计算的性能分析。

  1. 在CPU上使用串行计算,1024x1024的图像数据(8位无符号),依次遍历每个数据,进行比较,保存最大值和最小值。
  2. 在第一种方式的基础上,使用openmp进行并行化处理。
  3. 使用GPU进行计算,主要采用先分段计算,再归约的计算方法。

代码可以参考https://gitee.com/yt2014/cuda-programs/tree/master/max_min

对于以上3种方式,在保证结果正确一致的情况下,比较计算耗时,分别计算20次,然后计算各自的平均耗时。结果如下:

CPU与GPU计算能力比较_第1张图片

4,可以看出,

    4.1在CPU上使用omp进行并行化,计算性能最好,花费629微秒;

    4.2 其次是cuda GPU,花费717微秒;

    4.3 花费时间最多的是CPU串行计算,花费2.11毫秒。

5,这个里面GPU跟omp相比,没有优势,因为计算最大最小值的时候,需要将每个数据与其它数据进行比较,或者是与相邻的数据比较,或者是与临时最大值最小值进行比较,更新最大最小值时还需要进行同步。使得这个计算,只能在小局部内并行,最后还是需要归约。而CPU上omp计算时,多个线程间对共享资源的更新,要快很多。

 

三,图像滤波计算性能分析

1.图像滤波是指,使用特性的滤波核,在图像矩阵中移动,对应的计算图像中与核矩阵重叠部分与滤波核矩阵的点乘,将结果保存到图像部分矩阵的中心点。滤波核一般是小的矩阵,对于sobel滤波来说,滤波核如下:

-1 -2 -1         -1 0 1

0 0 0    以及   -2 0 2

1 2 1           -1 0 1

分别对应y方向上的二阶导,和x方向上的一阶导

2.使用1024x1024的图像进行sobel滤波计算,

    2.1 使用opencv在CPU上进行计算,

    2.2 使用cuda GPU进行计算,

      代码可以参考:https://gitee.com/yt2014/cuda-programs/tree/master/sobel    

      在保证计算结果正确一致的前提下,比较计算耗时。分别计算20次,然后计算平均值,计算结果如下:

    2.3 如果不把GPU的数据拷贝时间考虑在内,运行结果如下:

    2.4 如果计算拷贝时间,将结果数据从GPU拷贝回主机的时间 计算在内,那么运行结果如下:

3. 可以看出,如果不考虑GPU和主机之间的数据传输时间,GPU的计算性能还是很有优势,这是因为对于这个滤波计算,各个像素的计算可以实现完全的并行化,计算的结果之间没有依赖性。所以计算性能就有很大提升。

4.但是如果考虑数据传输时间,GPU计算耗时将比CPU计算耗时更长。所以在实际程序中,要考虑怎样避免数据传输(拷贝)时间影响程序的整体性能,主要的做法有,

    4.1 让尽量多的计算在GPU上运行,让GPU的计算工作量远远大于拷贝传输数据的工作量,而且不要频繁的拷贝传输,这样就让拷贝传输耗时在整体耗时中占比减小,从而对整体性能影响不大。一个极端的情况就是,整个程序的计算都在GPU上进行,在开始的时候,将数据拷贝传输到GPU,然后所有计算都在GPU上进行,最后将结果拷贝回主机。

    4.2 在CPU上启动多线程,一个线程在拷贝的过程中,另一个线程在执行计算,这样,计算与拷贝的时间就重合了,消除了一部分耗时。

    4.3 使用cuda GPU中流(stream)的机制,对GPU的操作,使用异步方式,在一个流进行拷贝的时候,另一个流进行计算。

 

 

你可能感兴趣的:(CPU与GPU计算能力比较)