「コマンドキュー」の版間の差分
ナビゲーションに移動
検索に移動
Administrator (トーク | 投稿記録) |
Administrator (トーク | 投稿記録) |
||
(同じ利用者による、間の1版が非表示) | |||
1行目: | 1行目: | ||
'''コマンドキュー'''(英語:command queue)とは、特定のコマンド(処理)を[[キュー]]に格納しておくと、別の[[プロセス]]や[[スレッド]]が適宜それを取り出して実行する方式のことである。 | '''コマンドキュー'''(英語:command queue)とは、特定のコマンド(処理)を[[キュー]]に格納しておくと、別の[[プロセス]]や[[スレッド]]が適宜それを取り出して実行する方式のことである。 | ||
− | + | 名称に「[[キュー]]」とあるが、ほとんどの実装は[[アルゴリズム]]の教科書に載っているような単純なキューではなく、キューの中においてコマンドの実行順序を並べ替えたりコマンドを結合したりといった[[最適化]]が行われているものが多い。 | |
[[マルチスレッド]]における「[[スレッドプール]]」もほぼ同じ概念である。スレッドプールでは汎用的な処理を格納することができるが、コマンドキューの場合は前述のような最適化が行いやすいように単純なコマンドであることが多い。 | [[マルチスレッド]]における「[[スレッドプール]]」もほぼ同じ概念である。スレッドプールでは汎用的な処理を格納することができるが、コマンドキューの場合は前述のような最適化が行いやすいように単純なコマンドであることが多い。 | ||
32行目: | 32行目: | ||
</source> | </source> | ||
− | [[GPU]] | + | [[GPU]]での描画処理の場合は、前回の描画処理が未完了なのに次の描画処理を始めると残念なことになる。そこで「[[フェンス]]」と呼ばれる[[シグナル状態]]を保持する[[変数]]を用いて適切に処理する必要がある。 |
<source lang="csharp"> | <source lang="csharp"> | ||
var fence; | var fence; |
2021年2月8日 (月) 04:08時点における最新版
コマンドキュー(英語:command queue)とは、特定のコマンド(処理)をキューに格納しておくと、別のプロセスやスレッドが適宜それを取り出して実行する方式のことである。
名称に「キュー」とあるが、ほとんどの実装はアルゴリズムの教科書に載っているような単純なキューではなく、キューの中においてコマンドの実行順序を並べ替えたりコマンドを結合したりといった最適化が行われているものが多い。
マルチスレッドにおける「スレッドプール」もほぼ同じ概念である。スレッドプールでは汎用的な処理を格納することができるが、コマンドキューの場合は前述のような最適化が行いやすいように単純なコマンドであることが多い。
主な実装例[編集 | ソースを編集]
ハードディスクのNCQ[編集 | ソースを編集]
最近のハードディスクにはNCQ (Native Command Queue)という機構が搭載されており、1つの読み書き依頼が1つのコマンドとしてコマンドキューに格納される。複数の処理待ちが発生している場合はコマンドキューの中で磁気ヘッドの動きが最小になるように最適化してから実際の読み書き処理が行われる。
GPUのコマンドリスト[編集 | ソースを編集]
最近のGPUでは「1フレーム分の描画処理」をコマンドキューに格納して実行する方式が主流となっている。こちらは「CPUがGPUの処理完了を待たないための機構」という意味合いが強く、GPUが別スレッドのような扱いになる。
架空のコマンドセットを示す。
void Draw() {
// コマンドリストを作る
var cl = new CommandList();
cl.Add(new SetFrameBufferCommand()); // フレームバッファをセットする
cl.Add(new ClearCommand() ); // フレームバッファをクリアする
// コマンドキューに格納する
GraphicsDevice.SubmitCommands(cl);
// ここでGPUでの処理完了を待てば従来同様になる。
// ただWaitForIdle()している間はCPUが遊んでしまう。
GraphicsDevice.WaitForIdle();
}
GPUでの描画処理の場合は、前回の描画処理が未完了なのに次の描画処理を始めると残念なことになる。そこで「フェンス」と呼ばれるシグナル状態を保持する変数を用いて適切に処理する必要がある。
var fence;
void Init() {
fence = GraphicsDevice.CreateFence();
}
void Draw() {
// 前回の処理完了を待つ
// ここで待たずにフレームスキップするのも手である。
//if (!fence.Signaled)
// return;
GraphicsDevice.WaitForFence(fence);
// コマンドリストを作る
var cl = new CommandList();
cl.Add(new SetFrameBufferCommand()); // フレームバッファをセットする
cl.Add(new ClearCommand() );
// コマンドキューに格納する
GraphicsDevice.SubmitCommands(cl, fence);
// ここで待たないのが重要
}