コマンドキュー

提供: MonoBook
2021年2月8日 (月) 04:08時点におけるAdministrator (トーク | 投稿記録)による版
(差分) ← 古い版 | 最新版 (差分) | 新しい版 → (差分)
ナビゲーションに移動 検索に移動

コマンドキュー(英語:command queue)とは、特定のコマンド(処理)をキューに格納しておくと、別のプロセススレッドが適宜それを取り出して実行する方式のことである。

名称に「キュー」とあるが、ほとんどの実装はアルゴリズムの教科書に載っているような単純なキューではなく、キューの中においてコマンドの実行順序を並べ替えたりコマンドを結合したりといった最適化が行われているものが多い。

マルチスレッドにおける「スレッドプール」もほぼ同じ概念である。スレッドプールでは汎用的な処理を格納することができるが、コマンドキューの場合は前述のような最適化が行いやすいように単純なコマンドであることが多い。

主な実装例[編集 | ソースを編集]

ハードディスクのNCQ[編集 | ソースを編集]

最近のハードディスクにはNCQ (Native Command Queue)という機構が搭載されており、1つの読み書き依頼が1つのコマンドとしてコマンドキューに格納される。複数の処理待ちが発生している場合はコマンドキューの中で磁気ヘッドの動きが最小になるように最適化してから実際の読み書き処理が行われる。

GPUのコマンドリスト[編集 | ソースを編集]

最近のGPUでは「1フレーム分の描画処理」をコマンドキューに格納して実行する方式が主流となっている。こちらは「CPUGPUの処理完了を待たないための機構」という意味合いが強く、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);
    
    // ここで待たないのが重要
}

関連項目[編集 | ソースを編集]