我使用的是 Mac Ventura 13.6.4。当我在线研究
<execution>
标头时,我了解到在尝试编译某些执行策略时存在问题。例如,对于 clang,我发现 c++ 17 目前不支持使用 std::execution::par
,我相信是因为 clang 中进行了切换以使用 libc++ 而不是 libstdc++。这意味着 apple clang 目前不支持其他编译器支持的执行策略。注意下图中的红框:
https://en.cppreference.com/w/cpp/compiler_support/17#C.2B.2B17_library_features
目前,我们有一些代码可以用 gcc 和 minggw 很好地编译,因为它们维护了 libstdc++。然而,当尝试使用较新的 Mac 系统进行编译时,特别是当尝试使用系统 clang 或系统 gcc(指向 clang)时,我们会遇到错误。例如,以下是我们在 Ventura 13.6.4 上尝试使用系统 gcc 或系统 clang 编译包含 std::execution::par 的代码时遇到的错误:
代码:
#include <vector>
#include <algorithm>
#include <execution>
int main(){
std::vector<int> vec = {1, 2, 3, 4, 5, 10, 20, 4 };
std::sort(std::execution::par, vec.begin(), vec.end());
}
我的系统 clang 是 clang 版本 14.0.3。这是我提供给编译器的参数和收到的错误(放置 ... 表示不重要的长编译器参数):
clang -std=c++17 -stdlib=libstdc++ ...
错误:
clang: warning: include path for libstdc++ headers not found; pass '-stdlib=libc++' on the command line to use the libc++ standard library instead [-Wstdlibcxx-not-found]
: fatal error: 'cstddef' file not found
#include <cstddef>
^~~~~~~~~
当我更改代码以包含 libc++ 时,我收到另一个错误(还添加 ... 来表示不重要的长编译器参数):
clang -std=c++17 -stdlib=libc++ ...
编译器错误:
no member named 'par' in 'std::exception'
我认为这可能与较旧版本的 clang 有关,因此我从 brew 安装了 llvm 并获得了 18 版的 clang。
当我用 llvm 运行它时,我得到了相同的编译器错误
no member named par in 'std::excecution'
。
有趣的是,当我使用从自制软件下载的 g++-13 构建时,我可以很好地编译代码。我发现 libstdc++.dylib 位于 g++-13 的 lib 文件夹中,所以我认为这就是原因。它要么链接它并找到执行策略,要么在随编译器安装的执行头中找到它。
因此,为了解决这个问题,我们正在考虑尝试以某种方式识别 cpp 中使用的特定编译器,并定义几种不同的构建方法。我很好奇是否有办法确定标题中是否存在该策略。
目前,我们知道您可以查看标头是否存在。例如,我见过使用
__has_include(...)
的实现
#if __has_include(<execution>)
#include <execution>
#define EXECUTION_POLICY
#endif
#ifdef EXECUTION_POLICY
// To use sequential processing, change "par" to "seq".
std::sort(std::execution::par, vec.begin(), vec.end());
#else
// Some compilers have not implemented execution policies.
std::sort(vec.begin(), vec.end());
是否可以判断文件头中是否存在执行策略?据我了解,maveric 10.9 之前的版本,libstdc++ 仍然存在。
我正在寻找一个函数,或者某种类似的实现:
#look for the execution header
#if the execution header exists, look for 'par'
#if par exists, define EXECUTION_POLICY
#if par does not exist, run the code without the parallel policy
我们认为,我们可以接受某些 Mac 不具备 std::execution::par 的并行化功能。例如,如果我们重写代码以取出执行策略,它仍然可以正常编译和运行。
我们想要做的是保持旧版 Mac 系统使用执行策略的能力,因为它们可以访问 libstdc++(如果我理解正确的话)。基本上,我正在寻找一种方法来让我们看看
std::execution::par
是否存在。据我了解, std::execution::par 实际上指的是枚举。不确定是否可以在编译发生之前确定枚举是否存在。对此有什么想法吗?
谢谢!
大家!如果您因编译器不支持 std::execution::par 而难以让 std::execution::par 工作,只需创建一个 ifdef 来查找 __cpp_lib_execution。例如,
#if __has_include(<execution>) //checking to see if the <execution> header is there
#include <execution>
#endif
#ifdef __cpp_lib_execution
// do parrallel processing
for_each(execution::par, range.begin(), range.end(),
#else
// Some compilers have not implemented execution policies, so don't.
for_each(range.begin(), range.end(),
#endif