任务很简单,将一个整数变量序列写入内存:
原始代码:
for (size_t i=0; i<1000*1000*1000; ++i)
{
data[i]=i;
};
并行化代码:
size_t stepsize=len/N;
#pragma omp parallel num_threads(N)
{
int threadIdx=omp_get_thread_num();
size_t istart=stepsize*threadIdx;
size_t iend=threadIdx==N-1?len:istart+stepsize;
#pragma simd
for (size_t i=istart; i<iend; ++i)
x[i]=i;
};
性能很烂,写1G变量需要1.6秒(uint64
相当于每秒5GB),通过上面代码的简单并行化open mp parallel
(i7 3970 有 6 个线程。
我的设备( i7 3970/64G DDR3-1600)的理论内存带宽是51.2 GB/sec,对于上面的例子,即使通过应用程序,实现的内存带宽也只有理论带宽的1/10左右。 -带宽有界。
有人知道如何改进代码吗?
我在 GPU 上写了很多内存绑定代码,GPU 很容易充分利用 GPU 的设备内存带宽(例如 85% 以上的理论带宽)。
编辑:
该代码由 Intel ICC 13.1 编译为 64 位二进制,并启用了最大优化 (O3) 和 AVX 代码路径以及自动矢量化。
更新:
我尝试了下面的所有代码(感谢 Paul R),没有什么特别的事情发生,我相信编译器完全有能力进行那种 simd/矢量化优化。
至于我为什么要在那里填写数字,长话短说:
它是高性能异构计算算法的一部分,在设备端,该算法效率很高,以至于多GPU集如此之快,以至于我发现性能瓶颈恰好是CPU尝试编写多个序列时记忆中的数字。
当然,知道 CPU 在填充数字方面很糟糕(相比之下,GPU 可以以非常接近的速度填充数字序列( GK110 上的 288GB/秒中的238GB /秒与 51.2GB/秒中的可怜的5GB/秒) CPU)到GPU全局内存的理论带宽),我可以稍微改变一下我的算法,但让我想知道的是为什么CPU在这里填充数字序列时表现如此糟糕。
至于我的设备的内存带宽,我相信带宽(51.2GB)是正确的,根据我的memcpy()
测试,实现的带宽约为理论带宽的80%+(>40GB/秒)。