我想测试一个函数以验证哪个更快,按值传递还是按引用传递
这是我的测试用例:https://godbolt.org/g/cjaEx3
代码:
struct Vec4f
{
float val[4];
};
Vec4f suma(const Vec4f& a, const Vec4f& b)
{
return {a.val[0] + b.val[0],
a.val[1] + b.val[1],
a.val[2] + b.val[2],
a.val[3] + b.val[3]};
}
Vec4f sumb(Vec4f a, Vec4f b)
{
return {a.val[0] + b.val[0],
a.val[1] + b.val[1],
a.val[2] + b.val[2],
a.val[3] + b.val[3]};
}
使用 -O3 -std=c++14
在 x86-64 clang 上的程序集输出:
suma(Vec4f const&, Vec4f const&): # @suma(Vec4f const&, Vec4f const&)
movq xmm1, qword ptr [rdi] # xmm1 = mem[0],zero
movq xmm0, qword ptr [rsi] # xmm0 = mem[0],zero
addps xmm0, xmm1
movq xmm2, qword ptr [rdi + 8] # xmm2 = mem[0],zero
movq xmm1, qword ptr [rsi + 8] # xmm1 = mem[0],zero
addps xmm1, xmm2
ret
sumb(Vec4f, Vec4f): # @sumb(Vec4f, Vec4f)
addps xmm0, xmm2
addps xmm1, xmm3
ret
事实证明,在 gcc、clang 和 msvc 上,在这种特殊情况下,按值传递会产生更少的汇编。
我的问题是:
- 比较 assembly 线数量通常是比较此类简单功能性能的良好启发式方法吗?
而且我不太了解汇编输出
- 你能解释一下
suma
和sumb
函数的汇编输出吗?
有趣的是,如果我将 Vec4f 改为具有 float val[40]
,这两个函数会产生相同的汇编输出。所以,
- 初始组装差异的原因是什么?
最佳答案
1) 不。并非所有指令的执行时间都相同,一旦需要访问内存,就会有很大的延迟。
2) 和 3)。 suma
需要将a
和b
的内容加载到适当的寄存器中。在 sumb
中,这些值被传递给寄存器中已有的函数。在某些情况下,suma
中的寄存器加载将由 sumb
的调用者完成。在其他情况下,值可能已经在寄存器中,suma
调用者首先需要将这些值存储在内存中,以便它可以创建对它们的引用。
当你使用 float val[40]
时,它超出了寄存器传递值的能力,所以这两个函数都需要先从内存中加载数据(在 suma
中) ,通过取消引用引用;在 sumb
中,通过从堆栈加载值)。
关于c++ - 通过查看程序集比较按值传递与按引用传递的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45135688/