我正在制作矢量/矩阵库。 (GCC,Arm Neon,iPhone)

typedef struct{ float v[4]; } Vector;
typedef struct{ Vector v[4]; } Matrix;

我将结构数据作为指针传递,以避免在调用功能时从数据复制中降低性能。因此,我一开始像这样设计了这样的功能:

void makeTranslation(const Vector* factor, Matrix* restrict result);

但是,如果函数是内联的,是否有任何理由将值作为性能指针传递给指针?这些变量也会被复制吗?注册和缓存怎么样?我试图这样重新设计函数:

inline Matrix makeTranslation(const Vector factor) __attribute__ ((always_inline));

您如何看待每种情况的呼叫费用?

  • 我在第二个签名中添加了“ const”以反映建议。
有帮助吗?

解决方案

当函数为内联时,通常不直接与呼叫涉及变量的复制。有时仍将变量移动并放在堆栈上,作为执行的正常部分,而不是函数调用的直接结果。 (当您用完寄存器时,某些值可能会被放在堆栈等上等...但是只有在需要时。)因此,“呼叫”的开销基本上在函数被嵌入时会消失(不再设置/拆除/拆除堆栈框架,不再有无条件的跳跃,不再推动/弹出参数。)

如果你能依靠你的 always_inline 属性为 总是 内联函数,那么您也不应通过指针传递向量(如果未修改)。这样做的原因是,通过指针将其传递需要进行向量的地址,这意味着编译器必须确保其具有地址,因此不能仅存在于CPU寄存器中。如果不需要的话,这可能会放慢速度,当您采用某物的地址时,编译器将始终确保它具有地址,因为编译器无法确定不需要地址。

由于逐个定位,此代码将始终具有获取对象地址的指令,并且至少有一个解雇以获取成员的价值。如果您通过价值传递,那么这可能仍然会发生,但是编译器可能能够优化所有这些。

不要忘记,过度使用内部会大大增加编译器二进制代码的大小。在某些情况下,具有较大的代码段(由于内联函数的结果)可能会导致更多的指令缓存失误会导致性能较慢,因为CPU不断不得不出门到主内存以获取程序的部分,因为其中一些是其中的部分太大了,无法适应小的L1缓存。这在嵌入式处理器(例如iPhone)中尤其重要,因为这些处理器通常具有小缓存。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top