概要
C++でSIMDを書く人向けの良いライブラリを見つけました。
https://github.com/p12tic/libsimdpp
SIMDをtemplateで扱うことができるので、SSE、AVXなどの異なった命令セットや、float, doubleなどの異なった型を同じコードで扱うことができます。
メリット
- 命令セットを簡単に切り替えられる
- 型を簡単に切り替えられる
- ヘッダーオンリーで導入が楽
アセンブラや組み込み関数を使うくらいならlibsimdppを使った方が良いと思います。
デメリット
- GPUと横断の抽象化(OpenCLなど)はできない
- 最新の命令に追従しないかもしれない
OpenCLとどちらを選ぶかは吟味する必要がありそうです。
OpenCLだとCPU向けのカリカリチューニングはできないかもしれないので、カリカリチューニングをする必要があるなら、libsimdppが良いと思います。
体験談
x86環境で、実際に使ってみてよかった点のレポートです。
かんたんに移植できた
libsimdppへの移植は3時間くらいでサクっと終わり、floatからdoubleに切り替えて一発で動作したときは、簡単すぎてビビりました。コンパイル時に、型チェックができるので、ミスが少ないです。
アルゴリズムの精度を分析できた
アルゴリズムの研究と、アプリケーションへの実装を同時並行で行なっています。
アプリケーションなので、高速化のためにfloatを使っています。ただ、一度アルゴリズムを、生の組み込み関数で書いてしまうと、doubleに切り替えるのはかなり大変です。
一方、研究用途で、以下を知りたいことがあります。
- アルゴリズム自体の性能が悪いのか、計算精度のせいで性能が悪いのか?
- 桁落ちやオーバーフローなど、計算精度を考慮した実装ができているか?
こういうときに、精度を切り替えたバージョンと結果を比較できると、調査がかんたんです。
アルゴリズムのパフォーマンスを分析できた
型のサイズを変えたり、命令セットを変えたりすることで、メモリボトルネックなのか、CPUボトルネックなのかのヒントが得られました。
Google BenchmarkのTemplate Benchmark機能と組み合わせて、各命令セットでのパフォーマンスを、一覧でかんたんに出力できました。
その他使ったもの
- Intel TBB
- Intel IPP
- Intel Architecture Code Analyzer: https://software.intel.com/en-us/articles/intel-architecture-code-analyzer
類似ライブラリ
MIPP
- MIPP github
- MIPP: a Portable C++ SIMD Wrapper and its use for
Error Correction Coding in 5G Standard
↑によると、AVX-512でMIPPのほうがsimdppより速い?理由は調べてない。