也见过类似的问题,但它们与缓存未命中或代码重新排序有关.在我的情况下,这些都不会发生.
代码非常简单:
#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);
}
所以有两个变量a
和b
,我用它们做一些事情(做什么并不重要).
第一个循环修改a
和b
,第二个循环仅修改a
.可以只有b
就好了,没关系.
第二个循环大约需要两倍的时间.
a *= 2
和b *= 2
的装配线如下所示:
sal BYTE PTR -1[rbp]
sal BYTE PTR -2[rbp]
对于第二个循环,它们看起来如下所示:
sal BYTE PTR -2[rbp]
sal BYTE PTR -2[rbp]
正如您所看到的,操作的数量是相同的,操作是相同的,内存访问是相同的,并且不可能发生缓存未命中.唯一的区别是在-1[rbp]
和-2[rbp]
之间.
那么,为什么第二次循环需要两倍的时间呢?我只能猜测它在某种程度上与在两个连续操作中访问相同的变量有关.我可以想象,第一个操作需要一些时间来完成,第二个操作才能访问相同的var.而在第一个循环中,第一个操作是在一个变量上执行的,第二个操作是在另一个变量上执行的,因此它们是独立的,不必相互等待.但这应该意味着在CPU级别上存在一些微并行性.这是真的吗?
您也可以在以下位置在线运行该程序: https://onlinegdb.com/27qixKsWP个