繁体   English   中英

使用 openMP 在向量 c++ 对象上并行化循环

[英]Using openMP to parallelize a loop over a vector c++ objects

我正在尝试使用 openMP 提高 c++ 代码的性能,但没有看到很好的缩放。 在深入研究我的代码的细节之前,我有一个非常笼统的问题,如果我能得到一个明确的答案,我认为可以节省很多时间。

代码的基本结构是一个对象向量(假设大小为num_objs = 5000),其中每个对象拥有一个相对较小的双精度向量(假设大小为num_elems = 500)。 我想遍历这个对象向量,对于每个对象,在成员向量上执行一个子循环来修改每个元素。 我只是试图并行化外循环(在对象上),因为这是 openMP 的标准方法,而且这个循环比嵌套循环大得多。

所以现在我的问题。 我是否通过循环遍历对象数组然后遍历每个较小的成员向量来严重影响性能? 如果我改为创建一个大小为num_objects * num_elems 的大向量,然后对该大向量的“块”进行并行循环,这些大向量将对应于存储在我上面描述的每个对象中的成员向量,我是否应该期望性能显着提高? 这样外循环和内循环都将从一个大向量访问数据,而不必从单独的对象中获取数据?

实际代码比上面描述的要复杂得多,因此为了尝试这种替代方法需要大量时间修改。 因此,我只是想感受一下,如果我花时间重构整个代码,我可以获得多大的加速。 我对计算机体系结构、内存访问、缓存等方面的知识并不多,所以如果这很明显,我深表歉意。

编辑:我在想这可能有一个简单的答案; 然而,我发现情况并非如此。 请考虑以下(简化示例)。

#include <cmath>
#include <ctime>
#include <iostream>
#include <omp.h>
#include <string>
#include <vector>

class Block {
public:
  static double a;
  std::vector<double> x;
  std::vector<double> y;
  Block(int N);
};

double Block::a = 5;

int main(int argc, char const *argv[]) {
  int num_blocks = 80000;
  int num_elems = 1000;
  int num_iter = 100;

  int nthreads = 1;
  bool parallel_on = true;

  omp_set_num_threads(nthreads);

  std::vector<Block> block_vec;

  for (int i = 0; i < num_blocks; i++) {
    block_vec.push_back(Block(num_elems));
  }

  double start;
  double end;
  start = omp_get_wtime();

  int iter = 0;

  while (iter < num_iter) {
#pragma omp parallel for if (parallel_on)
    for (int bl = 0; bl < num_blocks; bl++) {
      for (int i = 0; i < num_elems; i++) {
        block_vec[bl].x[i] = Block::a * block_vec[bl].y[i] + block_vec[bl].x[i];
      }
    }
    iter++;
    std::cout << "ITER: " << iter << std::endl;
  }

  end = omp_get_wtime();
  double time_taken = end - start;
  std::cout << "TIME: " << time_taken << std::endl;

  return 0;
}

Block::Block(int N) {
  x.assign(N, 2.0);
  y.assign(N, 3.0);
}

我编译这个程序:

g++ -fopenmp -O3 saxpy.cpp

我在 i7-6700 CPU @ 3.40GHz(四个物理内核和八个逻辑内核)上运行它。 以下是不同线程数的计算时间:

1 线程:8.65 秒
2线程:7.37s
3线程:7.41s
4线程:7.65s

我确实尝试了上述代码的一个版本,它使用一个大向量而不是嵌套循环; 然而,它的结果大致相同,实际上慢了一点。

你的程序的速度主要取决于内存读/写的速度(包括缓存利用率等)。 根据硬件,您可能会或可能不会观察到速度增加。 有关更多详细信息,请阅读例如这个

在我的笔记本电脑(i7-8550U,g++ -fopenmp -O3 -mavx2 saxpy.cpp)上我得到了类似的结果,但在至强服务器上我得到了显着的速度提升:

nthreads=1     
TIME: 13.0372
real    0m14.303s
user    0m13.206s
sys     0m1.096s

nthreads=4
TIME: 5.1537
real    0m5.921s
user    0m18.473s
sys     0m0.615s

nthreads=8
TIME: 3.43479
real    0m4.237s
user    0m27.337s
sys     0m0.608s

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM