And*_*nko 3 c optimization performance
见过类似的问题,但它们与缓存未命中或代码重新排序有关。在我的例子中,这些都没有发生。
代码很简单:
#include <stdio.h>
#include <time.h>
void main()
{
unsigned char a, b;
int i;
clock_t before = clock();
for (i = 0; i < 10000000; i++) {
a *= 2;
b *= 2;
}
printf("elapsed: %lu\n", clock() - before);
before = clock();
for (i = 0; i < 10000000; i++) {
a *= 2;
a *= 2;
}
printf("elapsed: %lu\n", clock() - before);
}
Run Code Online (Sandbox Code Playgroud)
所以有两个变量a和b,我用它们做一些事情(做什么并不重要)。第一个循环修改a和b,第二个循环a仅修改 。只能是b也好,无所谓。
第二个循环大约花费两倍的时间。
a *= 2和的装配线b *= 2如下所示:
sal BYTE PTR -1[rbp]
sal BYTE PTR -2[rbp]
Run Code Online (Sandbox Code Playgroud)
对于第二个循环,它们看起来像这样:
sal BYTE PTR -2[rbp]
sal BYTE PTR -2[rbp]
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,操作数量相同,操作相同,内存访问相同,并且不可能存在缓存未命中。唯一的区别在于-1[rbp]和之间-2[rbp]。
那么为什么第二个循环需要两倍的时间呢?我只能猜测它与在两个连续操作中访问相同的变量有关。我可以想象,第一个操作需要一些时间才能完成,然后第二个操作才能访问相同的变量。而在第一个循环中,第一个操作是在一个 var 上执行的,第二个操作是在另一个 var 上执行的,因此它们是独立的,不必彼此等待。但这应该意味着 CPU 级别上的一些微并行性。真的吗?
您还可以在此处在线运行该程序: https: //onlinegdb.com/27qixKsWP
第一个循环可以是流水线式的,因为两条指令在不同的内存位置上运行。两个乘法可以同时进行。
第二个循环在同一内存位置上运行,因此第二个乘法必须等待第一个乘法完成。