【发布时间】:2021-04-06 07:41:40
【问题描述】:
我想并行化一个 for 循环,发现了 std::for_each 以及它的 execution policies。令人惊讶的是它在使用GCC 时没有并行化:
#include <iostream>
#include <algorithm>
#include <execution>
#include <chrono>
#include <thread>
#include <random>
int main() {
std::vector<int> foo;
foo.reserve(1000);
for (int i = 0; i < 1000; i++) {
foo.push_back(i);
}
std::for_each(std::execution::par_unseq,
foo.begin(), foo.end(),
[](auto &&item) {
std::cout << item << std::endl;
std::random_device dev;
std::mt19937 rng(dev());
std::uniform_int_distribution<std::mt19937::result_type> dist6(10, 100);
std::this_thread::sleep_for(std::chrono::milliseconds(dist6(rng)));
std::cout << "Thread ID: " << std::this_thread::get_id() << std::endl;
});
}
此代码仍按顺序运行。
使用MSVC,代码被并行化并且完成得更快。
GCC:
$ gcc --version
gcc (Ubuntu 10.1.0-2ubuntu1~18.04) 10.1.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
MSVC:
>cl.exe
Microsoft (R) C/C++ Optimizing Compiler Version 19.27.29112 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
usage: cl [ option... ] filename... [ /link linkoption... ]
CMakeLists.txt:
cmake_minimum_required(VERSION 3.17)
project(ParallelTesting)
set(CMAKE_CXX_STANDARD 20)
add_executable(ParallelTesting main.cpp)
我还需要做些什么来启用GCC 的并行化吗?
ldd 我的二进制输出:
$ ldd my_binary
linux-vdso.so.1 (0x00007ffe9e6b9000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f79efaa0000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f79ef881000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f79ef4ad000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f79ef295000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f79eeea4000)
/lib64/ld-linux-x86-64.so.2 (0x00007f79f041a000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f79eeb06000)
二进制整体的debug 和release 版本具有相同的ldd 输出。
【问题讨论】:
-
您是否尝试过更改 GCC 的优化级别?我对 cppreference 文档的阅读表明,当指定
par_unseq时,允许并行化,而不是必需的。 -
Libstdc++(可能被您的 GCC 使用)没有自己的并行算法版本。相反,它使用英特尔 TBB 作为后端。 TBB 是否与您的计划相关联? Libstdc++ 也可以配置为使用串行后端,有关更多详细信息,请查看此处:github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/…。
-
@Dr.Watson:使用完全优化进行编译也无济于事。丹尼尔,我使用的是“常规”
GCC 10版本,所以我不确定它是如何具体配置的,以及TBB是否与它相关联。我将二进制文件的ldd输出添加到问题中以供进一步调查。 -
@BullyWiiPlaza,我认为丹尼尔的想法是正确的。 cppreference 库功能支持page 表明GCC 仅在使用-ltbb 编译时支持Parallelism TS。因此,您需要在项目中的某个位置使用
tbb库,然后您需要add_library和target_link_libraries,就像任何其他库一样。 -
sudo apt-get install libtbb-dev然后链接-ltbb,否则你会得到未定义的符号。
标签: c++ gcc visual-c++ parallel-processing c++20