织梦CMS - 轻松建站从此开始!

罗索

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

落鹤生 发布于 2010-05-28 14:29 点击:次 
在多核CPU中锁竞争到底会造成性能怎样的下降呢?相信这是许多人想了解的,因此特地写了一个测试程序来测试原子操作,windows CriticalSection, OpenMP的锁操作函数在多核CPU中的性能。
TAG:

相关文档连接:
 双核CPU上的快速排序效率            
 
在多核CPU中锁竞争到底会造成性能怎样的下降呢?相信这是许多人想了解的,因此特地写了一个测试程序来测试原子操作,windows CriticalSection, OpenMP的锁操作函数在多核CPU中的性能。
 
原子操作选用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. // TestLock.cpp : OpenMP任务中的原子操作和锁性能测试程序。 
  2. #include <windows.h> 
  3. #include <time.h> 
  4. #include <process.h> 
  5. #include <omp.h> 
  6. #include <stdio.h> 
  7.   
  8. void TestAtomic() 
  9.      clock_t t1,t2; 
  10.      int      i = 0; 
  11.      volatile LONG      a = 0; 
  12.   
  13.      t1 = clock(); 
  14.   
  15.      for( i = 0; i < 2000000; i++ ) 
  16.      { 
  17.          InterlockedIncrement( &a); 
  18.      } 
  19.      
  20.      t2 = clock(); 
  21.      printf("SingleThread, InterlockedIncrement 2,000,000: a = %ld, time = %ld\n", a, t2-t1); 
  22.   
  23.      t1 = clock(); 
  24.   
  25. #pragma omp parallel for 
  26.      for( i = 0; i < 2000000; i++ ) 
  27.      { 
  28.          InterlockedIncrement( &a); 
  29.      } 
  30.      
  31.      t2 = clock(); 
  32.      printf("MultiThread, InterlockedIncrement 2,000,000: a = %ld, time = %ld\n", a, t2-t1); 
  33.   
  34. void TestOmpLock() 
  35.      clock_t t1,t2; 
  36.      int i; 
  37.      int a = 0; 
  38.      omp_lock_t    mylock; 
  39.   
  40.      omp_init_lock(&mylock); 
  41.   
  42.      t1 = clock(); 
  43.   
  44.      for( i = 0; i < 2000000; i++ ) 
  45.      { 
  46.          omp_set_lock(&mylock); 
  47.          a+=1; 
  48.          omp_unset_lock(&mylock); 
  49.      } 
  50.      t2 = clock(); 
  51.      
  52.      printf("SingleThread,omp_lock 2,000,000:a = %ld, time = %ld\n", a, t2-t1); 
  53.   
  54.      t1 = clock(); 
  55.   
  56. #pragma omp parallel for 
  57.      for( i = 0; i < 2000000; i++ ) 
  58.      { 
  59.          omp_set_lock(&mylock); 
  60.          a+=1; 
  61.          omp_unset_lock(&mylock); 
  62.      } 
  63.      t2 = clock(); 
  64.      printf("MultiThread,omp_lock 2,000,000:a = %ld, time = %ld\n", a, t2-t1); 
  65.      omp_destroy_lock(&mylock); 
  66.   
  67. void TestCriticalSection() 
  68.      clock_t t1,t2; 
  69.      int i; 
  70.      int a = 0; 
  71.      CRITICAL_SECTION   cs; 
  72.   
  73.      InitializeCriticalSection(&cs); 
  74.   
  75.      t1 = clock(); 
  76.   
  77.      for( i = 0; i < 2000000; i++ ) 
  78.      { 
  79.          EnterCriticalSection(&cs); 
  80.          a+=1; 
  81.          LeaveCriticalSection(&cs); 
  82.      } 
  83.      t2 = clock(); 
  84.   
  85.      printf("SingleThread, Critical_Section 2,000,000:a = %ld, time = %ld\n", a, t2-t1); 
  86.   
  87.      t1 = clock(); 
  88.   
  89. #pragma omp parallel for 
  90.      for( i = 0; i < 2000000; i++ ) 
  91.      { 
  92.          EnterCriticalSection(&cs); 
  93.          a+=1; 
  94.          LeaveCriticalSection(&cs); 
  95.      } 
  96.      t2 = clock();  
  97.      printf("MultiThread, Critical_Section, 2,000,000:a = %ld, time = %ld\n", a, t2-t1);  
  98.      DeleteCriticalSection(&cs);  
  99. }  
  100. int main(int argc, char* argv[]) 
  101.      TestAtomic(); 
  102.      TestCriticalSection(); 
  103.      TestOmpLock(); 
  104.   
  105.      return 0; 

 

(drzhouweiming)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201005/9531.html]
本文出处:CSDN博客 作者:drzhouweiming
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容