在 Mac OS X 上,通过引用传递向量还是通过值传递向量更有效?

Posted

技术标签:

【中文标题】在 Mac OS X 上,通过引用传递向量还是通过值传递向量更有效?【英文标题】:On Mac OS X, is it more efficient to pass vectors by reference or by value? 【发布时间】:2013-05-16 22:33:11 【问题描述】:

Clang 有一个 C/C++ 扩展,它允许您将向量值视为一等公民:

typedef double double4 __attribute__((ext_vector_type(4));
// easy assignment
double4 a = 1, 2, 3, 4;
double4 b = 4, 3, 2, 1;
// basic operators work component-wise
double4 c = a + b; // 5, 5, 5, 5
// you can even swizzle elements!
double4 d = a.zyxw; // 3, 2, 1, 4

我相信这些向量会利用底层平台的 SIMD 指令(英特尔 Mac 上的 SSE,ARM 上的 NEON)。但是,我不太确定 Mac OS 调用约定如何处理向量类型。

通过引用或复制传递向量会更有效吗?差异可能不会很大,但由于我会传递很多向量,我想我可能会尽快养成正确的习惯。

【问题讨论】:

SSE 寄存器是 128 位宽,但 double4 是 256 位宽。 @DietrichEpp,据我了解,AVX 带来了 256 位 ymm0-ymm15 寄存器(xmm 现在指的是低 128 位)。 AVX 默认不启用。 @DietrichEpp 由什么启用? Mac OS X 从 10.6.8 开始支持它们。如果只是编译器切换的问题,那听起来还不错。 对。我就是这个意思。默认不启用,必须使用-mavx编译器标志。 【参考方案1】:

快速测试表明,在您的示例中,double4 参数在堆栈上传递,但在寄存器 xmm0 和 xmm1 中返回。这有点奇怪。另一方面,float4 参数在寄存器 xmm0 到 xmm7 中传递,结果在 xmm0 中返回,正如您所期望的那样。

Apple 使用System V 应用程序二进制接口。 AMD64 架构处理器补充。 适用于 Mac OS X。如果我正确解释该文档,则所有内容都应在寄存器中传递。我不确定clang在这里做什么。也许这仍在进行中,将来可能会改变?如果他们这样做了,当您尝试混合新旧行为时,它可能会破坏您的程序。

为了性能,使用 clang 传递每个值的向量不是问题。如果您的功能不是非常短,则应该没有明显的区别。如果您确实使用了非常小的函数,您应该尝试说服编译器内联它们(例如,通过声明它们 static)。

编辑:关于 AVX 扩展:如果启用它们,编译器将使用寄存器 ymm0 到 ymm7 作为参数,使用 ymm0 作为结果。在这种情况下,double4 占用单个 ymm 寄存器,而不是 xmm 寄存器对。

【讨论】:

如何在xmm0 中返回?它是必要宽度的一半。 @zneak 一个 float4 是 128 位,并且适合 xmm0。 double4 为 256 位,在寄存器对 xmm0 和 xmm1(缩写为 xmm0/1)中返回。

以上是关于在 Mac OS X 上,通过引用传递向量还是通过值传递向量更有效?的主要内容,如果未能解决你的问题,请参考以下文章

通过引用函数传递向量,但更改不会持续

无法在 Mac OS X 上通过 jinfo 启用 DTrace 探测

用Mac OS X 10.7的vecLib框架将矩阵和向量相乘的问题

通过引用传递向量内联

在 Mac OS X 上打开时 IDLE 崩溃

通过引用传递向量的 typedef 向量