I/Oはもはやボトルネックではないのか? (2022)
101日前原文(stoppels.ch)
概要
- 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アーキテクチャやコンパイラ技術の進化に期待