OPEN CASCADE学习笔记
——并行程序开发
著: Roman Lygin
waitforsingleobject函数译:George Feng
这是一篇关于开源三维建模软件O P E N C A S C A D E内核的博文:
R O M A N L Y G I N是O P E N C A S C A D E的前程序开发员和项目经理,
曾经写过许多关于该开源软件开发包的深入文章,可以在他的博
客(H T T P://O P E N C A S C A D E.B L O G S P O T.C O M)上面到这些文章。
序
在Open Cascade的论坛上知道了Roman Lygin在他的博客上写了Open Cascade notes系列文章,考虑到Open Cascade的学习资料并不多,于是从他的博客上下载了其中绝大部分文章,将其翻译过来以方便大家学习交流。如果大家发现文中翻译有错误或不足之处,望不吝赐教,可以发到我的邮箱fenghongkui@si
na,十分感谢。
2012年11月22日星期四
第1节并行程序开发综述
正如在之前的文章中提到的,我正在开发CAD Exchanger的ACIS导入部分,并且将其开发成并发执行的。到目前为止结果非常理想(除了STL的流解析,因为之前文章中提到的Microsoft的bug,我安装了VS2008SP1正在检测这个错误是否得到了修正)。所以我准备在这篇文章中分享我的经验,希望能够对其他开发人员有帮助(有关并行性问题在论坛上讨论的也越来越多)。也希望Open CASCADE小组能够从我的发现中受益。
我之前已经简短介绍过几次并行应用程序开发了,再强调一下在多核时代并行应
用程序将在某个时期成为主流,你最好现在就准备好应对这个趋势。这对你的职业路线是非常有助的,这些能力将增强你的竞争力。最近发布的Intel Parallel Studio(它已经成为我的工具箱的很重要的部分)可以调试多线程应用程序,简化开发人员的工作。关于并行程序开发这个方面有很多基础书籍。我现在在读的是Timothy Mattson 等写的《Patterns for Parallel Programming》(我的一位这方面非常熟练的同事推荐的),还有Erich Gamma 写的《Design Patterns》也是类似的书(所有专业软件开发人员都需要读的书)。它帮助我设计CAD Exchanger 中ACIS导入部件的构架。
回到Open CASCADE,我可以明确的说Open CASCADE对于并行应用程序非常有用,但是正如其他软件库一样需要小心使用。
一般性评述
假如从较高的角度看问题,从问题领域看,而不是从一个特定的算法的角度看。看看什么能够并发进行,什么需要顺序执行。例如,在我的初始IGES转换(参考这里)实验中,我特别注意了IGES组的并行转换模块,这个模块运行的非常好。但是整个程序的性能提高非常少,因为不是这部分占用的时间最多,而是Shape Healing占用了整个时间的50%-70%,而且该部分仍然是顺序执行的。所以在重新设计算法之前,性能不会提高太多。我不得不重构ACIS读取器,重新设计传统的瀑布模型结构(其中遍历模型从根节点到叶节点),然后是shape healing模块。由此产生了很多有价值的东西。《Design Patterns》这本书具有很好的指导作用,可以帮助确定算法的模式。
句柄
从6.2.x 开始Open CASCADE的句柄(Handle_Standard_Transient的子类)已经对引用计数实现了线程安全。要利用这个优点,你必须定义MMGT_REENTRANT系统变量为非空,或者在线程之间使用句柄之前调用Standard::SetReentrant (Standard_True),这使引用计数依赖于原子态的增加/减小(例如Windows 上的InterlockedIncrement()),而不是++,这可能并不是原子态的。
void Handle(Standard_Transient)::BeginScope()
{
if (entity != UndefinedHandleAddress)
{
if ( Standard::IsReentrant() )
Standard_Atomic_Increment (&entity->count);
else
entity->count++;
}
}
内存管理
缺省情况下,Open CASCADE将变量MMGT_OPT定义为1。这意味着所有的对于Standard::Allocate()和::Free()的调用都最终到达Open CASCADE的内存管理器(Standard_MMgrOpt),其会优化内存分配,消除内存碎片(可能这值得另外专门写一篇文章,讨论内存管理的内部实现机制)。
Standard_MMgrOpt自身是线程安全的,并且安全的处理几个线程的并发内存分配/释放请求。然而它是基于Standard_Mutex的(将来会有更多基于这个类的实现),其在当前的实现中具有比较多的额外花费,这使得在并行程序中对于内存管理的优化作用显得无足轻重(然而在单线程环境中它运行的很好)。
所以为了克服这个缺陷应该使用MMGT_OPT=0,这就会激活Standard_MMgrRaw,它会简化前向调用(forward calls)malloc/free…
(待续...)
POSTED BY ROMAN LYGIN AT 19:50, 2009-06-09
第2节内存管理器
(接上节...)
顺便说一下,在应用程序启动之前必须设置环境变量(MMGT_OPT),以及其他控制Open CASCADE的内存管理的环境变量。这非常重要,因为内存管理的选择是在加载DLL文件之前开始的,在运行时无法改变用户的内存管理策略,这也是一个非常不方便的限制。
在应用程序的声明周期中,由于扩展内存的分配和释放可能会成为一个热点区域。例如,下图是CAD Exhcanger ACIS转换的热点分析截图。
直接使用操作系统的内存管理时(正如前面分析的不能使用Open CASCADE的内存管理),测量并发和等待&死锁(另外两项分析是由Amplifier完成的),可以
看到也引发了最大等待时间。
一方面,这是个好的信号,就算说代码的其他部分都运行的非常快。但是另一方面,它表明内存管理确实成为一个瓶颈。随着深入分析这个问题,我切换到直接看操作系统函数的模式(按下Amplifier工具条的按钮) (toggling off the button
on Amplifier toolbar),下图是我看到的:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论