澄梦希喜广告网站制作遂宁站

OpenMP创建线程中的锁及原子操作性能比较

在多核CPU中锁竞争到底会造成性能怎样的下降呢?相信这是许多人想了解的,因此特地写了一个测试程序来测试原子操作,windows CriticalSection, OpenMP的锁操作函数在多核CPU中的性能。

创新互联建站专注于企业网络营销推广、网站重做改版、巢湖网站定制设计、自适应品牌网站建设、H5开发、商城网站建设、集团公司官网建设、外贸营销网站建设、高端网站制作、响应式网页设计等建站业务,价格优惠性价比高,为巢湖等各大城市提供网站开发制作服务。

原子操作选用InterlockedIncrement来进行测试,

对每种锁和原子操作,都测试在单任务执行和多任务执行2000000次加锁解锁操作所消耗的时间。

测试的详细代码见后面。

测试机器环境: Intel 2.66G 双核CPU 机器一台

测试运行结果如下:

SingleThread, InterlockedIncrement 2,000,000: a = 2000000, time = 78

MultiThread, InterlockedIncrement 2,000,000: a = 2000000, time = 156

SingleThread, Critical_Section 2,000,000:a = 2000000, time = 172

MultiThread, Critical_Section, 2,000,000:a = 2000000, time = 3156

SingleThread,omp_lock 2,000,000:a = 2000000, time = 250

MultiThread,omp_lock 2,000,000:a = 2000000, time = 1063

在单任务运行情况下,所消耗的时间如下:

原子操作                 78ms

Windows CriticalSection 172ms

OpenMP 的lock操作        250ms

因此从单任务情况来看,原子操作最快,Windows CriticalSection次之,OpenMP库带的锁最慢,但这几种操作的时间差距不是很大,用锁操作比原子操作慢了2~3倍左右。

在多个任务运行的情况下,所消耗的时间如下:

原子操作                 156ms

Windows CriticalSection 3156ms

OpenMP 的lock操作        1063ms

在多任务运行情况下,情况发生了意想不到的变化,原子操作时间比单任务操作时慢了一倍,在两个CPU上运行比在单个CPU上运行还慢一倍,真是难以想象,估计是任务切换开销造成的。

Windows CriticalSection则更离谱了,居然花了3156ms,是单任务运行时的18倍多的时间,慢得简直无法想象。

OpenMP的lock操作比Windows CriticalSection稍微好一些,但也花了1063ms,是单任务时的7倍左右。

由此可以知道,在多核CPU的多任务环境中,原子操作是最快的,而OpenMP次之,Windows CriticalSection则最慢。

同时从这些锁在单任务和多任务下的性能差距可以看出,,多核CPU上的编程和以往的单核多任务编程会有很大的区别。

需要说明的是,本测试是一种极端情况下的测试,锁住的操作只是一个简单的加1操作,并且锁竞争次数达200万次之多,在实际情况中,一由于任务中还有很多不需要加锁的代码在运行,实际情况中的性能会比本测试的性能好很多。

测试代码如下:

 
 
 
  1. // TestLock.cpp : OpenMP任务中的原子操作和锁性能测试程序。 
  2. // 
  3.   
  4. #include  
  5. #include  
  6. #include  
  7. #include  
  8. #include  
  9.   
  10. void TestAtomic() 
  11. { 
  12.      clock_t t1,t2; 
  13.      int      i = 0; 
  14.      volatile LONG      a = 0; 
  15.   
  16.      t1 = clock(); 
  17.   
  18.      for( i = 0; i < 2000000; i++ ) 
  19.      { 
  20.          InterlockedIncrement( &a); 
  21.      } 
  22.      
  23.      t2 = clock(); 
  24.      printf("SingleThread, InterlockedIncrement 2,000,000: a = %ld, time = %ld/n", a, t2-t1); 
  25.   
  26.      t1 = clock(); 
  27.   
  28. #pragma omp parallel for 
  29.      for( i = 0; i < 2000000; i++ ) 
  30.      { 
  31.          InterlockedIncrement( &a); 
  32.      } 
  33.      
  34.      t2 = clock(); 
  35.      printf("MultiThread, InterlockedIncrement 2,000,000: a = %ld, time = %ld/n", a, t2-t1); 
  36. } 
  37.   
  38. void TestOmpLock() 
  39. { 
  40.      clock_t t1,t2; 
  41.      int i; 
  42.      int a = 0; 
  43.      omp_lock_t    mylock; 
  44.   
  45.      omp_init_lock(&mylock); 
  46.   
  47.      t1 = clock(); 
  48.   
  49.      for( i = 0; i < 2000000; i++ ) 
  50.      { 
  51.          omp_set_lock(&mylock); 
  52.          a+=1; 
  53.          omp_unset_lock(&mylock); 
  54.      } 
  55.      t2 = clock(); 
  56.      
  57.      printf("SingleThread,omp_lock 2,000,000:a = %ld, time = %ld/n", a, t2-t1); 
  58.   
  59.      t1 = clock(); 
  60.   
  61. #pragma omp parallel for 
  62.      for( i = 0; i < 2000000; i++ ) 
  63.      { 
  64.          omp_set_lock(&mylock); 
  65.          a+=1; 
  66.          omp_unset_lock(&mylock); 
  67.      } 
  68.      t2 = clock(); 
  69.      
  70.      printf("MultiThread,omp_lock 2,000,000:a = %ld, time = %ld/n", a, t2-t1); 
  71.   
  72.      omp_destroy_lock(&mylock); 
  73. } 
  74.   
  75.   
  76.   
  77. void TestCriticalSection() 
  78. { 
  79.      clock_t t1,t2; 
  80.      int i; 
  81.      int a = 0; 
  82.      CRITICAL_SECTION   cs; 
  83.   
  84.      InitializeCriticalSection(&cs); 
  85.   
  86.      t1 = clock(); 
  87.   
  88.      for( i = 0; i < 2000000; i++ ) 
  89.      { 
  90.          EnterCriticalSection(&cs); 
  91.          a+=1; 
  92.          LeaveCriticalSection(&cs); 
  93.      } 
  94.      t2 = clock(); 
  95.   
  96.      printf("SingleThread, Critical_Section 2,000,000:a = %ld, time = %ld/n", a, t2-t1); 
  97.   
  98.      t1 = clock(); 
  99.   
  100. #pragma omp parallel for 
  101.      for( i = 0; i < 2000000; i++ ) 
  102.      { 
  103.          EnterCriticalSection(&cs); 
  104.          a+=1; 
  105.          LeaveCriticalSection(&cs); 
  106.      } 
  107.      t2 = clock(); 
  108.   
  109.      printf("MultiThread, Critical_Section, 2,000,000:a = %ld, time = %ld/n", a, t2-t1); 
  110.   
  111.      DeleteCriticalSection(&cs); 
  112.   
  113. } 
  114.   
  115. int main(int argc, char* argv[]) 
  116. { 
  117.   
  118.      TestAtomic(); 
  119.      TestCriticalSection(); 
  120.      TestOmpLock(); 
  121.   
  122.      return 0; 
  123. } 

原文链接:http://blog.csdn.net/drzhouweiming/article/details/1689853


网页名称:OpenMP创建线程中的锁及原子操作性能比较
转载来于:http://hfanp.com/article/dpoosoe.html

其他资讯

在线咨询

微信咨询

电话咨询

028-86922220(工作日)

18980820575(7×24)

提交需求

返回顶部