Reputation: 137
I am on a Mac Ventura 13.6.4. When I research online about the <execution>
header, I am learning that there is an issue when trying to compile some of the execution policies. For example, with clang, I am seeing that using std::execution::par
is currently not supported for c++ 17, I believe because there was a switch made in clang to use libc++ instead of libstdc++. This means that apple clang does not currently support the execution policies that other compilers would support. Note the red box shown in the following chart:
https://en.cppreference.com/w/cpp/compiler_support/17#C.2B.2B17_library_features
Currently, we have some code that compiles fine with gcc and minggw because they have maintained libstdc++. However, we get errors when trying to compile with newer Mac systems, particularly when trying to use a system clang, or a system gcc (which points to clang). For example, here is the error we get on Ventura 13.6.4 when trying to compile some code containing std::execution::par with system gcc or system clang:
code:
#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());
}
My system clang is clang version 14.0.3. Here is the argument I provide to the compiler and the error received (putting ... to signify long compiler args that are unimportant):
clang -std=c++17 -stdlib=libstdc++ ...
The error:
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>
^~~~~~~~~
When I change the code to include libc++, I get another error (also putting ... to signify long compiler args that are unimportant):
clang -std=c++17 -stdlib=libc++ ...
The compiler error:
no member named 'par' in 'std::exception'
I thought this might have to do with a younger version of clang than what is out there, so I installed llvm from brew and got a version 18 of clang.
When I ran it with llvm, I got the same compiler error no member named par in 'std::excecution'
.
What is interesting, is that when I build with g++-13 that I downloaded from homebrew, I can compile the code fine. I found that the libstdc++.dylib is in the lib folder for g++-13 so I think this is why. Either it is linking against that and finding the execution policy, or it found it in the execution header installed with the compiler.
Therefore, to solve this problem, we are thinking about trying to identify the specific compilers being used in cpp some way and define a couple different ways to build. I am curious if there is a way to determine if the policy exists in the header.
Currently, we are aware that you can see if the header exists. For example, I have seen implementations with __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());
Is it possible to determine if an execution policy exists in the file header instead? From what I understand, pre-maveric 10.9, libstdc++ still exists.
I am looking for a function, or perhaps some kind of implementation that would be like:
#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
We are thinking that we are ok with some Mac's not having the parallelization capabilities with std::execution::par. For example, if we rewrite the code to take out the execution policy, it still compiles and runs fine.
What we would like to do, though is maintain the capability for older Mac systems to use the execution policy, since those have access to libstdc++ (if I am understanding correctly). Basically, I am looking for a way to allow us to see if std::execution::par
exists. From what I understand, std::execution::par actually refers to an enum. Not sure if it is possible to just determine if the enum exists as well before the copilation occurs. What are some thoughts on this?
Thanks!
Upvotes: 0
Views: 534
Reputation: 137
If you are struggling to get std::execution::par to work because it is not supported on your compiler, just create an ifdef
to look for the __cpp_lib_execution
.
For example:
#if __has_include(<execution>) //checking to see if the <execution> header is there
#include <execution>
#endif
#ifdef __cpp_lib_execution
// do parallel 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
Upvotes: 4