Mac標準のclangでParallel STLを使う

# Mac標準のclangがParallel STLをサポートしていない（2024年1月現在）

表題の通りです。macos Sonoma 14.2.1及びXCode 15.2、Clangのバージョンは15.0.0です。

次のようなParallel STLの計測プログラムを書いてみたのですが、

```cpp:performance_comparison.cpp
#include <algorithm>
#include <execution>
#include <chrono>
#include <vector>
#include <iostream>
#include <random>

int main() {
    // ベクターのサイズ
    const size_t dataSize = 1000000;

    // テストデータの生成
    std::vector<int> data(dataSize);
    std::generate(data.begin(), data.end(), std::rand);

    // Parallel STLを使用しない場合の計測
    auto dataCopy = data;
    auto start = std::chrono::high_resolution_clock::now();
    std::sort(dataCopy.begin(), dataCopy.end());
    auto end = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> elapsed = end - start;
    std::cout << "通常のSTLの実行時間: " << elapsed.count() << " 秒" << std::endl;

    // Parallel STLを使用する場合の計測
    start = std::chrono::high_resolution_clock::now();
    std::sort(std::execution::par, data.begin(), data.end());
    end = std::chrono::high_resolution_clock::now();
    elapsed = end - start;
    std::cout << "Parallel STLの実行時間: " << elapsed.count() << " 秒" << std::endl;

    return 0;
}
```

std::executionなんてないとか言われますね。ご無体な……。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/c18bb507-52f1-8c19-6ad7-b79cf99b45d0.png)

# LLVMプロジェクトからParallel STLの実装をとってくる

仕方がないので、LLVMプロジェクトからpstl(Paralell STL)の実装を取ってきます。

https://github.com/llvm/llvm-project/tree/main/pstl

上記ディレクトリをDownloadして、上記.cppファイルの隣に配置します。

そして、CMakeLists.txtも追加します。

```cmake
cmake_minimum_required(VERSION 3.13)
project(app)
set(CMAKE_C_STANDARD 17)
set(CMAKE_CXX_STANDARD 23)

add_subdirectory(pstl)

add_executable(app "performance_comparison.cpp")

target_link_libraries(app PRIVATE ParallelSTL)
```

add_subdirectoryで先ほど配置したpstlディレクトリを指定します。

## ヘッダファイルの書き換え

実装を置き換えるために、algorithmとexecutionのヘッダファイルを置き換えます。

```cpp:performance_comparison.cpp
// #include <algorithm>
// #include <execution>
#include "pstl/include/__pstl_algorithm"
#include "pstl/include/__pstl_execution"
#include <chrono>
#include <vector>
#include <iostream>
#include <random>
...
```

cmakeとmakeを実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/64306cd4-b1b2-bc46-be95-ae8f9d2beeb0.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/535762de-173f-629c-0a48-3ada27ea4e2b.png)

さて、実行してみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/8043f31a-3883-409f-dbb4-b5d3ff8cc4f7.png)

あ、あれ？ Parallel STL版の方が遅い？
実は、標準ではシリアル実行になっていて、全く速くなりません。
バックエンドにOpenMPかTBBを指定できるようになっています。それらを指定しないと速くならないのですね。

## TBBをバックエンドに指定する

OpenMPの方は色々試しましたがうまくいかなかったので、TBBを利用することにします。

homebrewでTBBをインストールします。

```bash
$ brew install tbb
```

CMakeで`PSTL_PARALLEL_BACKEND`を`tbb`に指定します

```cmake
cmake_minimum_required(VERSION 3.13)
project(app)
set(CMAKE_C_STANDARD 17)
set(CMAKE_CXX_STANDARD 23)

set(PSTL_PARALLEL_BACKEND tbb) # ←追加

add_subdirectory(pstl)

add_executable(app "performance_comparison.cpp")

target_link_libraries(app PRIVATE ParallelSTL)

```

CMakeを実行すると、TBBをバックエンドに使う旨が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/bd4d3084-f641-e822-8010-0fe5c6755650.png)

makeして実行すると……

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12753/d04214b4-75da-00c3-6526-6681b095cc30.png)

速くなってますね。2倍程度だとちょっと物足りないけど。もう少し大きいサンプルでも試してみたいところです。

# 最後に

LLVMプロジェクトのpstl実装を利用することで、現行のMacでもParallel STLが使えることを確認できました。
READMEを見る限り、まだ制約も多いようなので個人的にはあくまで練習用に使うつもりですが、この記事がお役に立てれば幸いです。

そして、LLVMのpstlの存在を教えてくれたMehmet Oguz Derinさんに感謝します。