【问题标题】:Why is my parallel std::for_each only using 1 thread?为什么我的并行 std::for_each 只使用 1 个线程?
【发布时间】:2021-04-28 04:18:32
【问题描述】:

我正在尝试并行化这段 C++ 代码(计算点的连续傅里叶变换,建模为狄拉克脉冲),这段代码编译并正常工作,但它只使用 1 个线程。我还需要做些什么来让多个线程工作吗?这是在具有 4 个内核(8 个线程)的 Mac 上,使用 GCC 10 编译的。

vector<double> GetFourierImage(const Point pts[],
                               const int num_samples,
                               const int res,
                               const double freq_step) {
  vector<double> fourier_img(res*res, 0.0);
  double half_res = 0.5 * res;

  vector<int> rows(res);
  std::iota(rows.begin(), rows.end(), 0);
  std::for_each(  // Why doesn't this parallelize?
      std::execution::par_unseq,
      rows.begin(), rows.end(),
      [&](int i) {
    double y = freq_step * (i - half_res);
    for (int j = 0; j < res; j++) {
      double x = freq_step * (j - half_res);

      double fx = 0.0, fy = 0.0;
      for (int pt_idx = 0; pt_idx < num_samples; pt_idx++) {
        double dot = (x * pts[pt_idx].x) + (y * pts[pt_idx].y);
        double exp = -2.0 * M_PI * dot;
        fx += cos(exp);
        fy += sin(exp);
      }
      fourier_img[i*res + j] = sqrt((fx*fx + fy*fy) / num_samples);
    }
  });

  return fourier_img;
}

【问题讨论】:

  • 我还没有确定这个,但是完全有可能gcc还没有实现std::execution::par_unseq,这听起来是这样的。该符号已定义,但它……什么都没有。
  • par_unseq 告诉编译器它可以使用并行,但必须使用。谷歌搜索,我发现了一个邮件列表条目(2017),它谈到了par_unseq#pragma omp 之上的初步实现。如果该实现已合并到 gcc 10 中,您可能必须启用 OpenMP 才能使其工作。查看gcc.gnu.org/gcc-9/changes.html,您似乎需要std::execution 的“线程构建块”(无论是什么)
  • 哦,嗯,好的,谢谢你们。我安装了线程构建块(TBB)并将 -ltbb 添加到我应该链接它的编译命令中,但它似乎仍然没有使用多个线程......
  • 您要迭代多少个项目?如果数量很少,t 可能不会费心启动新线程。
  • @Andrew So HAL 提到了 OpenMP 和 TBB。你只提到了TBB。是不是看不懂,错过了,还是?

标签: c++ foreach parallel-processing c++17


【解决方案1】:

在 GCC 9 中,使用不同的执行策略时对 TBB 存在硬依赖,如果不存在,则构建将失败。这在 GCC 10(并且出现在 GCC 11)中发生了变化,如果库不存在,那么 for_each 将默认为顺序循环。这可以在https://github.com/gcc-mirror/gcc/blob/releases/gcc-10.1.0/libstdc++-v3/include/bits/c++config#L679 看到。要解决您的问题,请尝试使用-ltbb 链接到 TBB。这解决了您在使用 GCC 11.2 的 Ubuntu 20.04 上遇到的相同问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    • 1970-01-01
    • 1970-01-01
    • 2011-01-03
    • 1970-01-01
    • 2019-12-19
    • 1970-01-01
    相关资源
    最近更新 更多