Macos 如何用金属制作模板计算内核
我一直在写一些金属计算内核。因此,我用以下声明编写了一个内核:Macos 如何用金属制作模板计算内核,macos,gpu,gpgpu,metal,Macos,Gpu,Gpgpu,Metal,我一直在写一些金属计算内核。因此,我用以下声明编写了一个内核: kernel void myKernel(const device uint32_t *inData [[buffer(MyKernelIn)]], device uint32_t *outData [[buffer(MyKernelOut)]], uint2 gid [[thread_position_in_grid]],
kernel void
myKernel(const device uint32_t *inData [[buffer(MyKernelIn)]],
device uint32_t *outData [[buffer(MyKernelOut)]],
uint2 gid [[thread_position_in_grid]],
uint2 thread_position_in_threadgroup [[thread_position_in_threadgroup]],
uint2 threads_per_threadgroup [[threads_per_threadgroup]],
uint2 threadgroup_position_in_grid [[threadgroup_position_in_grid]])
{ }
现在,我想写一个变量,它接受uint8\t
类型的inData
和float
,我该怎么做呢
我可以想到的可能方法:
inData
和outData
中读取/写入任何内存位置。这意味着我创建的任何临时数据也将使用这种逻辑进行铸造。(这将再次在内核代码中引发大量间接操作,不确定它将如何影响我的性能)MTLTexture
上工作,该着色器指定pixelFormat
,并且基于该pixelFormat
,MPS可以在大范围的数据类型上工作。对如何做到这一点有什么见解吗
谢谢 一种可行的方法是:
- 将
声明为inData
void*
- 在内核着色器的主体中,调用模板函数,传递参数。模板函数将按所需类型进行模板化,并将接收
作为指向该类型的指针inData
constant int variant [[function_constant(0)]];
template<typename T> void
work(const device void *inData,
device uint32_t *outData,
uint2 gid,
uint2 thread_position_in_threadgroup,
uint2 threads_per_threadgroup,
uint2 threadgroup_position_in_grid)
{
const device T *data = static_cast<const device T*>(inData);
// ...
}
kernel void
myKernel(const device void *inData [[buffer(MyKernelIn)]],
device uint32_t *outData [[buffer(MyKernelOut)]],
uint2 gid [[thread_position_in_grid]],
uint2 thread_position_in_threadgroup [[thread_position_in_threadgroup]],
uint2 threads_per_threadgroup [[threads_per_threadgroup]],
uint2 threadgroup_position_in_grid [[threadgroup_position_in_grid]])
{
if (variant == 0)
work<uint32_t>(inData, outData, gid, thread_position_in_threadgroup,
threads_per_threadgroup, threadgroup_position_in_grid);
else if (variant == 1)
work<uint8_t>(inData, outData, gid, thread_position_in_threadgroup,
threads_per_threadgroup, threadgroup_position_in_grid);
else
work<float>(inData, outData, gid, thread_position_in_threadgroup,
threads_per_threadgroup, threadgroup_position_in_grid);
}
常量int变量[[函数_常量(0)];
模板空隙
工作(const device void*inData,
设备uint32_t*输出数据,
uint2 gid,
uint2螺纹在螺纹组中的位置,
每个螺纹组的uint2螺纹,
uint2螺纹组(网格中的位置)
{
常量设备T*数据=静态广播(inData);
// ...
}
内核空洞
myKernel(const device void*inData[[buffer(MyKernelIn)]],
设备uint32_t*outData[[buffer(MyKernelOut)],
uint2 gid[[螺纹位置在网格中],
uint2螺纹组中的螺纹位置[[螺纹组中的螺纹位置],
uint2线程每线程组[[线程每线程组]],
uint2线程组在网格中的位置[[线程组在网格中的位置])
{
如果(变量==0)
工作(inData、outData、gid、螺纹组中的螺纹位置、,
每个线程组的线程数,线程组在网格中的位置);
else if(变量==1)
工作(inData、outData、gid、螺纹组中的螺纹位置、,
每个线程组的线程数,线程组在网格中的位置);
其他的
工作(inData、outData、gid、螺纹组中的螺纹位置、,
每个线程组的线程数,线程组在网格中的位置);
}
谢谢!只是一个简单的问题,因为function\u常量将在MTLFunction
上设置,这是否意味着,我必须为变量的每个新值创建一个新的MTLComputePipelineState
?是的。如果您不想这样做,您可以将variant
作为制服传入。这可能会影响性能。我不知道,但我怀疑这会很轻微。