大小のクリティカル・セクション多くの計算処理を多用するアプリケーションでは、順序付き入力データを順序付き出力データに変換する複雑な処理が行われます。具体的な例としては、オーディオ変換、ビデオ変換、ロスレスデータ圧縮、地震データ解析などがあります。順序による依存性の管理にはいくつかの課題があります。この記事は、これらの課題について説明し、並列パフォーマンスを維持しながら課題に取り組む方法を示します。プラットフォーム向けにマルチスレッド・アプリケーションを効率的に開発するための手法について説明します。リアルタイムに処理してディスクやネットワーク・クライアントに転送するように設計されたビデオ圧縮エンジンのマルチスレッド化を考えます。このようなアプリケーションのリアルタイム処理では、複数のプロセッサーを活用することが有益であることは明らかです。ようなビデオ圧縮規格は、信頼性の低いリンク上のストリーミング向けに設計されています。このため、単一のビデオストリームをより小さなスタンドアロン・ストリームのシーケンスとして扱うことが容易です。この場合、小さなストリームを並列に処理することで、大幅なスピードアップを達成できます。マルチスレッド化によって並列化を行うには、以下のような課題があります。問題のオーバーラップしない部分を定義してスレッドに割り当てる。入力データを正しい順序で一度だけ読み取る。処理が実際に終了した順序に関係なく、大幅にパフォーマンスを低下させることなく正しい順序でブロックを出力する。知識なしに上記の処理を行う。ロスレスデータ圧縮のようなケースでは、多くの場合、入力データのサイズをあらかじめ決定して、データを独立した入力ブロックに明示的に分割します。ここで説明するテクニックは、このケースにも同様に適用できます。アドバイス生産と消費のチェーンをセットアップする方法が考えられるかもしれませんが、このアプローチはスケーラブルではなく、ロード・インバランスが発生しやすくなります。代わりに、この記事では、よりスケーラブルなデータ分解を使用して上記の課題に取り組みます。ここで採用するアプローチは、ビデオのブロックを読み取り、エンコードして、リオーダーバッファーに出力するスレッドのチームを作成します。各ブロックの処理が完了すると、スレッドは次のビデオブロックを読み取って処理します。この動的な割り当てにより、ロード・インバランスを最小限に抑えます。リオーダーバッファーは、完了した順序に関係なく、コード化されたビデオのブロックが正しい順序で書き込まれることを保証します。オリジナルのビデオ・エンコーディング・アルゴリズムは以下のとおりです。outFile)最初に、フレームシーケンスの読み取りとエンコードをブロックベースのアルゴリズムに変更して、スレッドのチームで分解を行うようにコードを設定します。outFile)}データブロックの定義はアプリケーションによって異なりますが、ビデオストリームの場合、最小および最大ブロックサイズの制約により、自然なブロック境界が、インプットでシーンの変更が検出される最初のフレームになります。ブロックベースで処理を行うためには、処理の前にバッファーが設定されるように、入力バッファーの割り当てとソースコードの変更が必要です。メソッドを変更する必要もあります。つのユニットとして書き込まれるようにします。ブロックが単に正しい順序で出力されれば良いため、このアプローチは出力のリオーダー処理を単純化します。以下のコードは、出力をブロックベースで行うように変更したものです。最大ブロックサイズに対応するサイズの出力バッファーが必要です。各ブロックは独立しているため、各出力ブロックは特別なヘッダーで始まります。結果的に、ヘッダーはブロックからループ内部へ移動されます。使用した並列化が可能になります。outFile)}これは簡単ですが、データを安全かつインオーダーで読み取るための効果的な手法です。各スレッドはロックされ、データのブロックを読み取った後、リリースされます。入力ファイルの共有により、データブロックが正しい順序で一度だけ読み取られることが保証されます。準備完了のスレッドは常にロックされるため、ブロックは動的または先着順でスレッドに割り当てられ、通常、ロード・インバランスが最小限に抑えられます。最後に、ブロックが安全かつ正しい順序で出力されるようにします。つのブロックのみ書き込まれるようにすることでしょう。このアプローチではスレッドセーフであることは保証されますが、オリジナルと異なる順序でブロックが出力される可能性があります。出力をフラッシュする前に以前のすべてのブロックが書き込まれるまでスレッドを待機させることもできますが、スレッドが書き込みを待つ間アイドル状態になるため、効率は悪くなります。ここでは、出力ブロックの循環リオーダーバッファーを確立するアプローチを考えます。各ブロックに連続した番号を割り当て、バッファーの「末尾」が次のブロックを指すようにします。スレッドは、バッファーの末尾が指していないデータブロックの処理を完了した場合、ブロックを適切なバッファーの位置に入れてから、次の利用可能なブロックの読み取りと処理を行います。バッファーの末尾が指しているブロックの処理を完了した場合、そのブロックとキューに入れられていた連続するブロックを書き込みます。最後に、次に出力するブロックを指すようにバッファーの末尾を更新します。キューに入れることができます。書き込み前のリオーダーバッファーの状態。リオーダーバッファーのある状態を示しています。まではすでに処理され書き込まれています。処理され、書き込みのためにキューに入れられています。