为了将巨大的双数组复制到另一个数组,我有以下两个选项:
copy(arr1, arr1+N, arr2);
#pragma omp parallel for
for(int i = 0; i < N; i++)
arr2[i] = arr1[i];
我想知道一个大的N值。以下哪个更好(花费更少的时间)选项和什么时候?“
系统配置:
记忆:15.6 GiB
处理器:英特尔®酷睿™i5-4590 CPU @ 3.30GHz×4
操作系统类型:64位
编译器:gcc(Ubuntu 4.9.2-0ubuntu1~12.04)4.9.2
答案 0 :(得分:1)
实际,如果表现很重要,请进行衡量。
std::copy
和memcpy
通常都经过高度优化,using sophisticated performance tricks。您的编译器可能或者可能不够聪明/有正确的配置选项来从原始循环中获得该性能。
那说,理论上,并行化副本可以提供一个好处。在现代系统上,您必须使用多个线程来充分利用内存和缓存带宽。看一下these benchmark results,其中前两行比较并行与单线程缓存,最后两行是并行与单线程主内存带宽。在像您这样的桌面系统上,差距不是很大。在面向高性能的系统中,尤其是具有多个套接字的系统,更多线程对于利用可用带宽非常重要。
对于最佳解决方案,您必须考虑不要从多个线程写入相同的缓存行。此外,如果您的编译器没有从原始循环生成完美的代码,您可能必须在多个线程/块上实际运行std::copy
。在我的测试中,原始循环执行得更糟,因为它没有使用AVX。只有英特尔编译器设法用avx_rep_memcpy
实际替换OpenMP循环中的部分 - 有趣的是它没有使用非OpenMP循环执行此优化。内存带宽的最佳线程数通常也不是内核数,而是更少。
一般建议是:从一个简单的实现开始,在本例中是惯用的std::copy
,然后分析您的应用程序以了解瓶颈实际上在哪里。不要投资复杂,难以维护,特定于系统的优化,这些优化可能只会影响整个运行时代码的微小部分。如果事实证明这是您的应用程序的瓶颈,并且您的硬件资源利用率不高,那么您需要了解底层硬件(本地/共享缓存,NUMA,预取程序)的性能特征并相应地调整您的代码。 / p>
答案 1 :(得分:0)
选项1更好。
RAM是一种共享资源,您不能简单地并行化它。当一个核心使用RAM时,其他核心会等待。
此外,RAM通常比CPU-RAM频率低于CPU频率慢,所以在上面的情况下,即使是单核也有等待RAM的周期。
您也可以考虑复制memcpy()
,它可能比std::copy()
更快。它通常取决于实施。
最后但不要以及始终衡量。首先,只需在您正在测量的代码之前和之后放置omp_get_wtime()
,然后查看差异。