VK_EXT_subgroup_size_control 解説:実際のサブグループサイズの選択と読み取り

gl_SubgroupSize は定数ではない。ほとんどの GPU ではドライバーが パイプラインごとに選び、同じデバイス上でもシェーダーステージ間で 異なり得る。「subgroup = warp = 32」と仮定したコードは AMD (wave64)、Intel(SIMD8/16/32)、サブグループを再パックする あらゆるドライバーで壊れる。VK_EXT_subgroup_size_control(1.3 で コア化)は2つのものを与える。ランタイムでの実際のサイズと、 それを固定する機能だ。

実際のサイズを読み取る

query.comp
#extension GL_KHR_shader_subgroup_basic : require

// これらはコンパイル時ではなくランタイムの値だ:
int  sz    = gl_SubgroupSize;         // サブグループあたりの実際のレーン数
int  lid   = gl_SubgroupInvocationID; // レーンインデックス 0..sz-1
bool first = gl_SubgroupElect();      // 「自分はレーン 0 か?」

NVIDIA では sz は32、AMD では32または64(wave64 モード)、Intel ではパイプラインのレジスタ圧力に応じて8/16/32だ。常にランタイム値を 使うこと。32 は絶対に使わない。

サイズの固定

pin.cpp
// VkPipelineShaderStageRequiredSubgroupSizeCreateInfo は
// シェーダーステージにチェインする:
vk::PipelineShaderStageRequiredSubgroupSizeCreateInfo req{};
req.requiredSubgroupSize = 64;   // AMD で wave64 を強制 — あるいは 32、16、8

vk::PipelineShaderStageCreateInfo st{};
st.pNext = &req;
st.stage = vk::ShaderStageFlagBits::eCompute;
// … モジュール、エントリーポイント …
// 許可サイズは VkPhysicalDeviceSubgroupSizeControlProperties::
//   minSubgroupSize … maxSubgroupSize + requiredSubgroupSizeStages から

サイズの固定は、アルゴリズムが特定の幅向けに調整されているときに 重要だ。例えば、32レーンシャッフル向けに書かれたスキャンカーネルは、 コードが32を仮定していると wave64 で正しく動くが遅くなる。

読み取りと固定の使い分け

cases.txt
読み取りのみ(ほとんどのシェーダー):gl_SubgroupSize /
                             SubgroupInvocationID を使い、サイズ非依存の
                             コードを書く — ドライバーがパイプラインごとに
                             効率的な幅を選ぶ
固定(調整済みカーネル):    wavefront スキャン/リダクションカーネルで
                             サブグループが倍になるとスクラッチメモリに
                             爆発する場合 — requiredSubgroupSize を固定
固定(移植性):              全プラットフォームで*最小*サイズを強制し、
                             動作を統一する

実践的なルール

  • VkPhysicalDeviceSubgroupSizeControlProperties:: requiredSubgroupSizeStages を確認する。全ドライバーで全ステージが 固定を受け付けるわけではない。
  • requiredSubgroupSize には subgroupSizeControl フィーチャーと pNext 構造体が必要だ。これは要求ではなく制約だ。ドライバーが 対応できない場合、パイプライン生成は失敗する。
  • subgroupSize(VkPhysicalDeviceSubgroupProperties から)は デフォルトサイズだ。固定しない限り実際のサイズはパイプライン ごとに異なり得る。シェーダー内の gl_SubgroupSize が真実だ。
  • fullSubgroups(VK_EXT_shader_subgroup_ballot)との相互作用: 固定サイズはディスパッチ範囲内で全サブグループが満員であることを 保証する。部分的な末尾サブグループを扱う必要がない。
  • 協調行列(VK_KHR_cooperative_matrix)は gl_ScopeSubgroup を使う。 行列タイル演算はサブグループサイズに暗黙に依存する。カーネルが 16×16タイルをハードコードしているなら固定する。

同じカテゴリの類似記事をチェック: Vulkan C++