4

我正在制作一个向量/矩阵库。(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”以反映建议。
4

1 回答 1

4

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

如果您可以依靠您的always_inline属性始终内联函数,那么您也不应该通过指针传递 Vector(如果未修改)。这样做的原因是通过指针传递它需要获取向量的地址,这意味着编译器必须确保它有一个地址,因此它不能只存在于 CPU 寄存器中。如果不需要,这可能会减慢速度,并且当您获取某物的地址时,编译器将始终确保它具有地址,因为编译器无法确定不需要该地址。

由于指针传递,这段代码总是有一条指令来获取对象的地址,并且至少有一个取消引用来获取成员的值。如果您按值传递,那么这可能仍然会发生,但编译器可能能够优化所有这些。

不要忘记过度使用内联会显着增加编译器二进制代码的大小。在某些情况下,具有较大的代码段(由于内联函数)可能会导致更多的指令缓存未命中,这将导致性能下降,因为 CPU 不断地不得不去主内存来获取程序的一部分,因为其中一些是太大而无法放入小型 L1 缓存中。这在嵌入式处理器(如 iPhone)中可能尤其重要,因为这些处理器通常具有小型缓存。

于 2010-05-01T14:03:56.287 回答