Metalは、GPUがテクスチャリング(または計算)を実行している間、1D、2D、または3Dメッシュで設定されたカーネル関数を実行します。
グリッド内の各ポイントは、スレッドと呼ばれるカーネル関数のインスタンスを表します。
たとえば、画像処理では、グリッドは通常、画像全体を表すスレッドの2Dマトリックスであり、各スレッドは処理される画像の1つのピクセルに対応します。
スレッドはスレッドグループ(スレッドグループ)に編成され、これらのスレッドグループは一緒に実行され、共通のメモリブロックを共有できます。カーネル関数は、スレッドを互いに独立して実行するように設計されている場合もありますが、スレッドグループ内のスレッドがワーキングセットで連携することも一般的です。
次の図は、コンピューティングコアが処理中のイメージをスレッドグループに分割する方法と、各スレッドグループが個々のスレッドで構成される方法を示しています。各スレッドは1ピクセルを処理します。
グリッド内の位置でスレッドを識別します
スレッドはグリッド内の位置によって識別できます。カーネル関数がスレッドごとに異なることを実行できるのは、この一意の位置です。
次のカーネル関数の例は、グリッド内のスレッドの位置を引数として関数に渡す方法を示しています。この場合、パラメータgid
は、テクスチャ内の特定の場所の読み取りと書き込みに使用される2D座標を表すベクトルです。
kernel void
grayscaleKernel(texture2d<half, access::read> inTexture [[texture(AAPLTextureIndexInput)]],
texture2d<half, access::write> outTexture [[texture(AAPLTextureIndexOutput)]],
uint2 gid [[thread_position_in_grid]])
{
if((gid.x >= outTexture.get_width()) || (gid.y >= outTexture.get_height()))
{
return;
}
half4 inColor = inTexture.read(gid);
half gray = dot(inColor.rgb, kRec709Luma);
outTexture.write(half4(gray, gray, gray, 1.0), gid);
}
复制代码
[[thread_position_in_grid]]
属性修飾子です。角括弧構文で識別できるプロパティ修飾子。この値がグリッド内のスレッドの位置であることを示す属性修飾子。
たとえば、16x16スレッドのグリッドが8x4スレッドの2x4スレッドグループに分割されている場合、グリッド内の1つのスレッド(図に赤で表示)の位置は(9,10)です。
スレッドグループ内の位置によってスレッドを識別します
次のコードを使用すると、グリッド内のスレッドの位置は、そのスレッドグループ内のスレッドの位置と、グリッド内のそのスレッドグループのサイズと位置に基づいて計算できます。
kernel void
myKernel(uint2 threadgroup_position_in_grid [[ threadgroup_position_in_grid ]],
uint2 thread_position_in_threadgroup [[ thread_position_in_threadgroup ]],
uint2 threads_per_threadgroup [[ threads_per_threadgroup ]])
{
uint2 thread_position_in_grid =
(threadgroup_position_in_grid * threads_per_threadgroup) +
thread_position_in_threadgroup;
}
复制代码
[[threadgroup_position_in_grid]]
グリッド内のスレッドグループの位置
[[thread_position_in_threadgroup]]
スレッドグループ内のスレッドの位置
例:スレッドはグリッド内の位置(1,2)のスレッドグループにあり、このスレッドグループ内の位置は(1,2)です。