You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何std::transform_reduce在MacOS下用std::execution::par无并行加速?

问题排查:std::transform_reduce并行策略未实现预期加速

环境与背景

  • 设备:Intel MacBook Pro(MacOS Sonoma)
  • 编译器:Homebrew安装的GCC 13.2(Xcode自带Clang未实现C++17并发部分)
  • 测试场景:基于C++20标准,对比std::transform_reduce使用std::execution::par并行策略与std::execution::seq串行策略的累加任务耗时

问题现象

测试大数值范围的立方累加任务时,并行策略与串行策略耗时接近(均约4.6秒),未获得预期的并行加速效果。已尝试链接Intel TBB,问题仍未解决。

测试代码

#include <chrono>
#include <algorithm>
#include <execution>
#include <ranges>
#include <iostream>
#include <thread>


template <typename EP>
inline void timed_effort (
  const std::string& label,
  EP&& execution_policy,
  const std::ranges::iota_view<unsigned long, size_t>& interval,
  size_t quantum
) {
  using namespace std::chrono;
  auto start = system_clock::now ();
  
  auto result_par = std::transform_reduce (
      execution_policy,
      interval.begin (), interval.end (),
      0ul,
      std::plus {},
      [&] (size_t i) -> size_t {
          auto inc = std::ranges::views::iota (i * quantum, (i + 1) * quantum);
          auto sum = std::accumulate (
            inc.begin (), inc.end (), 0ul, 
            [&] (size_t acc, size_t x) -> size_t { 
              return acc + x * x * x;  
            });

          return sum;
      });
  
  auto end = system_clock::now ();
  duration <double, system_clock::period> time = end - start;
  std::cout << label << " = " 
            << result_par << " in " 
            << duration_cast <milliseconds> (time).count () 
            << " ms." << std::endl;
}


int main (int argc, char* argv []) {
  using namespace std::chrono;

  std::cout << "Testing " << std::thread::hardware_concurrency() << " execution cores." << std::endl;

  auto length = 10000000000ul;
  auto split = 5ul;
  auto quantum = length / split;
  auto interval = std::ranges::views::iota (0ul, split);

  timed_effort (
    "Parallel execution",
    std::execution::par,
    interval,
    quantum
  );
  
  timed_effort (
    "Sequenced execution",
    std::execution::seq,
    interval,
    quantum
  );
  
  return 0;
}

CMakeLists.txt

cmake_minimum_required (VERSION 3.27)

project (
  example

  VERSION 1.0
  LANGUAGES CXX
)

message(status "Setting GCC flags and making sure we really have a gcc compiler.")

set(CMAKE_C_COMPILER "gcc-13")
set(CMAKE_CXX_COMPILER "/usr/local/bin/g++-13")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -std=c++20 -O3 -pthread")
message(status "** CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")

add_executable (
  example

  source/example.cpp
)

SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/bin")

排查建议

  • 确保并行库正确链接:GCC的并行算法依赖后端并行库,仅添加-pthread不足以启用并行。需显式链接TBB,先通过brew install tbb安装,再修改CMakeLists.txt:
    find_package(TBB REQUIRED)
    target_link_libraries(example PRIVATE TBB::tbb)
    
  • 调整任务粒度:当前仅拆分5个任务分片,远少于Intel MacBook Pro的核心数(通常≥8),无法充分利用多核资源。尝试将split值设为硬件核心数或其倍数,让每个线程处理更小的任务单元。
  • 检查编译器并行支持:GCC 13.2对C++20并行算法的支持可能需显式启用选项,尝试添加-ltbb或-fopenmp(若使用OpenMP后端),编译时确认无链接警告。
  • 优化负载均衡:当前分片逻辑可能因length % split != 0导致最后一个分片负载不均,调整分片逻辑确保各任务负载相近。
  • 验证并行策略生效:当前std::accumulate中的立方计算可能被编译器优化为向量运算,串行版本已接近硬件极限。可在计算中加入少量内存访问(如访问全局数组)模拟真实负载,验证并行策略是否实际启用。

内容的提问来源于stack exchange,提问作者Etuka Onono

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 05:07:31