C 在if-else的每种情况下,返回的速度会更快/使用更少的内存吗?
最近,我在CS研究中得到了一个代码示例(参见代码#1),我试图得出我的第二个版本的代码是更快还是使用更少的内存。 你对我的问题有答案吗C 在if-else的每种情况下,返回的速度会更快/使用更少的内存吗?,c,performance,memory,C,Performance,Memory,最近,我在CS研究中得到了一个代码示例(参见代码#1),我试图得出我的第二个版本的代码是更快还是使用更少的内存。 你对我的问题有答案吗 // Code #1 double f(double b, double x) { double s; if (x == 0.0) s = 1.0; else s = sin(x)/x; return s + b; } // Code #2 double f(double b, double x)
// Code #1
double f(double b, double x)
{
double s;
if (x == 0.0)
s = 1.0;
else
s = sin(x)/x;
return s + b;
}
// Code #2
double f(double b, double x)
{
// I thought this would be faster and using less memory due to
// not declaring a new double
if (x == 0.0)
return 1.0 + b;
else
return sin(x)/x + b;
}
谢谢你们的帮助。这取决于编译器和优化标志。通常,这两个代码将给出相同的结果。这取决于编译器和优化标志。一般来说,这两种代码将给出相同的结果。我已经生成了这两种情况的汇编 案例1:
push rbp
mov rbp, rsp
sub rsp, 48
movsd QWORD PTR [rbp-24], xmm0
movsd QWORD PTR [rbp-32], xmm1
pxor xmm0, xmm0
ucomisd xmm0, QWORD PTR [rbp-32]
jp .L2
pxor xmm0, xmm0
ucomisd xmm0, QWORD PTR [rbp-32]
jne .L2
movsd xmm0, QWORD PTR .LC1[rip]
movsd QWORD PTR [rbp-8], xmm0
jmp .L4
.L2:
mov rax, QWORD PTR [rbp-32]
mov QWORD PTR [rbp-40], rax
movsd xmm0, QWORD PTR [rbp-40]
call sin
divsd xmm0, QWORD PTR [rbp-32]
movsd QWORD PTR [rbp-8], xmm0
.L4:
movsd xmm0, QWORD PTR [rbp-8]
addsd xmm0, QWORD PTR [rbp-24]
leave
ret
.LC1:
.long 0
.long 1072693248
案例2:
push rbp
mov rbp, rsp
sub rsp, 32
movsd QWORD PTR [rbp-8], xmm0
movsd QWORD PTR [rbp-16], xmm1
pxor xmm0, xmm0
ucomisd xmm0, QWORD PTR [rbp-16]
jp .L2
pxor xmm0, xmm0
ucomisd xmm0, QWORD PTR [rbp-16]
jne .L2
movsd xmm1, QWORD PTR [rbp-8]
movsd xmm0, QWORD PTR .LC1[rip]
addsd xmm0, xmm1
jmp .L4
.L2:
mov rax, QWORD PTR [rbp-16]
mov QWORD PTR [rbp-24], rax
movsd xmm0, QWORD PTR [rbp-24]
call sin
divsd xmm0, QWORD PTR [rbp-16]
addsd xmm0, QWORD PTR [rbp-8]
.L4:
leave
ret
.LC1:
.long 0
.long 1072693248
没有区别。所以,它们之间没有速度优化。所以,代码优化取决于编译器。我已经生成了这两种情况的汇编 案例1:
push rbp
mov rbp, rsp
sub rsp, 48
movsd QWORD PTR [rbp-24], xmm0
movsd QWORD PTR [rbp-32], xmm1
pxor xmm0, xmm0
ucomisd xmm0, QWORD PTR [rbp-32]
jp .L2
pxor xmm0, xmm0
ucomisd xmm0, QWORD PTR [rbp-32]
jne .L2
movsd xmm0, QWORD PTR .LC1[rip]
movsd QWORD PTR [rbp-8], xmm0
jmp .L4
.L2:
mov rax, QWORD PTR [rbp-32]
mov QWORD PTR [rbp-40], rax
movsd xmm0, QWORD PTR [rbp-40]
call sin
divsd xmm0, QWORD PTR [rbp-32]
movsd QWORD PTR [rbp-8], xmm0
.L4:
movsd xmm0, QWORD PTR [rbp-8]
addsd xmm0, QWORD PTR [rbp-24]
leave
ret
.LC1:
.long 0
.long 1072693248
案例2:
push rbp
mov rbp, rsp
sub rsp, 32
movsd QWORD PTR [rbp-8], xmm0
movsd QWORD PTR [rbp-16], xmm1
pxor xmm0, xmm0
ucomisd xmm0, QWORD PTR [rbp-16]
jp .L2
pxor xmm0, xmm0
ucomisd xmm0, QWORD PTR [rbp-16]
jne .L2
movsd xmm1, QWORD PTR [rbp-8]
movsd xmm0, QWORD PTR .LC1[rip]
addsd xmm0, xmm1
jmp .L4
.L2:
mov rax, QWORD PTR [rbp-16]
mov QWORD PTR [rbp-24], rax
movsd xmm0, QWORD PTR [rbp-24]
call sin
divsd xmm0, QWORD PTR [rbp-16]
addsd xmm0, QWORD PTR [rbp-8]
.L4:
leave
ret
.LC1:
.long 0
.long 1072693248
没有区别。所以,它们之间没有速度优化。所以,代码优化依赖于编译器。只声明变量并不是唯一占用内存的事情
int a = 1 + 2;
int b = 3;
int c = a + b;
此代码将采用与以下代码相同的值
int c = 1 + 2 + 3;
因为最终处理器将在单核中一次执行一个操作。第二个代码添加两个数字并将其保存在堆栈中,然后将第三个数字添加到前两个数字的结果中。仅声明变量并不是唯一占用内存的事情
int a = 1 + 2;
int b = 3;
int c = a + b;
此代码将采用与以下代码相同的值
int c = 1 + 2 + 3;
因为最终处理器将在单核中一次执行一个操作。第二个代码添加两个数字并将其保存在堆栈中,然后将第三个数字添加到前两个数字的结果中。简短回答:不用担心 长答覆:
sin
在这个函数中花费的时间最多,因此如果有一些额外的指令,也不会有任何明显的效果
尽管有疑问,在生成的代码
对于x86_64上的GCC 6.3,第一个版本使用了1个寄存器(xmm2),但优化器能够更好地对指令重新排序
第1版:
ucomisd xmm1, QWORD PTR .LC1[rip]
movapd xmm2, xmm0
jp .L5
movsd xmm0, QWORD PTR .LC0[rip]
je .L7
.L5:
movapd xmm0, xmm1
sub rsp, 24
movsd QWORD PTR [rsp+8], xmm2
movsd QWORD PTR [rsp], xmm1
call sin
movsd xmm1, QWORD PTR [rsp]
movsd xmm2, QWORD PTR [rsp+8]
add rsp, 24
divsd xmm0, xmm1
addsd xmm0, xmm2
ret
.L7:
addsd xmm0, xmm2
ret
第2版:
ucomisd xmm1, QWORD PTR .LC0[rip]
jp .L2
je .L10
.L2:
sub rsp, 24
movsd QWORD PTR [rsp], xmm0
movapd xmm0, xmm1
movsd QWORD PTR [rsp+8], xmm1
call sin
movsd xmm1, QWORD PTR [rsp+8]
divsd xmm0, xmm1
addsd xmm0, QWORD PTR [rsp]
add rsp, 24
ret
.L10:
addsd xmm0, QWORD PTR .LC1[rip]
ret
那么这两个版本在性能上有多大差异呢?只有性能测试才能确定(但我猜你不会看到任何区别)。简短回答:别担心 长答覆:
sin
在这个函数中花费的时间最多,因此如果有一些额外的指令,也不会有任何明显的效果
尽管有疑问,在生成的代码
对于x86_64上的GCC 6.3,第一个版本使用了1个寄存器(xmm2),但优化器能够更好地对指令重新排序
第1版:
ucomisd xmm1, QWORD PTR .LC1[rip]
movapd xmm2, xmm0
jp .L5
movsd xmm0, QWORD PTR .LC0[rip]
je .L7
.L5:
movapd xmm0, xmm1
sub rsp, 24
movsd QWORD PTR [rsp+8], xmm2
movsd QWORD PTR [rsp], xmm1
call sin
movsd xmm1, QWORD PTR [rsp]
movsd xmm2, QWORD PTR [rsp+8]
add rsp, 24
divsd xmm0, xmm1
addsd xmm0, xmm2
ret
.L7:
addsd xmm0, xmm2
ret
第2版:
ucomisd xmm1, QWORD PTR .LC0[rip]
jp .L2
je .L10
.L2:
sub rsp, 24
movsd QWORD PTR [rsp], xmm0
movapd xmm0, xmm1
movsd QWORD PTR [rsp+8], xmm1
call sin
movsd xmm1, QWORD PTR [rsp+8]
divsd xmm0, xmm1
addsd xmm0, QWORD PTR [rsp]
add rsp, 24
ret
.L10:
addsd xmm0, QWORD PTR .LC1[rip]
ret
那么这两个版本在性能上有多大差异呢?只有性能测试才能确定(但我猜你不会看到任何区别)。c++不是c,请只选择一个标记,这样你就可以得到你需要的答案除非你使用的编译器是****,否则它们可能会被优化到相同的代码。你总是可以自己拆开看看。理论上第二种可能会更快,只是在实践中可能不会。没有区别。编译器可以很容易地进行这样的转换。无论如何,
sin(x)
将花费最多的时间。@George-几乎相同的代码()@HB-这在代码审查中是离题的。不要随便地建议它。C++不是C,请只选择一个标签,这样你就可以得到你需要的答案,除非你使用的编译器是***,否则它们可能会被优化到相同的代码。你总是可以自己拆开看看。理论上第二种可能会更快,只是在实践中可能不会。没有区别。编译器可以很容易地进行这样的转换。无论如何,sin(x)
将花费最多的时间。@George-几乎相同的代码()@HB-这在代码审查中是离题的。不要胡说。那是什么?.LC1[rip]
?它会做什么?那是什么?它能做什么?