我有一个基于金属的核心图像卷积内核,它使用half
精度变量来跟踪总和和权重。然而,我现在认为16位half
的范围在某些情况下是不够的,这意味着我需要32位float
用于某些变量。
现在我想知道哪个更高效:
- 尽可能多地使用
half
(对于采样器和大多数本地变量),仅在需要时转换为float
(这意味着相当多,在循环内) - 或将所有采样器和本地变量更改为
float
类型,以便不需要转换。
前者意味着所有的算术运算都以32位精度执行,尽管只在某些操作中需要。
我可以运行任何文档或基准来查找金属中float
↔︎half
转换的成本吗?
我认为你应该选择选项A:
使用尽可能多的一半(对于采样器和大多数局部变量),并且只在需要时转换为float(这意味着在循环内相当多)
基于WWDC 2016题为"Advanced Metal Shader optimization"的演讲中的讨论;联系。
在17:17-18:58之间是本主题的相关部分。演讲者Fiona提到了几件重要的事情:
- A8和更高版本的gpu具有16位寄存器,这意味着32位浮点格式(如
float
)使用两倍的寄存器,这意味着两倍的带宽,能量等。所以使用half
可以节省寄存器(这总是好的)和能量 - 在A8和更高版本的gpu上,数据类型转换通常是自由的,即使在float和half之间也是。Fiona甚至提出了你可能会问自己的问题,包括我认为你关心的所有转换,并说它仍然可能很快,因为转换是免费的。此外,根据金属着色语言规范版本2.3(第218页)
对于具有半精度浮点像素颜色值的纹理,从半精度到浮点的转换是无损的
这样你就不用担心精度的损失了。
在该部分中还有其他一些值得研究的相关要点,但我认为这足以证明选择A