我最初的直覺是,每個數組的循環會更好地工作,因爲數據的局部性將有助於緩存。
讓一個循環中的所有數組都會污染高速緩存(處理第一個數組時,高速緩存將由該數組的某些元素(部分)填充,但是在下一行代碼中,需要數據第二個數組和緩存將無法幫助)。
這兩種情況下的理論複雜性都保持不變。
但是,它取決於你有數組的數量(我不是說現在連續)。從頭有循環一次又一次可以擊敗緩存加速是每個循環一個陣列的方法可以提供,如下面所示:
Georgioss-MacBook-Pro:~ gsamaras$ cat bigloop.c
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#define N 100000
typedef struct timeval wallclock_t;
void wallclock_mark(wallclock_t *const tptr);
double wallclock_since(wallclock_t *const tptr);
// gcc -Wall -O3 bigloop.c -o bigloop
int main(void)
{
int a[N], b[N], c[N], d[N], e[N], i;
wallclock_t t;
double s;
wallclock_mark(&t);
for(i = 0; i < N; ++i)
{
a[i] = i * 10 + (i - 2);
b[i] = i * 9 + (i - 3);
c[i] = i * 8 + (i - 1);
d[i] = i * 11 + (i - 5);
e[i] = i * 5 + (i - 0);
}
s = wallclock_since(&t);
printf("Populating took %.9f seconds wall clock time.\n", s);
wallclock_mark(&t);
for(i = 0; i < N; ++i)
{
a[i] = e[i] + (i - 1);
b[i] = d[i] + (i + 3);
c[i] = a[i] - (i + 2);
d[i] = b[i] + (i - 2);
e[i] = a[i] + (i - 4);
}
s = wallclock_since(&t);
printf("Load/write took %.9f seconds wall clock time.\n", s);
return 0;
}
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#define N 100000
typedef struct timeval wallclock_t;
void wallclock_mark(wallclock_t *const tptr);
double wallclock_since(wallclock_t *const tptr);
int main(void)
{
int a[N], b[N], c[N], d[N], e[N], i;
wallclock_t t;
double s;
wallclock_mark(&t);
for(i = 0; i < N; ++i)
a[i] = i * 10 + (i - 2);
for(i = 0; i < N; ++i)
b[i] = i * 9 + (i - 3);
for(i = 0; i < N; ++i)
c[i] = i * 8 + (i - 1);
for(i = 0; i < N; ++i)
d[i] = i * 11 + (i - 5);
for(i = 0; i < N; ++i)
e[i] = i * 5 + (i - 0);
s = wallclock_since(&t);
printf("Populating took %.9f seconds wall clock time.\n", s);
wallclock_mark(&t);
for(i = 0; i < N; ++i)
a[i] = e[i] + (i - 1);
for(i = 0; i < N; ++i)
b[i] = d[i] + (i + 3);
for(i = 0; i < N; ++i)
c[i] = a[i] - (i + 2);
for(i = 0; i < N; ++i)
d[i] = b[i] + (i - 2);
for(i = 0; i < N; ++i)
e[i] = a[i] + (i - 4);
s = wallclock_since(&t);
printf("Load/write took %.9f seconds wall clock time.\n", s);
return 0;
}
,我已經離開了測量時間的代碼,我有here。結果如下:
Georgioss-MacBook-Pro:~ gsamaras$ ./bigloop
Populating took 0.000581000 seconds wall clock time.
Load/write took 0.000178000 seconds wall clock time.
Georgioss-MacBook-Pro:~ gsamaras$ ./loop
Populating took 0.001092000 seconds wall clock time.
Load/write took 0.000285000 seconds wall clock time.
在這裏你可以看到一個數量級的加速數組在填充數組時全部數組合在一起。而且,它的處理速度也更快!
所以,如果我是你,我會實施兩種方法,並測量時間! =)
PS:不要成爲過早優化的受害者。如果你有一個你想要優化的項目,請分析你的代碼以找到瓶頸並專注於此!
我看到你沒有反彙編代碼 - 否則你會看到在-O3之後發生了什麼 - >所有循環都作爲死代碼被刪除。所以你的代碼證明什麼都沒有。 – Anty
感謝Anty的評論! – gsamaras
@gsamaras「一個數量級加速」?更像是兩個因素。所以你使用單一循環獲得了最佳性能,但這與假定的高速緩存加速相反? –