私はMTLTexture
に16ビット符号なし整数(MTLPixelFormatR16Uint
)を含んでいます。値は約7000から20000の範囲で、0が 'nodata'値として使用されます。そのため、以下のコードでは省略されています。最小値と最大値を探して、0〜255の間でこれらの値を再スケーリングできるようにしたいと思います。最終的には、データのヒストグラムに最小値と最大値を設定することになりますが(これにはいくつかの異常値があります)、今は単純に最小値/最大値を抽出しています。金属テクスチャ内の最小値と最大値を見つける
私はGPUからCPUにデータを読み込み、最小/最大値を引き出すことができますが、GPUでこのタスクを実行することをお勧めします。
コマンドエンコーダがスレッドグループ当たり16×16スレッドをディスパッチさ
最初の試みは、スレッドグループの数は、テクスチャサイズに基づいている(例えば、幅= textureWidth/16、高さ= textureHeight/16 )。
typedef struct {
atomic_uint min;
atomic_uint max;
} BandMinMax;
kernel void minMax(texture2d<ushort, access::read> band1 [[texture(0)]],
device BandMinMax &out [[buffer(0)]],
uint2 gid [[thread_position_in_grid]])
{
ushort value = band1.read(gid).r;
if (value != 0) {
uint currentMin = atomic_load_explicit(&out.min, memory_order_relaxed);
uint currentMax = atomic_load_explicit(&out.max, memory_order_relaxed);
if (value > currentMax) {
atomic_store_explicit(&out.max, value, memory_order_relaxed);
}
if (value < currentMin) {
atomic_store_explicit(&out.min, value, memory_order_relaxed);
}
}
}
これより最小値と最大値が得られますが、同じデータセットでは最小値と最大値が異なる値を返すことがよくあります。これは、複数のスレッドが実行されている場合、単一スレッドからの最小値と最大値です。
第二の試行前の試行で
ビル、私はそれぞれのスレッドから個々の最小/最大値を格納しています。この時、すべて256(16×16)。
kernel void minMax(texture2d<ushort, access::read> band1 [[texture(0)]],
device BandMinMax *out [[buffer(0)]],
uint2 gid [[thread_position_in_grid]],
uint tid [[ thread_index_in_threadgroup ]])
{
ushort value = band1.read(gid).r;
if (value != 0) {
uint currentMin = atomic_load_explicit(&out[tid].min, memory_order_relaxed);
uint currentMax = atomic_load_explicit(&out[tid].max, memory_order_relaxed);
if (value > currentMax) {
atomic_store_explicit(&out[tid].max, value, memory_order_relaxed);
}
if (value < currentMin) {
atomic_store_explicit(&out[tid].min, value, memory_order_relaxed);
}
}
}
これは、最小値/最大値の256セットを含む配列を返します。これらから、私は最小値の最低値を見つけることができたと思いますが、これは貧弱なアプローチのようです。正しい方向にポインタを感謝します、ありがとう!
ありがとう@warrenm、動作しているようです。アトミックバッファのオフセットに関する質問があります。例えば、 'atomicBuffer +((tgpig [1] * tpt [0] + tgpig [0])* 2)'となります。私の理解は、アトミック操作がスレッドグループごとに適用されることです(間違っていれば、これらの前提条件のいずれかを修正してください)? 'threads_per_threadgroup'アノテーションを使って' tpt'変数にカーネルに渡されるスレッドグループによる16x16スレッドを使用します。これがスレッドグループグリッドの幅であるかどうかはわかりませんか?例えば;テクスチャのサイズは192x160で、スレッドグループのグリッドは12x10で、offsetは 'atomicBuffer +((tgpig [1] * 12 + tgpig [0])* 2)'ですか? – lock
最後の行でハードコーディングされた12を許してください。私は、min_max_per_threadgroupカーネルで 'threads_per_threadgroup'を' threadgroups_per_grid'に置き換えていると言っています。 – lock
@lockはい、あなたは絶対に正しいです。 'threads_per_threadgroup'が' threadgroups_per_grid'と等しくなったので、私の実装では運が良かったです。上記を訂正。 – warrenm