`
lovnet
  • 浏览: 6823993 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

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

阅读更多

OpenMP创建线程中的锁及原子操作性能比较
相关文档连接:
在多核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 CriticalSection172ms
OpenMP 的lock操作 250ms
因此从单任务情况来看,原子操作最快,Windows CriticalSection次之,OpenMP库带的锁最慢,但这几种操作的时间差距不是很大,用锁操作比原子操作慢了2~3倍左右。
在多个任务运行的情况下,所消耗的时间如下:
原子操作 156ms
Windows CriticalSection3156ms
OpenMP 的lock操作 1063ms
在多任务运行情况下,情况发生了意想不到的变化,原子操作时间比单任务操作时慢了一倍,在两个CPU上运行比在单个CPU上运行还慢一倍,真是难以想象,估计是任务切换开销造成的。
Windows CriticalSection则更离谱了,居然花了3156ms,是单任务运行时的18倍多的时间,慢得简直无法想象。
OpenMP的lock操作比Windows CriticalSection稍微好一些,但也花了1063ms,是单任务时的7倍左右。
由此可以知道,在多核CPU的多任务环境中,原子操作是最快的,而OpenMP次之,Windows CriticalSection则最慢。
同时从这些锁在单任务和多任务下的性能差距可以看出,,多核CPU上的编程和以往的单核多任务编程会有很大的区别。
需要说明的是,本测试是一种极端情况下的测试,锁住的操作只是一个简单的加1操作,并且锁竞争次数达200万次之多,在实际情况中,一由于任务中还有很多不需要加锁的代码在运行,实际情况中的性能会比本测试的性能好很多。
测试代码如下:
// TestLock.cpp : OpenMP任务中的原子操作和锁性能测试程序。
//
#include <windows.h>
#include <time.h>
#include <process.h>
#include <omp.h>
#include <stdio.h>
void TestAtomic()
{
clock_tt1,t2;
int i = 0;
volatile LONG a = 0;
t1 = clock();
for( i = 0; i < 2000000; i++ )
{
InterlockedIncrement( &a);
}
t2 = clock();
printf("SingleThread, InterlockedIncrement 2,000,000: a = %ld, time = %ld\n", a, t2-t1);
t1 = clock();
#pragma omp parallel for
for( i = 0; i < 2000000; i++ )
{
InterlockedIncrement( &a);
}
t2 = clock();
printf("MultiThread, InterlockedIncrement 2,000,000: a = %ld, time = %ld\n", a, t2-t1);
}
void TestOmpLock()
{
clock_t t1,t2;
int i;
int a = 0;
omp_lock_t mylock;
omp_init_lock(&mylock);
t1 = clock();
for( i = 0; i < 2000000; i++ )
{
omp_set_lock(&mylock);
a+=1;
omp_unset_lock(&mylock);
}
t2 = clock();
printf("SingleThread,omp_lock 2,000,000:a = %ld, time = %ld\n", a, t2-t1);
t1 = clock();
#pragma omp parallel for
for( i = 0; i < 2000000; i++ )
{
omp_set_lock(&mylock);
a+=1;
omp_unset_lock(&mylock);
}
t2 = clock();
printf("MultiThread,omp_lock 2,000,000:a = %ld, time = %ld\n", a, t2-t1);
omp_destroy_lock(&mylock);
}
void TestCriticalSection()
{
clock_t t1,t2;
int i;
inta = 0;
CRITICAL_SECTION cs;
InitializeCriticalSection(&cs);
t1 = clock();
for( i = 0; i < 2000000; i++ )
{
EnterCriticalSection(&cs);
a+=1;
LeaveCriticalSection(&cs);
}
t2 = clock();
printf("SingleThread, Critical_Section 2,000,000:a = %ld, time = %ld\n", a, t2-t1);
t1 = clock();
#pragma omp parallel for
for( i = 0; i < 2000000; i++ )
{
EnterCriticalSection(&cs);
a+=1;
LeaveCriticalSection(&cs);
}
t2 = clock();
printf("MultiThread, Critical_Section, 2,000,000:a = %ld, time = %ld\n", a, t2-t1);
DeleteCriticalSection(&cs);
}
int main(int argc, char* argv[])
{
TestAtomic();
TestCriticalSection();
TestOmpLock();
return 0;
}
分享到:
评论

相关推荐

    OpenMP中文版教程

    OpenMP还提供了创建线程时的锁及原子操作性能比较,以及一些程序设计小技巧,例如动态设置并行循环的线程数量和嵌套循环的并行化。这些内容在本教程中都有详细的介绍。 OpenMP的简易教程可以帮助初学者快速上手,但...

    很不错OpenMP入门资料,中文的

    在OpenMP程序中,最初的控制线程被称为**主线程**,而由主线程创建出来的线程被称为**工作线程**。主线程负责启动并行区,同时也可以参与并行计算。工作线程则负责执行并行区内的任务。 #### 三、OpenMP的基本使用...

    OpenMP用户手册(中文).docx

    原子操作(`atomic`)和内存屏障(`flush`)用于控制并发访问和内存一致性。 4. **任务(Tasks)**:`task`指令引入了异步任务执行,允许在执行过程中动态创建和调度任务,增加了灵活性。 5. **数据环境(Data ...

    OpenMP用户指南.pdf

    OpenMP提供了多种同步构造,包括master构造(指示只有主线程执行)、critical构造(代码段一次只允许一个线程执行)、barrier构造(线程执行到此构造时必须等待其他线程到达)、atomic构造(保证原子操作)和flush...

    openmp-4.5.rar

    6. **原子操作和锁定的增强**:OpenMP 4.5增加了对更复杂原子操作的支持,如比较并交换(CAS)和无锁数据结构,提供了更多的同步机制选项。 7. **并行区域的调试和分析**:4.5版增强了对并行代码的调试工具支持,如...

    Intel, OpenMP编程

    12. **Atomic指令**:`C$OMPATOMIC`用于确保一个表达式的原子性,即使在多线程环境中也能正确执行。 13. **Flush指令**:`C$OMPFLUSH`用于强制刷新缓存,确保数据的一致性。 14. **Ordered并行循环**:`C$...

    OpenMP学习程序

    5. **原子操作(Atomic Operations)**:`#pragma omp atomic`用于保证对某个变量的更新是原子的,即不会被其他线程中断。 6. **单指令多数据(SIMD)向量化**:OpenMP 4.0引入了SIMD指令,允许并行处理向量数据,...

    OpenMP例子程序

    在学习OpenMP时,理解其背后的并发概念,如锁、条件变量和任务调度,以及如何优化并行性能,如减少同步开销和避免不必要的数据通信,都是非常重要的。通过这个例子程序,你将有机会亲自动手实践,这通常比阅读理论...

    OpenMP编程教程

    其中包括线程同步机制(如屏障、锁和原子操作)以及线程私有数据的管理等。运行库例程使得并行程序能有效管理线程间的依赖和数据一致性问题。 #### 环境变量 OpenMP还提供了一组环境变量,允许程序员控制并行行为...

    OpenMP+F90并行编程基础

    - `ATOMIC`: 保证一个或一组操作的原子性,即不允许其他线程插入操作。 #### 数据环境构造(Data Environment Constructs) 数据环境构造用于管理并行区域内的数据。这些构造包括: - `SAVED`: 保存并行区域外的...

    OpenMP 4.0 手册

    OpenMP提供了多种同步原语,如`mutexes`(互斥锁)、`critical sections`(临界区)、`atomic operations`(原子操作)和`locks`,以防止数据竞争和确保正确性。 8. **并行区域和工作共享** `#pragma omp ...

    OpenMP 3.0 英文规范

    在这一模型中,主进程负责启动并行区域,并创建一个或多个线程来执行并行代码块。线程之间通过共享内存进行通信和同步。 **1.4 内存模型** - **1.4.1 OpenMP 内存模型结构** - OpenMP 内存模型基于共享内存系统。...

    OpenMP 入门程序 --- 手把手教你学会并行程序

    原子操作(atomic operations)如`#pragma omp atomic`用于保证在多线程环境下对共享变量的无冲突访问,防止数据竞争。临界区(critical regions)通过`#pragma omp critical`指令,确保同一时刻只有一个线程能执行...

    hw1.rar_critical_openmp_openmp critical

    2. **OpenMP Reduction**:`reduction`是OpenMP提供的一种优化机制,用于高效地合并多个线程的局部变量值,比如在求和、最大值或最小值等操作中。它避免了多个线程同时更新同一个全局变量可能导致的冲突,减少了同步...

    OpenMP 4.0 API Specification

    OpenMP 4.0 规定了一个清晰的执行模型,该模型定义了线程如何创建、销毁以及如何分配工作。在这个模型中,每个并行区域都由一个主串启动,并根据构造的不同生成一定数量的工作串。 #### 五、内存模型 - **Structure...

    OpenMP开发规范

    OpenMP采用动态线程模型,允许程序在运行时根据需要创建和销毁线程。这种模型可以更好地适应不同类型的并行应用程序,提高资源利用率。 ##### 1.4 内存模型 - **1.4.1 OpenMP内存模型结构** - **共享存储区(Shared...

    基于OpenMP的并行程序设计

    对于同步,OpenMP提供了诸如屏障、临界区、原子操作等机制,以确保线程间操作的同步性和数据的一致性。 OpenMP的并行程序设计对于性能的提升主要体现在它可以利用多核处理器的并行计算能力,加快计算密集型任务的...

    OpenMP Intro

    在OpenMP中创建线程主要是通过并行区域实现的。并行区域内的代码会被多个线程并行执行。下面是一个简单的示例,展示了如何使用OpenMP创建线程: ```c #include #include int main() { #pragma omp parallel { ...

Global site tag (gtag.js) - Google Analytics