可以在内核函数内部的各行之间进行上下文切换吗?
由于我在进行更改之前先设置了一些值,所以我想确保是否设置了该值,然后进行了更改。
答案 0 :(得分:1)
最简单的答案是,是的,上下文切换肯定会在“两线之间”进行。这就是上下文切换的全部要点:如果着色器中的某些行(无论片段,顶点还是内核)需要一些尚不可用的资源(ALU,特殊功能单元,纹理单元,内存),GPU肯定会切换上下文。这称为 latency隐藏,它对于GPU的性能非常重要,因为如果没有它,GPU内核将大部分时间停滞在上述各种资源上。这意味着Metal内核功能绝对不是原子的。
对于您遇到的问题,如果您希望原子地进行某些操作,则有两种主要方法可以使用“金属着色”语言进行处理:
metal_atomic
标头中的原子类型和函数。这是C ++ 14 atomic
标头的子集,它包含原子存储,加载,交换,比较和交换以及获取和修改功能。有关这些功能的更多信息,请参阅Metal Shading Language Specification(有关“线程组和SIMD-group同步功能”的信息,请参阅5.8.1;有关“原子功能”的信息,请参阅5.13)。
通常,如果您的内核函数处理了一些数据(以后需要减少这些数据),则您将执行以下操作(这是一个非常简单的示例):
kernel void
my_kernel(texture2d<half> src [[ texture(0) ]],
texture2d<half, access::write> dst [[ texture(1) ]],
threadgroup float *intermediate [[ threadgroup(0) ]],
ushort2 lid [[ thread_position_in_threadgroup ]],
ushort ti [[ thread_index_in_threadgroup ]],
ushort2 gid [[ thread_position_in_grid ]])
{
// Read data
half4 clr = src.read(gid);
// Do some work for each thread
intermediate[ti] = intermediateResult;
// Make sure threadhroup memory writes are visible to other threads
threadgroup_barrier(mem_flags::mem_threadgroup);
// One thread in the whole threadhgroup calculates some final result
if (lid.x == 0 && lid.y == 0)
{
// Do some work per threadgroup
dst.write(finalResult, gid);
}
}
这里,线程组中的所有线程都从src
纹理读取数据,执行工作,将中间结果存储在线程组内存中,然后计算最终结果并将其写出到纹理dst
。 threadgroup_barrier
确保其他线程(包括将要计算最终结果的thread_position_in_threadgroup
等于(0, 0)
的线程)可以看到内存写入。