【发布时间】:2017-03-01 15:38:49
【问题描述】:
警告:实际上这不是由于 2 的幂,而是由于奇偶性。请参阅编辑部分。
我发现了一段代码,它表现出非常奇怪的行为。
代码使用二维数组(大小 x 大小)。 当 size 是 2 的幂时,代码会慢 10% 到 40%,最慢的是 size=32。
我使用英特尔编译器获得了这些结果。如果我使用 gcc 5.4 进行编译,2 的力量就会消失,但 代码会慢 3 倍。在不同的 CPU 上对其进行了测试,我认为它应该具有足够的重现性。
代码:
#define N 10000000
unsigned int tab1[TS][TS];
void simul1() {
for(int i=0; i<TS; i++)
for(int j=0; j<TS; j++) {
if(i > 0)
tab1[i][j] += tab1[i-1][j];
if(j > 0)
tab1[i][j] += tab1[i][j-1];
}
}
int main() {
for(int i=0; i<TS; i++)
for(int j=0; j<TS; j++)
tab1[j][i] = 0;
for(int i=0; i<N; i++) {
tab1[0][0] = 1;
simul1();
}
return tab1[10][10];
}
编译:
icc:
icc main.c -O3 -std=c99 -Wall -DTS=31 -o i31
icc main.c -O3 -std=c99 -Wall -DTS=32 -o i32
icc main.c -O3 -std=c99 -Wall -DTS=33 -o i33
gcc:
gcc main.c -O3 -std=c99 -Wall -DTS=31 -o g31
gcc main.c -O3 -std=c99 -Wall -DTS=32 -o g32
gcc main.c -O3 -std=c99 -Wall -DTS=33 -o g33
Xeon E5 上的结果:
time ./icc31
4.549s
time ./icc32
6.557s
time ./icc33
5.188s
time ./gcc31
13.335s
time ./gcc32
13.669s
time ./gcc33
14.399s
我的问题:
- 为什么数组的大小正好是 32 时会出现性能损失?
- (可选:这里为什么 icc 比 gcc 快 3 倍?)
编辑:实际上这是由于奇偶性,并且仅适用于大小> = 32。偶数和奇数之间的性能差异是一致的,并且随着大小变大而减小。这是一个更详细的基准:
(y 轴是每秒的元素数,以百万为单位,用 TS² * N / size / 1000000 获得)
我的 CPU 有 32KB L1 缓存和 256 KB L2
【问题讨论】:
-
时间保持一致是执行顺序改变了吗?
-
额外问题:我刚刚检查了 Godbolt:
icc和clang生成矢量化代码,而gcc没有 -
要推断 gcc 和 icc 之间的 3 倍差异,您可以查看生成的程序集。可以通过传递 -S 标志来生成程序集。
-
注意比较时间,只有数组的sizeof应该改变,使用
for(int i=0; i<31; i++) for(int j=0; j<31; j++)。 32x32 循环应该比 31x31 长 6%。那么问题是为什么 33x33 比 32x32 快? -
你应该检查这个线程的答案stackoverflow.com/questions/11413855/…
标签: c performance gcc optimization icc