一个关于Memory Reordering的实验

原创 2013年09月16日 22:08:52

  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平台)


  

#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 的情况。


ACL_2017年深度学习与NLP论文分享先行版(一)

本周末参加了由腾讯和中国中文信息学会青工委联合举办的ACL2017前沿论文报告会,邀请了ACL发表论文的国内学者们介绍NLP研究最新技术动态。 ACL是Annual Meeting of the ...
  • lqfarmer
  • lqfarmer
  • 2017年04月23日 12:56
  • 1900

SDUT 3373 数据结构实验之查找一:二叉排序树

数据结构实验之查找一:二叉排序树 Time Limit: 400ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 对应...
  • Code_KK
  • Code_KK
  • 2015年12月03日 13:22
  • 1533

windows进程间通信

摘 要: 随着人们对应用程序的要求越来越高,单进程应用在许多场合已不能满足人们的要求。编写多进程/多线程程序成为现代程序设计的一个重要特点,在多进程程序设计中,进程间的通信是不可避免的。Microso...
  • liuyinghui523
  • liuyinghui523
  • 2014年10月24日 08:38
  • 1221

Memory reordering

Memory Barriers and JVM Concurrency  对主存的一次访问一般花费硬件的数百次时钟周期。处理器通过缓存(caching)能够从数量级上降低内存延迟的成本这些缓存为...
  • dannyPolyu
  • dannyPolyu
  • 2013年03月26日 19:46
  • 383

java多线程和并发编程(三)--- 从JVM并发看CPU内存指令重排序(Memory Reordering)

前言:  Dennis Byrne 写的一片博文Memory Barriers and JVM Concurrency (中译文内存屏障与JVM并发)。 中提到:对主存的一次访问一般花费硬件的...
  • lixiaodong037
  • lixiaodong037
  • 2012年09月18日 16:17
  • 1071

主题:从JVM并发看CPU内存指令重排序(Memory Reordering)

这两天,我拜读了 Dennis Byrne 写的一片博文?Memory Barriers and JVM Concurrency (中译文?内存屏障与JVM并发)。 文中提到: 对...
  • youling_lh
  • youling_lh
  • 2013年09月17日 21:43
  • 510

从JVM并发看CPU内存指令重排序(Memory Reordering)

这两天,我拜读了 Dennis Byrne 写的一片博文Memory Barriers and JVM Concurrency,文中提到: 对主存的一次访问一般花费硬件的数百次时钟周期。处理...
  • mrdothe
  • mrdothe
  • 2016年03月08日 23:47
  • 218

【Oracle】Oracle 12c DB In-Memory入门实验手册(二)

(二)加载数据到IM column store 在实验手册(一)中介绍了IM的基础操作,objects如何开启IM column store。 链接:http://blog.csdn.net/badl...
  • badly9
  • badly9
  • 2015年11月11日 09:53
  • 1159

[CortexM0--stm32f0308]memory详细使用的实验

问题描述stm32f0308 discovery在Keil工具下编译链接,并download代码到IC中,在程序下载到IC,以及到程序实际运行时IC是如何使用其memory来实现具体的功能的呢,因此对...
  • suxiang198
  • suxiang198
  • 2015年07月20日 23:01
  • 1962

【Oracle】Oracle 12c DB In-Memory入门实验手册(一)

该手册实验基础要在实例级别启用IM column store,开启方法参考上篇文章: 链接:http://blog.csdn.net/badly9/article/details/49724983 (...
  • badly9
  • badly9
  • 2015年11月09日 23:19
  • 1153
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:一个关于Memory Reordering的实验
举报原因:
原因补充:

(最多只允许输入30个字)