oneTBB をソースファイルからビルドする
概要
oneAPI Threading Building Blocks(oneTBB) を git リポジトリのソースファイルからビルドする方法をまとめます。
こういうのに慣れておらず苦戦したので残しておきます。
vcpkg でインストールできるらしいのですが、自分の環境ではうまくいかず…。
基本的には Installation from Sources や README for the CMake build system の内容に沿って進めるだけです。
環境
私の環境は以下の通りです。同じ Windows でも Visual Studio の場合や、Linux など OS が異なる場合は手順が違うかもしれません。
- GCC (Mingw-w64 12.2.0)
- Windows 10 Home 64bit
- CMake 3.24.0
- Ninja 1.11.0
- hwloc 2.8
ビルド手順
まず、oneTBB の Git リポジトリからクローンしてきます。
> git clone https://github.com/oneapi-src/oneTBB.git
> cd oneTBB
ビルド用のディレクトリを作ってそこに移動します。名前はなんでもよいです。
> mkdir build
> cd build
CMake でビルドルールを生成します。自分は Ninja を使っているのでジェネレータに Ninja
を指定しています。
> cmake \
-GNinja
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=C:\cbw\tbb \
-DTBB_STRICT=OFF \
-DTBB_TEST=OFF \
-DCMAKE_HWLOC_2_5_LIBRARY_PATH=C:\cbw\hwloc\lib\libhwloc.lib \
-DCMAKE_HWLOC_2_5_INCLUDE_PATH=C:\cbw\hwloc\include \
-DCMAKE_HWLOC_2_5_DLL_PATH=C:\cbw\bin\libhwloc-15.dll \
-DBUILD_SHARED_LIBS=OFF ..
CMake のオプションについて
指定するオプションが多いので、必要そうなものを説明します。
他のオプションについては README for the CMake build system で説明されています。
-
CMAKE_BUILD_TYPE=Release
-
Debug
ビルドかRelease
ビルドかを選びます。指定しなければ両方なのかもしれません(未確認)。
-
-
CMAKE_INSTALL_PREFIX=<oneTBB ライブラリをインストールするディレクトリパス>
-
include/
やlib/
、share/
など、後の過程でninja install
したときに oneTBB ライブラリの中身が配置されるディレクトリパスです。 - 例えば、
C:/tbb
など
-
-
TBB_STRICT=OFF
- ビルド時にコンパイラの警告をビルドエラーとするかどうかを切り替えます。
- 自分の環境では、
error: value computed is not used [-Werror=unused-value]
という警告が発生してビルドがコケてしまうので、このオプションをOFF
にして警告を無視しています。無視しても多分大丈夫なはず…。- この警告をなんとかしようとして手間取りました
CMAKE_HWLOC_2_5_LIBRARY_PATH=<hwloc のライブラリファイル(libhwloc.lib)へのパス>
CMAKE_HWLOC_2_5_INCLUDE_PATH=<hwloc のヘッダファイルがあるディレクトリへのパス>
-
CMAKE_HWLOC_2_5_DLL_PATH=<hwloc の動的ライブラリファイル(libhwloc-XX.dll)へのパス>
- 動的ライブラリファイル名は自分の場合
libhwloc-15.dll
でした。 - hwloc の静的/動的ライブラリファイル(libhwloc.{lib/dll})へのパスというところがポイントです。普段 GCC でリンクするときの指定方法とは異なります(ここでも少し詰まりました)。
- Windows の場合は
CMAKE_HWLOC_2_5_DLL_PATH
の指定が必要になります。 - 例えば、
C:/hwloc
に hwloc ライブラリが配置されていれば以下のような指定になります。-DCMAKE_HWLOC_2_5_LIBRARY_PATH=C:/hwloc/lib/libhwloc.lib
-DCMAKE_HWLOC_2_5_INCLUDE_PATH=C:/hwloc/include
-DCMAKE_HWLOC_2_5_DLL_PATH=C:/hwloc/bin/libhwloc-15.dll
- 動的ライブラリファイル名は自分の場合
hwloc
とは?
そもそも Potable Hardware Locality(hwloc)ライブラリとは、コンピュータの OS やアーキテクチャなどの違いを抽象化して移植性を高めるためのライブラリ、のようです(多分)。並列でコアを動かす oneTBB としては、確かに必要となりそうです。
自分ははじめこのライブラリを用意しておらず、これ関連でビルドがコケてようやく必要なのを知りました(ドキュメントをよく読め)。
これも Git リポジトリ からビルドしてもよかったのですが、公式ページ からビルド済みのものをダウンロードできるのでこちらが楽です。
左の「Sub Projects > Hardware Locality」から最新のバージョンをダウンロードして任意のディレクトリに展開します。
私がダウンロードした時点でバージョンは 2.8 だったので、CMake のオプションでは『バージョン 2.5 以上の場合』として設定すれば問題なさそうです(CMAKE_HWLOC_2_5_*
を使う)。
静的ライブラリとしてのビルド
oneTBB は普通にビルドすると共有(動的)ライブラリとしてビルドされます。しかし、共有ライブラリをリンクする場合、実行時のライブラリファイルの配置が重要になるので、管理が少し面倒です(環境変数を汚したくないし"共有ライブラリ置き場"に全部突っ込んみもしたくない)。個人的にはバイナリサイズは大きくなっていいので静的ライブラリとしてリンクしたいです。
--static
オプションをリンク時に指定すれば、共有ライブラリも静的ライブラリのようにリンクできるのですが、「このライブラリは共有ライブラリか静的ライブラリか」を意識してビルドする必要があるので、これもまた面倒。
調べてみると、-DBUILD_SHARED_LIBS=OFF
とオプションを指定すると静的ライブラリとしてビルドできるようです。→GitHubのイシュー
今回はこのオプションを使って静的ライブラリとしてビルドしています。
さて、手順に戻ります。
CMake をお望みのオプション付きで実行すると、同じディレクトリ内に build.ninja
が生成されるので、Ninja でビルドします。
> ninja
これで、同じディレクトリに gnu_12.2_cxx11_64_release
というフォルダが作成され、その中にビルド生成物が格納されています。
そして、これを先ほど指定したディレクトリへインストールして完了です。
> ninja install
oneTBB の動作確認
実際に oneTBB を呼び出してみて動作確認してみます。
今回は concurrent_hash_map
を使います。ネットに転がっていたコードそのままですが…。→参考
※ビルドが成功し正常に実行できることだけを確認していて、実際の並列処理がうまくいくかまでは試していません。ビルド通ればいけるやろ。
#include <iostream>
#include <string>
#include <tbb/concurrent_hash_map.h>
int main(int argc, char* arv[]) {
using Accessor = tbb::concurrent_hash_map<int, std::string>::accessor;
tbb::concurrent_hash_map<int, std::string> hmap;
hmap.insert({1, "hello"});
hmap.emplace(2, "world");
{
Accessor accessor;
auto found = hmap.find(accessor, 2);
if(found) {
std::cout << "key 2 => " << accessor->second << std::endl;
}
}
{
Accessor accessor;
auto found = hmap.find(accessor, 1);
if(found) {
accessor->second += ", world!";
std::cout << "key 1 is updated : " << accessor->second << std::endl;
}
}
return 0;
}
コンパイルするときにライブラリを指定します(oneTBB の配置場所を C:/tbb
とします)。
> g++ -IC:/tbb/include -o ./onetbb_test ./onetbb_test.cpp -LC:/tbb/lib -ltbb12
実行すると、問題なく動作しました。
> ./onetbb_test.exe
key 2 => world
key 1 is updated : hello, world!
concurrent_hash_map
のリファレンスはこちら、
oneTBB のリファレンスは こちら です。
おわりに
自分は色々な前提知識が足りておらず悪戦苦闘しましたが、みなさんはこの記事が助けとなり導入が楽になっていれば幸いです。
oneTBB で並列プログラミング頑張るぞ~!(使いこなせるとは言ってない)
Discussion