一个关于Memory Reordering的实验
2013-09-16 22:08
330 查看
Instruction Reordering有两种,包括Compiler Reordering和Memory Reordering。
Intel官方列出的有关Memory Reordering的情况总共有8种:
Neither Loads Nor Stores Are Reordered with Like Operations
Stores Are Not Reordered With Earlier Loads
Loads May Be Reordered with Earlier Stores to Different Locations
Intra-Processor Forwarding Is Allowed
Stores Are Transitively Visible
Stores Are Seen in a Consistent Order by Other Processors
Locked Instructions Have a Total Order
Loads and Stores Are Not Reordered with Locked Instructions
可以看出,第三点是会发生指令重排的情况。
下面做一个验证第三点的实验,参考《Memory Reordering Caught in the Act》一文,
原文链接:http://preshing.com/20120515/memory-reordering-caught-in-the-act
(注:原文采用的是windows平台,这里采用linux平台)
其中,__asm__ __volatile__("":::"memory") 是禁止编译器进行指令重排,保证了store操作和load操作在编译后的先后顺序。
可以发现,输出结果出现了 r1==0&&r2==0 的情况,证明CPU对指令进行了重排。
下面,再将__asm__ __volatile__("":::"memory") 改为 __asm__ __volatile__("mfence":::"memory"),强制使用strong ordering的模式,保证CPU不对该句前后的store和load操作进行重排:
可以发现,输出结果中没有了 r1==0&&r2==0 的情况。
Intel官方列出的有关Memory Reordering的情况总共有8种:
Neither Loads Nor Stores Are Reordered with Like Operations
Stores Are Not Reordered With Earlier Loads
Loads May Be Reordered with Earlier Stores to Different Locations
Intra-Processor Forwarding Is Allowed
Stores Are Transitively Visible
Stores Are Seen in a Consistent Order by Other Processors
Locked Instructions Have a Total Order
Loads and Stores Are Not Reordered with Locked Instructions
可以看出,第三点是会发生指令重排的情况。
下面做一个验证第三点的实验,参考《Memory Reordering Caught in the Act》一文,
原文链接:http://preshing.com/20120515/memory-reordering-caught-in-the-act
(注:原文采用的是windows平台,这里采用linux平台)
#define _GNU_SOURCE #include <sched.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <pthread.h> #include <semaphore.h> sem_t beginSema1; sem_t beginSema2; sem_t endSema; int X,Y; int r1,r2; void* thread1Func(void* param) { while (1) { sem_wait(&beginSema1); while ( (rand() / (double)RAND_MAX) > 0.2 ) ; X=1; __asm__ __volatile__("":::"memory"); r1 = Y; sem_post(&endSema); } return NULL; } void* thread2Func(void* param) { while (1) { sem_wait(&beginSema2); while ( (rand() / (double)RAND_MAX) > 0.2 ) ; Y=1; __asm__ __volatile__("":::"memory"); r2 = X; sem_post(&endSema); } return NULL; } int main() { sem_init(&beginSema1,0,0); sem_init(&beginSema2,0,0); sem_init(&endSema,0,0); pthread_t thread1,thread2; pthread_create(&thread1,NULL,thread1Func,NULL); pthread_create(&thread2,NULL,thread2Func,NULL); int detected = 0; int iterations = 0; for (iterations=1;;iterations++) { X=0; Y=0; sem_post(&beginSema1); sem_post(&beginSema2); sem_wait(&endSema); sem_wait(&endSema); if (r1 == 0 && r2 == 0) { detected++; printf("%d reorders detected after %d iterations\n", detected, iterations); } } return 0; }
其中,__asm__ __volatile__("":::"memory") 是禁止编译器进行指令重排,保证了store操作和load操作在编译后的先后顺序。
可以发现,输出结果出现了 r1==0&&r2==0 的情况,证明CPU对指令进行了重排。
下面,再将__asm__ __volatile__("":::"memory") 改为 __asm__ __volatile__("mfence":::"memory"),强制使用strong ordering的模式,保证CPU不对该句前后的store和load操作进行重排:
#define _GNU_SOURCE #include <sched.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <pthread.h> #include <semaphore.h> sem_t beginSema1; sem_t beginSema2; sem_t endSema; int X,Y; int r1,r2; void* thread1Func(void* param) { while (1) { sem_wait(&beginSema1); while ( (rand() / (double)RAND_MAX) > 0.2 ) ; X=1; __asm__ __volatile__("mfence":::"memory"); r1 = Y; sem_post(&endSema); } return NULL; } void* thread2Func(void* param) { while (1) { sem_wait(&beginSema2); while ( (rand() / (double)RAND_MAX) > 0.2 ) ; Y=1; __asm__ __volatile__("mfence":::"memory"); r2 = X; sem_post(&endSema); } return NULL; } int main() { sem_init(&beginSema1,0,0); sem_init(&beginSema2,0,0); sem_init(&endSema,0,0); pthread_t thread1,thread2; pthread_create(&thread1,NULL,thread1Func,NULL); pthread_create(&thread2,NULL,thread2Func,NULL); int detected = 0; int iterations = 0; for (iterations=1;;iterations++) { X=0; Y=0; sem_post(&beginSema1); sem_post(&beginSema2); sem_wait(&endSema); sem_wait(&endSema); if (r1 == 0 && r2 == 0) { detected++; printf("%d reorders detected after %d iterations\n", detected, iterations); } } return 0; }
可以发现,输出结果中没有了 r1==0&&r2==0 的情况。
相关文章推荐
- 稍微进阶点的搞实验中的杂谈(一)—— 主要关于boost asio例程2,多个io_service的server,例程3,多个线程一个io_service
- 关于编程语言中?:运算符(三元表达式)的一个小实验
- 一个关于Java子类父类方法执行的小实验
- Memory Reordering Caught in Act
- 从JVM并发看CPU内存指令重排序(Memory Reordering) http://ifeve.com/jvm-memory-reordering/
- [memory fence] Memory Reordering Caught in the Act
- python3.x,一个关于queue.task_done()与queue.join()的实验
- 一个关于LSTM的high-level介绍(但是很好):A Gentle Introduction to Long Short-Term Memory Networks by the Experts
- 关于memory barrier/memory ordering的笔记和总结(1)
- 关于oracle中spfile和pfile的一个实验
- 关于指针类型转换的一个有趣实验
- 关于Pandas库中reindex函数填充选项ffill和bfill的一个有趣的实验。
- 关于memory barrier/memory ordering 的笔记和总结(2)
- 一个关于路由的小综合实验
- 关于javascript程序内存占用的一个有趣的实验
- 从JVM并发看CPU内存指令重排序(Memory Reordering)
- 关于LWIP在应用中遇到的一个问题memp_malloc: out of memory in pool TCP_PCB
- 关于memory barrier/memory ordering的笔记和总结(3)
- 关于Windows更新窗口内容的问题(作为一个实验,效果很明显)
- Memory Reordering Caught in the Act