概要
- Ben Hoyt のブログ記事を受けて、I/Oがボトルネックではないとする主張の検証
- CPU最適化 やベクトル化によるパフォーマンス向上の試み
- wc -w などの既存ツールや手動ベクトル化との速度比較
- AVX2 による手動最適化の実践と結果
- ディスク速度とCPU速度の関係 についての考察
I/Oは本当にボトルネックか?ベンチマークと最適化の実践
- Ben Hoyt のブログで「I/Oはボトルネックではない」と主張
- 順次読み込み速度 は近年大幅に向上、CPU速度は頭打ち傾向
- cold cache で1.6GB/s、 warm cache で12.8GB/sの読込速度を計測
- 単一スレッド で1.6GB/sのワード頻度カウントは可能かという疑問
- GitHub にコードを公開
Cによる最適化実装の検証
- Ben Hoyt の高速C実装を GCC 12 で-O3 -march=native付きでコンパイル
- 425MB のテキスト(聖書100冊分)を入力として実行
- 結果は 278MB/s (warm cache)と期待外れの速度
- ホットループに分岐や早期脱出が多く、 ベクトル化困難 であることが判明
ベクトル化による改善
- 小文字変換部分をループ外に出すことで 330MB/s に改善(clang使用)
- しかし、依然としてcold cacheの順次読込速度の5分の1程度
- ハッシュマップのキャッシュミスやパーフェクトハッシュ導入などの余地もあるが、劇的な改善は難しいと判断
問題を単純化して計測
- 頻度カウントをやめて単純なワード数カウント( wc -w)を実行
- 結果は 245.2MB/s とさらに低速
- wc -w は多様なホワイトスペースやロケール対応で処理が重い点を指摘
AVX2による手動ベクトル化とビットトリック
- AVX2 などの新しいCPU命令セットでのベクトル化を試行
- コンパイラの自動ベクトル化は困難、分岐の多いスカラプログラムの限界
- VPCMPEQB でホワイトスペース位置をマスク化し、 PMOVMSKB でビットマスクをintへ
- ffs (Find First Set)命令でワード開始位置を効率的に特定
実装と検証
- immintrin.h を使った手動AVX2実装
- データを32バイトアラインし、ループを4回アンローリングして 128バイト ずつ処理
- 実装上のバグ修正に苦戦しつつも動作確認
- wc-avx2 と wc -w で同一結果を確認
パフォーマンス結果
- warm cache で 1.45GB/s (順次読込速度の11%程度)
- cold cache でもユーザーモード処理の割合が高い
- ディスク速度の向上に対し、CPU側の処理が追いついていない現状
まとめと展望
- ディスクI/O速度の向上 は著しいが、 CPU側の処理最適化 がボトルネック
- 自動ベクトル化 の限界、手動最適化の必要性
- GitHub でコード公開、さらなるビットトリックや最適化案の募集
- 今後も CPUアーキテクチャ や コンパイラ技術 の進化に期待