是否可以在编译前检查头文件中的 std::execution::par ?

问题描述 投票:0回答:1

我使用的是 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 实际上指的是枚举。不确定是否可以在编译发生之前确定枚举是否存在。对此有什么想法吗?

谢谢!

c++ c++17 libstdc++ libc++
1个回答
0
投票

大家!如果您因编译器不支持 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

© www.soinside.com 2019 - 2024. All rights reserved.