您的位置:首页 > 运维架构

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

2008-04-08 23:35 393 查看
 
[align=center]OpenMP创建线程中的锁及原子操作性能比较[/align][align=left] [/align][align=left]相关文档连接:[/align][align=left]多核编程中的任务随机竞争模式的概率分析 [/align][align=left]多核编程中的任务分组竞争模式            [/align][align=left] 多核编程中的负载平衡难题 [/align][align=left]多核编程中的锁竞争难题 [/align][align=left]多核编程的几个难题及其应对策略(难题一)[/align][align=left]OpenMP并行程序设计(二) [/align][align=left] OpenMP并行程序设计(一) [/align][align=left] 双核CPU上的快速排序效率             [/align][align=left] [/align][align=left]在多核CPU中锁竞争到底会造成性能怎样的下降呢?相信这是许多人想了解的,因此特地写了一个测试程序来测试原子操作,windows CriticalSection, OpenMP的锁操作函数在多核CPU中的性能。[/align][align=left] [/align][align=left]原子操作选用InterlockedIncrement来进行测试,[/align][align=left]对每种锁和原子操作,都测试在单任务执行和多任务执行2000000次加锁解锁操作所消耗的时间。[/align][align=left]测试的详细代码见后面。[/align][align=left] [/align][align=left]测试机器环境: Intel 2.66G 双核CPU 机器一台[/align][align=left] [/align][align=left]测试运行结果如下:[/align][align=left]SingleThread, InterlockedIncrement 2,000,000: a = 2000000, time = 78[/align][align=left]MultiThread, InterlockedIncrement 2,000,000: a = 2000000, time = 156[/align][align=left]SingleThread, Critical_Section 2,000,000:a = 2000000, time = 172[/align][align=left]MultiThread, Critical_Section, 2,000,000:a = 2000000, time = 3156[/align][align=left]SingleThread,omp_lock 2,000,000:a = 2000000, time = 250[/align][align=left]MultiThread,omp_lock 2,000,000:a = 2000000, time = 1063[/align][align=left] [/align][align=left]在单任务运行情况下,所消耗的时间如下:[/align][align=left]原子操作                 78ms[/align][align=left]Windows CriticalSection 172ms[/align][align=left]OpenMP 的lock操作        250ms[/align][align=left] [/align][align=left]因此从单任务情况来看,原子操作最快,Windows CriticalSection次之,OpenMP库带的锁最慢,但这几种操作的时间差距不是很大,用锁操作比原子操作慢了2~3倍左右。[/align][align=left] [/align][align=left]在多个任务运行的情况下,所消耗的时间如下:[/align][align=left] [/align][align=left]原子操作                 156ms[/align][align=left]Windows CriticalSection 3156ms[/align][align=left]OpenMP 的lock操作        1063ms[/align][align=left] [/align][align=left]在多任务运行情况下,情况发生了意想不到的变化,原子操作时间比单任务操作时慢了一倍,在两个CPU上运行比在单个CPU上运行还慢一倍,真是难以想象,估计是任务切换开销造成的。[/align][align=left]Windows CriticalSection则更离谱了,居然花了3156ms,是单任务运行时的18倍多的时间,慢得简直无法想象。[/align][align=left]OpenMP的lock操作比Windows CriticalSection稍微好一些,但也花了1063ms,是单任务时的7倍左右。[/align][align=left] [/align][align=left]由此可以知道,在多核CPU的多任务环境中,原子操作是最快的,而OpenMP次之,Windows CriticalSection则最慢。[/align][align=left] [/align][align=left]同时从这些锁在单任务和多任务下的性能差距可以看出,,多核CPU上的编程和以往的单核多任务编程会有很大的区别。[/align][align=left][/align][align=left]需要说明的是,本测试是一种极端情况下的测试,锁住的操作只是一个简单的加1操作,并且锁竞争次数达200万次之多,在实际情况中,一由于任务中还有很多不需要加锁的代码在运行,实际情况中的性能会比本测试的性能好很多。[/align][align=left] [/align][align=left] [/align][align=left]测试代码如下:[/align][align=left] [/align][align=left]// TestLock.cpp : OpenMP任务中的原子操作和锁性能测试程序。[/align][align=left]//[/align][align=left] [/align][align=left]#include [/align][align=left]#include [/align][align=left]#include [/align][align=left]#include [/align][align=left]#include [/align][align=left] [/align][align=left]void TestAtomic()[/align][align=left]{[/align][align=left]     clock_t t1,t2;[/align][align=left]     int      i = 0;[/align][align=left]     volatile LONG      a = 0;[/align][align=left] [/align][align=left]     t1 = clock();[/align][align=left] [/align][align=left]     for( i = 0; i < 2000000; i++ )[/align][align=left]     {[/align][align=left]         InterlockedIncrement( &a);[/align][align=left]     }[/align][align=left]     [/align][align=left]     t2 = clock();[/align][align=left]     printf("SingleThread, InterlockedIncrement 2,000,000: a = %ld, time = %ld/n", a, t2-t1);[/align][align=left] [/align][align=left]     t1 = clock();[/align][align=left] [/align][align=left]#pragma omp parallel for[/align][align=left]     for( i = 0; i < 2000000; i++ )[/align][align=left]     {[/align][align=left]         InterlockedIncrement( &a);[/align][align=left]     }[/align][align=left]     [/align][align=left]     t2 = clock();[/align][align=left]     printf("MultiThread, InterlockedIncrement 2,000,000: a = %ld, time = %ld/n", a, t2-t1);[/align][align=left]}[/align][align=left] [/align][align=left]void TestOmpLock()[/align][align=left]{[/align][align=left]     clock_t t1,t2;[/align][align=left]     int i;[/align][align=left]     int a = 0;[/align][align=left]     omp_lock_t    mylock;[/align][align=left] [/align][align=left]     omp_init_lock(&mylock);[/align][align=left] [/align][align=left]     t1 = clock();[/align][align=left] [/align][align=left]     for( i = 0; i < 2000000; i++ )[/align][align=left]     {[/align][align=left]         omp_set_lock(&mylock);[/align][align=left]         a+=1;[/align][align=left]         omp_unset_lock(&mylock);[/align][align=left]     }[/align][align=left]     t2 = clock();[/align][align=left]     [/align][align=left]     printf("SingleThread,omp_lock 2,000,000:a = %ld, time = %ld/n", a, t2-t1);[/align][align=left] [/align][align=left]     t1 = clock();[/align][align=left] [/align][align=left]#pragma omp parallel for [/align][align=left]     for( i = 0; i < 2000000; i++ )[/align][align=left]     {[/align][align=left]         omp_set_lock(&mylock);[/align][align=left]         a+=1;[/align][align=left]         omp_unset_lock(&mylock);[/align][align=left]     }[/align][align=left]     t2 = clock();[/align][align=left]     [/align][align=left]     printf("MultiThread,omp_lock 2,000,000:a = %ld, time = %ld/n", a, t2-t1);[/align][align=left] [/align][align=left]     omp_destroy_lock(&mylock);[/align][align=left]}[/align][align=left] [/align][align=left] [/align][align=left] [/align][align=left]void TestCriticalSection()[/align][align=left]{[/align][align=left]     clock_t t1,t2;[/align][align=left]     int i;[/align][align=left]     int a = 0;[/align][align=left]     CRITICAL_SECTION   cs;[/align][align=left] [/align][align=left]     InitializeCriticalSection(&cs);[/align][align=left] [/align][align=left]     t1 = clock();[/align][align=left] [/align][align=left]     for( i = 0; i < 2000000; i++ )[/align][align=left]     {[/align][align=left]         EnterCriticalSection(&cs);[/align][align=left]         a+=1;[/align][align=left]         LeaveCriticalSection(&cs);[/align][align=left]     }[/align][align=left]     t2 = clock();[/align][align=left] [/align][align=left]     printf("SingleThread, Critical_Section 2,000,000:a = %ld, time = %ld/n", a, t2-t1);[/align][align=left] [/align][align=left]     t1 = clock();[/align][align=left] [/align][align=left]#pragma omp parallel for [/align][align=left]     for( i = 0; i < 2000000; i++ )[/align][align=left]     {[/align][align=left]         EnterCriticalSection(&cs);[/align][align=left]         a+=1;[/align][align=left]         LeaveCriticalSection(&cs);[/align][align=left]     }[/align][align=left]     t2 = clock();[/align][align=left] [/align][align=left]     printf("MultiThread, Critical_Section, 2,000,000:a = %ld, time = %ld/n", a, t2-t1);[/align][align=left] [/align][align=left]     DeleteCriticalSection(&cs);[/align][align=left] [/align][align=left]}[/align][align=left] [/align][align=left]int main(int argc, char* argv[])[/align][align=left]{[/align][align=left] [/align][align=left]     TestAtomic();[/align][align=left]     TestCriticalSection();[/align][align=left]     TestOmpLock();[/align][align=left] [/align][align=left]     return 0;[/align][align=left]}[/align][align=left] [/align] 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: