バージョン

menu_open
Wwise SDK 2018.1.11
I/Oのヒント、トラブルシューティングと最適化
Default Streaming Manager Information

この章に記載されているヒントやその他のI/Oに関連する検討事項は、高レベル Stream Manager の API を使用し、I/Oコードを低レベルI/Oインターフェース下にフックする場合にのみ関連する情報です。ほとんどの部分において、デフォルト Stream Manager 設定 (Audiokinetic ストリームマネージャ初期化設定) および低レベル I/Oインターフェース (低レベル I/O) への理解が前提とされています。

DVD デバイスの設定

デフォルトのデバイス設定(AK::StreamMgr::GetDefaultDeviceSettings より取得可能)は、DVDデバイスに適切です。デフォルトの粒度は16 KBですが、より粒度が大きいほど単一ストリームの優れたDVDスループットを得られます。32 KBは、ほとんどのDVDドライブに適しています。1つまたは2つ以上のオーディオファイルをストリーミングしない場合のみより大きい粒度を使用するようにしてください。さもないと、他のストリームを犠牲にして単一ストリームのスループットを最適化することになります。また、粒度が大きいほどより多くのストリームI/Oメモリが要求されることに注意してください。

おそらく、ある段階でメモリ使用量を最適化したくなることがあるでしょう。これに関する有用な情報が I/O プール メモリ使用量の低減 にありますので、参照してください。

ブロッキングI/Oフックの代わりに遅延I/Oフックを使用

ブロッキング(blocking)I/O フックの代わりに遅延(deferred)I/Oフックを使用すると、一般的に効率が悪くなります。これは、遅延I/Oデバイスがより多くの false予測をするので(転送のキャンセルや帯域幅の浪費につながり)、より多くの Stream Manager プール内メモリを必要とするためです。このようなフックは、以下の状況のいずれかに該当する場合のみ使用してください。

ゲームエンジンI/Oマネージャが非同期APIを公開

ご使用の I/Oマネージャが、非同期 API のみを公開しており、Wwise I/O 呼び出しをこれにルーティングしたい場合、遅延I/Oフックでアダプタレイヤを実装するほうがはるかに簡単です。遅延I/Oフックに典型的な false 予測を減らすには、AkDeviceSettings::uMaxConcurrentIO を1または2に設定します。

ゲームエンジンI/Oマネージャがファイル配置に基づいてI/O要求をシャッフル可能

Wwise Stream Manager は、ファイルが配置されているディスク上の物理的な位置に応じて決定を行うことができません。ご使用の I/Oマネージャが、例えば隣り合った転送を優遇するなど、ファイル配置に関する認識に基づいて保留中の要求の順序をシャッフルできる場合、一度に多くの転送を Wwise Stream Manager から受信し、これらの転送を独自のスケジューラへプッシュするほうが有益であるかもしれません。

転送完了が発行転送数に非依存

一部のデバイスは、発行された転送数にほとんど依存しないメカニズムに基づいて転送要求を解決します。これは、しばしば DMAコントローラベースのデバイスに当てはまります。転送はDMAの完了時に完了しますが、これを待たずに別のDMAの準備をしたい場合には、遅延デバイスを大きな AkDeviceSettings::uMaxConcurrentIO と使用します。最大転送数は、I/O要求の低レベルI/Oへの送信を妨げないように、十分に大きい値を設定する必要があります。これにより、帯域幅の量はターゲットバッファ長によってのみ制御されるようになります。

複数デバイスの使用

一般的には、各物理デバイス(DVD、HDD、RAM/VRAMなど)ごとに異なるストリーミングデバイスを使用する必要があります。第一の理由は、各ストリーミグデバイスが別々のスレッドで実行されるということで、これは転送要求を物理デバイス間でシリアライズしたくない場合に必須となります。DVDリード(read)を待ってから、HDDリードを発行するのは非効率的です。第二の理由は、最適な設定が通常は各デバイスごとに異なるということです。

複数デバイスを使用する場合、ディスパッチャが必要です。システムへの複数デバイス実装に関する詳細は マルチデバイスI/Oシステム を参照してください。

ディスパッチでは、どのデバイスからどのファイルがオープンされるべきかを認識している必要があります。推奨されるソリューションは、ファイルパッケージの使用です。File Packager を使用すると、サウンドバンク生成後にサウンドバンクとストリーミングオーディオファイルを様々なファイルパッケージにまとめてパックすることができます。それぞれのファイルパッケージは、特定のデバイスにロードされるようになっています。ランタイム時には、単一のディスパッチャで、いずれかのデバイスがファイルのオープンを受け付けるまで、各デバイスをクエリーできます。これは、デフォルトディスパッチャの動作です(SDKサンプルの AkDefaultLowLevelIODispatcher.h/cpp を参照)。このテクニックで、フォールバックメカニズムを実装することもできます。例えば、RAM/VRAMデバイスからファイルをロードしようとしてこれが動作しない場合、DVDからロードします。

ファイルディスパッチ/デバイス割り当てが同期している必要があることに注意してください:これを遅延させることはできないので、高速であることを確認してください。SDKサンプルに実装されているファイルパッケージルックアップはバイナリサーチアルゴリズムを使用するため高速です。

I/Oのトラブルシューティング

Wwiseツールをゲームに接続してプロファイラを使用すると、ご使用のI/Oシステムと設定をトラブルシューティングおよび最適化することができます。キャプチャログが、ソース枯渇やその他のI/Oエラーを通知します。Advanced Profiler ビューの次の2つのタブはI/O専用です:Streams タブおよび Streaming Devices タブ。

また、AkFileDesc のカスタムパラメータおよび AK::StreamMgr::IAkLowLevelIOHook::GetDeviceDesc()AK::StreamMgr::IAkLowLevelIOHook::GetDeviceData() を使用して、低レベルI/Oシステムデータを Wwise プロファイラに表示することができます。

ソース枯渇のトラブルシューティング

ソース(I/O)枯渇は、ストリーミングデータが要求された期限内に Stream Manager へ送信されなかった場合に発生します。プロファイラのキャプチャログに、枯渇しているオーディオソースの名前/ IDとともにエラー通知が表示されます。

ソース枯渇の原因

ソース枯渇は、不良なI/O設定によってではなく、他の原因によって発生します:

1)インタラクティブミュージック: Interactive Music 階層のストリーミングオブジェクトは、事前に予定され、ストリーミングデータが時間通りに準備される必要があります。このルックアヘッド時間は各ミュージックトラックのプロパティです。インタラクティブミュージックで枯渇が発生した場合は、指定したルックアヘッド時間が十分に長くないことが原因である可能性があります。

2)ゼロレイテンシ ストリーミング: サウンドと音楽トラックプロパティで「Zero Latency (ゼロ レイテンシ)」オプションをチェックした場合、ストリーミングファイルの最初を、サウンドバンクに保存する必要があります。該当サウンドやミュージックトラックを再生するためにイベントをポストすると、サウンドバンクに格納されたデータ(プリフェッチデータ)を利用して直ちに再生が開始します。しかし、ファイルの残りの部分がディスクからストリーミングされる前にプリフェッチデータがなくなると、ソース枯渇が発生します。この場合には、プリフェッチ長を拡大してください。

"Zero-Latency" が選択されていない Actor-Mixer(アクターミキサー)階層のサウンドは、ターゲットバッファ長に到達するまで再生を開始しません。サウンドがターゲットバッファ長に到達するのにかかる時間がサウンドの初期レイテンシー(遅延)に影響します。従って、これらのサウンドで枯渇が起こっているのは、不適切またはアンバランスなI/O条件が原因である可能性があります。

I/Oメモリ不足

デバイスが供給できる以上のスループット要求の他に、枯渇につながる主な原因としてI/Oメモリ不足があります。I/Oメモリプールがいっぱいになると、ストリーミングデバイスは、低レベルI/Oへの.転送要求の送信を停止します。プロファイラの Streaming Devices タブでI/Oメモリ使用状況を確認してください。

過度のワークロード

ある状況においてソース枯渇が発生しており、これが特定のストリームに固有ではない場合、I/Oデバイスが提供できる限度を超えてあまりにも多くのオーディオデータを要求していることが原因である可能性があります。その帯域幅をゲームの他のアセットと共有する必要があることを忘れないようにしてください。I/Oのオーディオの負荷を制限する好ましい方法は、インスタンス制限(instance limiting)やバーチャルボイス(virtual voices)など、Wwiseのデータドリブン機能を使用するストリーム数を制限することです。

枯渇は、ターゲットバッファが小さすぎる場合にも発生します。Streamsタブで、バッファステータス(Buffering Status)と参照メモリ量(Ref. Memory)に注意を払ってください。もしも、ウィジェットがほとんど常に "full" を示していて、参照メモリが頻繁に0まで低下する場合、ターゲットバッファ長が小さすぎる可能性があります:I/Oスレッドはほとんどアイドル状態ですが、I/OスケジューラがI/O要求の送出を決定した時点でディスクからバッファを読み出すのにかかる時間を補うのにバッファリングが十分長くありません。

一方、Buffering Status ウィジェットが定常状態であるべきストリーム(つまり、既に再生を開始しているストリーム)に対して "not full" を示しているような場合、これは低レベルI/Oデバイスが遅すぎてこれらのストリームにサービスを提供できていないことを意味します。また、I/Oプール内に使用可能なメモリがない(Streaming Devices を確認してください)、または、スケジューラが同時I/O要求の数が AkDeviceSettings::uMaxConcurrentIO を下回るのを待機していることが原因である可能性もあります。

特定ストリーム存在下での系統的な枯渇の発生

時々、ソース枯渇が特定ストリームの存在下で系統的に発生する場合があります。

すべてのオーディオストリームに対して適切なサービスを提供するためにストリーミングデバイスが必要とする総スループットは、ストリームの圧縮フォーマット、サンプルレート、チャンネル数などに基づいたヒューリスティックを使用して、これらのストリーム間でバランスを保たれます。しかしながら、一部の可変ビットレートコーデック(XMA や Vorbis など)は、最初に宣言したより多くの I/O データをプルすることがあり、これは、例えばシーク中や時にはループ境界で起こります。シークで起こる場合には、変換設定(conversion settings)で、より小さいシークテーブル ブロックサイズを使用してみてください。シークは、インタラクティブミュージックやバーチャルボイスの "From Elapsed Time" ビヘイビアでも発生することに注意してください。

それ以外の場合は、ディスク上の遠い位置にファイルがある場合にも枯渇が発生します。プラットフォームのツール(ファイルパッケージを使用する場合は File Packager ユーティリティ)を使用して、ランタイム時のシークを最小限にすることで、ディスク上のファイル配置を最適化してください。

また、ターゲットバッファ長を増加させることによって、これらのスループット要件のスパイクを補うことができます(ただし I/O メモリ使用の増加に注意)。

その他のヒント

小さなループサウンドをストリーミングする場合は、キャッシング (AkDeviceSettings::fMaxCacheRatio) を有効にすると便利かもしれません。これにより、帯域幅およびI/Oメモリを節約することができます。

またDVD/HDDデバイスでの帯域幅浪費を避けてください。遅延(deferred)デバイスを使用する場合は、キャンセル転送(プロファイラの Streaming Devices タブ)を監視してください。同時転送の最大数 (AkDeviceSettings::uMaxConcurrentIO) を減らすことも有用です。

I/OスレッドによるCPU使用率の低減

I/Oデバイスのスレッドは、I/O 待ちにほとんどの時間を費やすため、通常わずかな量のCPUしか使用しません。このCPU使用率は、非常に高速なデバイス(RAMなど)では、もっと大きくなることがあります。このような場合、次のような対処を行ってみてください:

  • ターゲットバッファを減少させる;
  • スレッドの優先度を下げる。

ファイルオープンの時のみに CPU スパイクが発生する場合は、ファイルオープンにかなりの時間がかかっていることが原因である可能性があります。プラットフォーム/ディスク デバイスの中には、fopen() から戻るのが遅いものがあります。そのような場合には、ファイルオープンを遅延(defer)させてください(詳細は 遅延オープン を参照)。

I/O プール メモリ使用量の低減

同時に再生するストリーム数を減らすことの他に、次のような対処により必要なI/Oメモリサイズを低減することができます。

  • 粒度を下げる(デバイススループットへの負の影響に注意);
  • ターゲットバッファを低くする(ソース枯渇に注意);
  • ストリームデータのキャッシングを使用する(ただし、小さめのプールではキャッシングがあまり効率的でないことに注意)。

I/Oメモリプールでは、フラグメンテーション(断片化)が発生しないことに注意してください。また、このプールにおける散発的なメモリ不足は許容されます。ほとんどの場合において、既にストリーミングされたデータは、このようなメモリ使用量のスパイクをじゅうぶんに持ちこたえることができます。発生する可能性のある最悪の事態は、ソースの枯渇です。

ストリームマネージャプールメモリ使用量を低減

Stream Manager のメモリプールは、小オブジェクトの割り当てに使用されます:デバイスおよびストリームオブジェクト、転送構造、非同期ファイルオープン用ストレージ、ストリームメモリ ルックアップテーブルなど。このプールに必要とされる一般的サイズはかなり小さいですが、理想としては、このプール内のメモリが決して不足しないようにしてください。さもないと、回復不能なI/O障害が発生する可能性があります。ほとんどの割り当ては、デバイスの作成時に行われることに注意してください。

以下の設定により、Stream Manager プールから要求されるメモリを低減することができます:

  • 遅延(deferred)デバイスの代わりにブロッキング(blocking)デバイスを使用;
  • 遅延デバイスを使用する場合は、同時要求の最大数を低減 (AkDeviceSettings::uMaxConcurrentIO);
  • キャッシュ率を低減 (AkDeviceSettings::fMaxCacheRatio);
  • 同期ファイルオープンを実行(詳細は 遅延オープン を参照);
  • 同時オープンされるストリーム数を制限。

このページはお役に立ちましたか?

サポートは必要ですか?

ご質問や問題、ご不明点はございますか?お気軽にお問い合わせください。

サポートページをご確認ください

あなたのプロジェクトについて教えてください。ご不明な点はありませんか。

プロジェクトを登録していただくことで、ご利用開始のサポートをいたします。

Wwiseからはじめよう