Metal如何将图像块分配给每个线程组?

Posted

技术标签:

【中文标题】Metal如何将图像块分配给每个线程组?【英文标题】:How Metal distribute the image block to each thread group? 【发布时间】:2019-04-19 21:39:53 【问题描述】:

例如,如果我要进行灰度转换,我需要通过以下方式设置我的threadsPerGroup和线程组。

NSUInteger maxTotalThreadsPerThreadgroup = [self.computePipelineState maxTotalThreadsPerThreadgroup];
MTLSize threadgroupCounts = MTLSizeMake(threadExecutionWidth * 2, threadExecutionWidth * 2, 1);
MTLSize threadsPerThreadGroup = MTLSizeMake([self.texutre width] / threadgroupCounts.width + 1,
[self.texutre height] / threadgroupCounts.height + 1,
1);

我知道图像会被分割成不同的块,每个块将由一个线程组处理。但好像在内核中,我们只会读取二维纹理,然后输出处理后的纹理。

但问题是如何将图像切成不同的 2d 纹理?我们如何知道每个图像块是否被分配给一个线程来处理?这是由 Metal 自己完成的吗?或者我们需要使用 gid 手动将每个块分配给每个线程组?

【问题讨论】:

【参考方案1】:

Metal 不知道也不关心您的着色器是否在图像上运行。它不会“切割”图像或类似的东西。

计算着色器在“网格”上进行处理。网格是一种抽象。这是您组织工作的任意方式。 Metal 不会为网格分配任何意义,例如将网格中的位置与图像中的像素相关联。

这种关联(如果存在)隐含在着色器代码的行为方式中。是的,这主要基于着色器对thread_position_in_gridthread_position_in_threadgroupthread_index_in_threadgroup 等所做的操作。

因此,如果您使用带有thread_position_in_grid 属性的gid 变量,并且将其坐标用作图像坐标,那么这种用法决定了每个网格位置对应于图像像素。一旦你这样做了,那么每个线程组都对应于图像的一个块,因为一个线程组只是一个网格位置块。不过,这又不是 Metal 正在做的事情,而是您的着色器正在做的事情。

你可以做一些完全不同的事情,Metal 不会在意。

【讨论】:

以上是关于Metal如何将图像块分配给每个线程组?的主要内容,如果未能解决你的问题,请参考以下文章

Java 多线程进阶-并发编程 线程组ThreadGroup

计算内核的网格和块尺寸

多线程可以加速内存分配吗?

Java的多线程

如何将用户定义的变量值限制为jmeter中的特定线程组

Servlet容器如何同时来处理多个请求