为何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
相关产品推荐
相关产品推荐

