今天在看CPU cache时候,根据上面的例子做了个练习,发现了一个怪事情,没想明白
例子如下,在powerpc下面跑,多个power7的CPU:
例子一test:
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
int main()
{
int steps = 256 * 1024 * 1024;
int a[] = {0,0};
int i ;
struct timeval start ;
struct timeval end ;
unsigned long diff ;
gettimeofday(&start, NULL);
for (i=0; i<steps; i++) { a[0]++; a[0]++; } -----此处为两个a[0]
gettimeofday(&end, NULL);
diff = 1000000 * (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec);
printf("diff----%ld\n",diff);
}
例子2 test2:
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
int main()
{
int steps = 256 * 1024 * 1024;
int a[] = {0,0};
int i ;
struct timeval start ;
struct timeval end ;
unsigned long diff ;
gettimeofday(&start, NULL);
for (i=0; i<steps; i++) { a[0]++; a[1]++; } ----此处为一个a[0],一个a[1]
gettimeofday(&end, NULL);
diff = 1000000 * (end.tv_sec-start.tv_sec)+ end.tv_usec-start.tv_usec;
printf("diff2----%ld\n",diff);
}
执行./test;./test2
结果如下:
diff----3826802
diff2----1976746
现代处理器中对不同部分指令拥有一点并发性。这使得CPU在同一时刻访问L1两处内存位置,或者执行两次简单算术操作。在第一个循环中,处理器无法发掘这种指令级别的并发性,但第二个循环中就可以。所以test2比test快近一倍。
但将test和test2合并在一起
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
#define mb() __asm__ __volatile__ ("sync" : : : "memory") ----此是因为怀疑cpu乱序这类造成引入
int main()
{
int steps = 256 * 1024 * 1024;
int a[] = {0,0};
int i ;
struct timeval start ;
struct timeval end ;
unsigned long diff ;
gettimeofday(&start, NULL);
for (i=0; i<steps; i++) { a[0]++; a[0]++; }
gettimeofday(&end, NULL);
diff = 1000000 * (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec);
printf("diff----%ld\n",diff);
mb(); ------加和不加,对输出的数字有较大影响
gettimeofday(&start, NULL);
for (i=0; i<steps; i++) { a[0]++; a[0]++; } -----先用a[0],后面用a[1]作不同实验
gettimeofday(&end, NULL);
diff = 1000000 * (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec);
printf("diff2----%ld\n",diff);
}
加mb()
diff----3919898
diff2----6281302
去掉mb()
diff----4068821
diff2----3803478
疑问:为什么加mb()之后,执行时间要多花这么多
改为a[1],加mb()
diff----3815021
diff2----3473165
不加mb()
diff----3815935
diff2----3463169
考虑到误差,这两者基本一样
疑问:为什么分开两个程序,和一个程序内执行时间差别这么大。
有空看看两者产生的汇编语言,看看有什么不同之处。
并行编程真是个神奇的怪物,还有待深入。
这两天稍微有点空,看了一下汇编,在上面的mb()之前产生的汇编和mb()之后产生的汇编不一样,估计就是传说中的乱序优化,在第一个gettimeofday(&start,NULL)之前加上mb(),其结果就比较正常了,a[0]++,a[0]++比a[0]++,a[1]++慢将近一倍
diff----6159865
diff2----3427905
但不加mb(),a[1]++这个速度相比下不明显,不知何故?
直接用 gcc -O2 -o test test.c,之后执行便变成了
diff----0
diff2----0