设为首页 加入收藏

TOP

10.3.2 运行期按架构派发
2013-10-07 15:05:37 来源: 作者: 【 】 浏览:74
Tags:10.3.2 运行 架构 派发

10.3.2  运行期按架构派发

下面我想为你展示在Intel平台上对原子整型操作进行性能优化的一点小技巧。正如我们前面已经了解到的,Intel处理器能够不被中断地执行单个指令形式的RMW(读-改-写)操作(例如ADD、XADD),因而在Intel单处理器上我们不必对总线进行加锁就能实现该操作的原子性。相反,在多处理器机器上要想达到这个目的的话,你就必须对总线进行加锁。由于人们构建(build)并分发的通常是单一版本的代码,1所以最好让代码只在必要时才付出因总线锁定而导致的性能开销。既然对总线加锁和不加锁两种情况下的指令数目都很少,那么我们就必须以一种高效的方式来完成这种优化,否则用于测试是否多处理器的代码的开销反而大过它带来的节省。解决方案的简化版本2展示于程序清单10.4中,它跟大多数现代的Win32编译器都是兼容的:3

程序清单10.4

  1. namespace  
  2. {  
  3.   static bool s_uniprocessor = is_host_up();  
  4. }  
  5.  
  6. inline __declspec(naked) void __stdcall  
  7.   atomic_increment(sint32_t volatile * /* pl */)  
  8. {  
  9.   if(s_uniprocessor)  
  10.   {  
  11.     _asm  
  12.     {  
  13.       mov ecx, dword ptr [esp + 4]  
  14.       add dword ptr [ecx], 1  
  15.       ret 4  
  16.     }  
  17.   }  
  18.   else  
  19.   {  
  20.     _asm  
  21.     {  
  22.       mov ecx, dword ptr [esp + 4]  
  23.       lock add dword ptr [ecx], 1  
  24.       ret 4  
  25.     }  
  26.   }  
  27. }  

即使你对Intel汇编语言不熟悉,你也应该能够看出这种机制是何等的简单。s_uniprocessor变量对于单处理器机器来说是true,对于多处理器来说则是false。如果是true的话,就可以不加锁地实现原子的递增操作,反之则需要对总线进行加锁。这里在s_uniprocessor的实例化中可能存在的任何竞争条件都是无关紧要的,因为缺省情况下是进行加锁。

在下面的性能测试表中,这正是Synesis库里的Atomic_API和WinSTL原子函数所采用的机制。

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇10.3.4 原子整型操作:尾声 下一篇10.1.1 操作系统函数

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: