c++ - OpenMP 线性加速

标签 c++ openmp

我有这个简单的代码来测试分配了更多内核的加速次数,但是我没有观察到线性加速。

int main() {
    using u64_t = unsigned long long;
    u64_t n = 1e9;
    u64_t* a = new u64_t[n];
    #pragma omp parallel for
    for (u64_t i=0; i<n; ++i) {
        a[i] = i;
    }
}

编译成'g++ -fopenmp -O3 test.cpp',然后

export OMP_NUM_THREADS=1  # time cost = 4.485s
export OMP_NUM_THREADS=2  # time cost = 2.916s
export OMP_NUM_THREADS=3  # time cost = 2.571s
export OMP_NUM_THREADS=4  # time cost = 2.347s

为什么没有线性加速?

更新

系统环境如下

enter image description here

此外,htop 给了我 4 个线程,我怀疑如果启用了超线程,可能只有 2 个物理内核。

我使用 time ./a.out 测量速度,使用 gnu g++-7 编译。

跟进

现在我稍微改了一下代码,如下

int main() {
    using u64_t = unsigned long long;
    u64_t n = 1e9;
    u64_t a[7];
    #pragma omp parallel for
    for (u64_t i=0; i<n; ++i) {
        a[i%7] = i;   // a is an array, I know there might be data race here
    }
    cout << a[0] << "," << a[6];
}

我测试了上面的代码,但是现在omp版本(2.1s)比串行版本(1.2s)慢,为什么?

最佳答案

此代码主要受内存带宽的限制,因为您为每个操作写入一个值。通常,内存带宽小于所有内核并行使用的带宽。

对内存饱和度进行数学计算有点偏离规范。 你的系统可能有一个 i5-5257U在这种配置下,它应该有 25.6 GB/s 的内存带宽。您只能写入 3.4 GB/s - 对于写入,您实际上经常使用两倍,因为每次写入都首先需要从内存中读取缓存行。所以在 6.8 GB/s 和理论带宽之间还有很大的进步,但这并非闻所未闻。我无法重现这个,因为我没有相同的硬件。要进行更详细的分析,必须深入研究生成的指令和硬件性能计数器。

一些补充说明:

  • 我听说 apple 有时会将 gcc 别名化为 clang,这可能会产生误导。
  • 您应该在循环之后对 a 做一些事情,以防止编译器优化它。
  • 您的时间测量包括应用非并行设置和新...,因此您受到严重影响Amdal's law .考虑使用 omp_get_wtime() 仅对并行部分进行计时。

总而言之,您的处理器只有两个内核(四个硬件线程),无论如何您都不应该期望超过两个线程的加速。

关于c++ - OpenMP 线性加速,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49607021/

相关文章:

c++ - 就地构造函数 std::vector

c++ - 在模块之间传递对象的替代方法

java - 从 C/C++ 执行交互式 CLI 应用程序

c - 解决在R中使用OpenMP时的封闭并行错误

c++ - 如何使用 C++11 正则表达式将字符串与通配符匹配

c++ - 大型 JPEG/PNG 图像序列循环

c++ - MPI 大小和 OpenMP 线程数

我可以将多个有序语句放入一个有序 for 循环 (OpenMP) 中吗?

c - 嵌套循环、内循环并行化、重用线程

c++ - 如何在多线程 C++ 中实现 "soft barrier"