#はじめに
Facebookがアプリケーションを高速化するBOLTというツールを公開したので試してみました。
以下によると、2-15% ほどアプリケーションの性能が上がるそうです。
記事を読む感じだと、プロファイルデータをもとにプログラムバイナリの配置を修正し、プログラム命令自体の CPU キャッシュへの載り方とTLBミスの発生を最適化するようです。
#環境
CentOS7 の環境でやりました。
BOLT (perf) は CPU のパフォーマンスカウンタを使って性能プロファイリングをするので、AWSなどの仮想マシンでは実行できない可能性があります。
また、BOLTのビルド時にはかなり大量のメモリを使います。ビルドだけはAWSなどを利用したほうが良いかもしれません。(私は m5.4xlarge を使いました。)
環境
OS: CentOS 7.4
メモリ: 64GB 程度 ※BOLT ビルド時にかなりメモリを使います
ディスク: 30GB 程度の空き ※BOLT ビルド時にかなり容量を食います
ビルド方法
準備
まずは必要なパッケージを入れます。
ビルドには新しい目の GCC がいるので GCC の7 系を入れます。
$ sudo yum groupinstall 'Development Tools'
$ sudo yum install centos-release-scl-rh epel-release
$ sudo yum install cmake3
$ sudo yum install -y "devtoolset-7-gcc*"
$ sudo yum install -y ninja-build
ビルドは以下に従って実行します。
https://github.com/facebookincubator/BOLT
$ git clone https://github.com/llvm-mirror/llvm llvm
$ cd llvm/tools
$ git checkout -b llvm-bolt f137ed238db11440f03083b1c88b7ffc0f4af65e
$ git clone https://github.com/facebookincubator/BOLT llvm-bolt
$ cd ..
$ patch -p 1 < tools/llvm-bolt/llvm.patch
$ cd ..
$ mkdir build
$ cd build
$ scl enable devtoolset-7 bash # gcc のバージョン切り替え
$ cmake3 -G Ninja ../llvm
$ ninja-build
LLVM のビルドになり、かなり時間がかかるので気長に待ちましょう。
正常にビルドできれば llvm-bolt というバイナリができます
$ ls -l bin/llvm-bolt
-rwxrwxr-x. 1 centos centos 1137884624 6月 23 11:33 bin/llvm-bolt
実行方法
実行も下記に手順があります。
https://github.com/facebookincubator/BOLT
プログラムを実行して perf でプロファイルデータを取り、それをBOLTに渡してバイナリを最適化するという流れです。
適当なアプリケーションがないので、今回はUnixBenchのベンチマークプログラム (dhry2) を最適化してみました。
dhry2 のビルド
BOLTで最適化できるよう、プログラムのリンク時に "-Wl,--emit-relocs" をつけておきます。
$ git clone https://github.com/kdlucas/byte-unixbench.git
$ cd byte-unixbench/UnixBench/
$ gcc -o pgms/dhry2 -Wall -pedantic -O3 -ffast-math -march=native -mtune=native -I ./src -DTIME -DHZ= ./src/dhry_1.c ./src/dhry_2.c -Wl,--emit-relocs
BOLT の実行
最初に perf でプロファイルを取り、BOLT を実行してプログラムを最適化します
$ sudo perf record -e cycles:u -j any,u -o perf.data -- ./pgms/dhry2 10
$ sudo perf2bolt -p perf.data -o perf.fdata ./pgms/dhry2
$ sudo llvm-bolt ./pgms/dhry2 -o ./pgms/dhry2.bolt -data=perf.fdata -reorder-blocks=cache+ -reorder-functions=hfsort+ -split-functions=3 -split-all-cold -split-eh -dyno-stats
$ ls -l ./pgms/dhry2*
-rwxrwxr-x 1 user1 user1 19648 6月 23 19:53 ./pgms/dhry2
-rwxr-xr-x 1 root root 8399680 6月 23 20:40 ./pgms/dhry2.bolt
性能比較
最適化前/後でそれぞれ dhry2 の性能値を取り比較してみました。
性能値 | 改善率| | |
---|---|---|
最適化前 | 81063732 | - |
最適化後 | 78195069 | -3% |
ほぼ誤差の範囲ですね。
UnixBenchではプログラムが小さくて最適化の効果があまりなかったのだと思います。
もう少し複雑なプログラムがあれば効果が見えるかもしれません。