码迷,mamicode.com
首页 > 编程语言 > 详细

正确的C++并行

时间:2015-01-23 13:26:45      阅读:210      评论:0      收藏:0      [点我收藏+]

标签:c++   并行   

《C++0x漫谈》系列之:多线程内存模型 (简称为漫谈)解释了多线程并行的困难,在这里我分层地看看这个问题。


1.为什么分层次?
C++语言表达的抽象和机器的抽象距离比较近,而且几乎看不到C++在虚拟机上跑的实例,所以两者的关系容易混淆。有人常常把反汇编拿出来一看,并作为C++语言是如此的证据,这是本末倒置的。假定C++都是直接翻译为汇编,于是这只是一个如何将一个语言翻译为另外一个语言的问题。编译器干的事就是用目标语言的一些抽象来实现源语言一些抽象,所以目标语言的语义,行为,并不能决定源语言,而只能说明翻译的正确性和质量。比如,某个C++类在语义上有个构造函数的调用,但是其行为是平凡的,在翻译后的代码中看不到任何构造函数调用的代码,这并不是构造函数不存在的证据。所以,这里我们分出层次,一方面是汇编及其实现(即CPU)的结合体,另一方面就是C++了。


2.怎么翻译?
显然,翻译建立在对两种语言上的充分理解上。理解一个语言,就要理解其提供的抽象及其语义。如何定义语义?这是研究程序设计语言的人干的,比较经典的有操作语义,指称语义。在这里我们不严格从操作语义的角度来看这两种语言。


2.1汇编语言比较底层,其操作语义很明确。考虑并行,intel(这里只谈x86)也定义了其memory order,其中展示了一些并行执行的汇编代码,并说明什么样的结果是可能的,什么样的结果是不可能的。
2.2对于C++,其语义也能通过一些操作及其状态变化来描述(纯粹的操作语义并不能完全来描述C++,我们这里只是更关心操作及其结果)。


此时,翻译的正确性就变成了操作的对等性。


等等,在2.1中提到了并行,2.2中并没有提到(或者说在c++11之前都没提到),是的,这就是问题所在:C++本没有这样的语义,但是实际上通过多线程并行地执行,于是其正确性不能保证。


3.如何保证无并行语义的语言在并行执行的时候的正确性?
《漫谈》一文中已讲。其中提到的“一个简单的办法就是禁止编译器作任何优化:所有的操作严格按照代码顺序执行,所有的操作都触发cache coherence操作以确保它们的副作用在跨线程间的visibility顺序。”我认为并不是简单禁止编译器作任何优化就能达到后面的效果,甚至需要编译器做更多的事。这些做的更多的事,相当于对源语言有所扩展:出现了并行的苗头。而后面提到的“data-race-free”使得在保证正确性的同时,提高效率,其实相当于我们面向的是编译器扩展的一个有并行语义的语言(当同步原语是编译器提供的时候认为是编译器扩展语言,当同步原语是库提供的时候,认为是库扩展了语义,同时编译器必须理解库所提供的语义,否则在调用库代码的地方给个优化就完蛋了)。如何实现库呢?面向执行环境编程。要么库直接用执行环境的语言写,要么通过插入执行环境的代码(内联汇编),并行在插入代码处编译器不作优化。


上述正确性考虑得比较理论,如果从实际上讲呢?
a假定优化不会跨函数调用。这一方面使得库的代码被保护,另一方面保证了调用处的正确性。
b面向执行环境编程,通过内联汇编来保证并行语义。
c假定优化不跨内联汇编。
上述假定较容易实现,在实现后我们得到了依赖于库的提供了并行语义的语言。


4.如果源语言有并行语义呢?
定义了C++11中的mutex,atom的语义后,翻译时编译器知道某些操作的顺序不能改变,在适当的地方应该加入mb。

正确的C++并行

标签:c++   并行   

原文地址:http://blog.csdn.net/baihacker/article/details/43053791

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!