Windowsでディスクからの良好な同時読み取り性能を得る方法

マルチスレッド環境で大きなファイルを扱う際、ディスクからの最適な読み取り性能を達成することは大きな課題となることがあります。複数のスレッドが異なるファイルを同時に読み取ろうとするシナリオでは、オペレーティングシステムのディスクスケジューリングポリシーの影響でスループットが悪化することがあります。この投稿では、一般的な問題と、Windowsでのディスク読み取り性能を向上させるための戦略について探ります。

問題: 同時読み取り性能の制約

たとえば、約2 GiBの大きなファイルが2つあり、それぞれを2つのスレッドが同時に読み取ろうとしているとします。性能が向上するどころか、両方のスレッドがうまく機能せず、合計スループットがわずか2-3 MiB/secにとどまっています。以下は状況の概要です:

  • セットアップ: 2つのスレッドがそれぞれ1つのファイルを読み取っています。
  • 観察結果: 両方のスレッドがアクティブな場合の低い合計スループット(約2-3 MiB/sec)と、1つのスレッドでのはるかに良い性能(約45 MiB/sec)。
  • 疑われる原因: Windowsのディスクスケジューラによるディスクシーク動作が影響を及ぼし、効率的でない読み取りパターンを招いています。

Windowsにおけるディスクスケジューリングの理解

解決策に取り掛かる前に、WindowsがディスクI/Oリクエストをどのように管理しているかを理解することが重要です。歴史的に、WindowsはディスクリクエストのためにFIFO(先入れ先出し)キューを使用しており、リクエストは64 KBブロックに分割されていました。これにより、以下のような問題が生じました:

  • 頻繁なディスクシーク: 2つのスレッドが同時に読み込んでいる場合、そのリクエストが干渉し、ディスク上を行き来することになります。
  • 柔軟性の欠如: Windows Vista以前は、開発者がディスクリクエスト処理を変更する手段が非常に限られていました。

しかし、Windows Vistaの導入により、より洗練されたディスクスケジューリングアルゴリズムが実装され、同時I/O操作の管理が改善されました。ここでの疑問は、**Vista以前のシステムや、問題が続く場合の最新バージョンでの読み取り性能を最適化するにはどうすればよいか?**です。

同時読み取り性能を向上させるための提案ソリューション

  1. 自作のディスクアクセスポリシー: 以前のWindowsバージョンでスケジューリングポリシーを変更できないため、スレッド内でディスクアクセスを管理する独自の方法を考案します。

    • ポリシー実装の例
      if (THREAD_A がディスクから読み取り中) {
          THREAD_Aの読み取りが停止するまで待機するかX ms待機する
      }
      X ms(またはY MB)読み込み
      読み込みを停止し、再度THREAD_Aの状態を確認
      

    このポリシーは、スレッドが他のスレッドが現在読み取っていないときのみディスクにアクセスする待機メカニズムを導入し、シークの問題を軽減します。

  2. 同期プリミティブの利用: セマフォやミューテックスを使用してディスクへのアクセスを制御し、一度に1つのスレッドのみが読み取るようにします。これにより、真の同時読み取りと比較するとスループットはわずかに低下する可能性がありますが、全体的な効率を向上させることができます。

  3. メトリクスによるパフォーマンスのモニタリング: パフォーマンス監視ツール(perfmonなど)を使用してディスクキューの状態を評価し、読み取り間隔やデータサイズを動的に調整します。この「自動調整」アプローチにより、リアルタイムのパフォーマンスメトリクスに基づいて戦略を適応させることができます:

    • 現在の転送速度を測定。
    • 過去のパフォーマンスデータに基づいてXおよびYの値を調整。
  4. 新しいWindowsバージョンへのアップグレード: 可能であれば、オペレーティングシステムのアップグレードを検討します。Windows Vista以降は、よりスマートなディスクスケジューリングが提供され、より効率的な同時読み取りを可能にします。

結論

Windowsでディスクからの良好な同時読み取り性能を達成するには、OSのI/Oスケジューリングの制限を理解し、それらを回避するための巧妙なソフトウェア技術を実装することが必要です。カスタムディスクアクセスポリシーを導入し、同期技術を使用し、パフォーマンスメトリクスを監視することで、大きなファイルとマルチスレッド処理を扱う際に、アプリケーションのスループットを大幅に向上させることができます。

これらの戦略を慎重に実施すれば、ディスク読み取りプロセスを最適化し、アプリケーションにおける同時プログラミングの力を最大限に活用できるようになるでしょう。