gpt4 book ai didi

c - 涉及 sin() 的两个非常相似的函数表现出截然不同的性能——为什么?

转载 作者:太空狗 更新时间:2023-10-29 16:43:59 27 4
gpt4 key购买 nike

考虑以下两个以两种不同方式执行相同计算的程序:

// v1.c
#include <stdio.h>
#include <math.h>
int main(void) {
int i, j;
int nbr_values = 8192;
int n_iter = 100000;
float x;
for (j = 0; j < nbr_values; j++) {
x = 1;
for (i = 0; i < n_iter; i++)
x = sin(x);
}
printf("%f\n", x);
return 0;
}

// v2.c
#include <stdio.h>
#include <math.h>
int main(void) {
int i, j;
int nbr_values = 8192;
int n_iter = 100000;
float x[nbr_values];
for (i = 0; i < nbr_values; ++i) {
x[i] = 1;
}
for (i = 0; i < n_iter; i++) {
for (j = 0; j < nbr_values; ++j) {
x[j] = sin(x[j]);
}
}
printf("%f\n", x[0]);
return 0;
}

当我使用带有 -O3 -ffast-math 的 gcc 4.7.2 编译它们并在 Sandy Bridge 盒子上运行时,第二个程序的速度是第一个程序的两倍。

这是为什么?

一个疑点是 v1i 循环的连续迭代之间的数据依赖性。但是,我不太明白完整的解释是什么。

(问题灵感来自Why is my python/numpy example faster than pure C implementation?)

编辑:

这是为 v1 生成的程序集:

        movl    $8192, %ebp
pushq %rbx
LCFI1:
subq $8, %rsp
LCFI2:
.align 4
L2:
movl $100000, %ebx
movss LC0(%rip), %xmm0
jmp L5
.align 4
L3:
call _sinf
L5:
subl $1, %ebx
jne L3
subl $1, %ebp
.p2align 4,,2
jne L2

对于 v2:

        movl    $100000, %r14d
.align 4
L8:
xorl %ebx, %ebx
.align 4
L9:
movss (%r12,%rbx), %xmm0
call _sinf
movss %xmm0, (%r12,%rbx)
addq $4, %rbx
cmpq $32768, %rbx
jne L9
subl $1, %r14d
jne L8

最佳答案

忽略整个循环结构,只考虑调用sin的顺序。 v1 执行以下操作:

x <-- sin(x)
x <-- sin(x)
x <-- sin(x)
...

也就是说,sin( ) 的每次计算在前一次调用的结果可用之前无法开始;它必须等待整个先前的计算。这意味着对于 sin 的 N 次调用,所需的总时间是单个 sin 评估延迟的 819200000 倍。

相比之下,在 v2 中,您执行以下操作:

x[0] <-- sin(x[0])
x[1] <-- sin(x[1])
x[2] <-- sin(x[2])
...

请注意,每次调用 sin 都不依赖于之前的调用。实际上,对 sin 的调用都是独立的,处理器可以在必要的寄存器和 ALU 资源可用时立即开始每个调用(无需等待前一个计算完成)。因此,所需时间是 sin 函数吞吐量的函数,而不是延迟,因此 v2 可以在更短的时间内完成。


我还应该指出,DeadMG 是正确的,v1v2 在形式上是等价的,在一个完美的世界中,编译器会将它们优化成一个链100000 次 sin 评估(或仅在编译时评估结果)。可悲的是,我们生活在一个不完美的世界。

关于c - 涉及 sin() 的两个非常相似的函数表现出截然不同的性能——为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14468639/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com