PowerPoint Presentation

Similar documents
并行算法实践

并行计算

第7章-并行计算.ppt

Microsoft PowerPoint - PC13.pptx

IntelBook_cn.doc

提纲 1 2 OS Examples for 3

2011, Oracle / U.S. GOVERNMENT END USERS: Oracle programs, including any operating system, integrated software, any programs installed on the hardware

chap07.key

FY.DOC

C/C++语言 - C/C++数据

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.06.doc

技术沙龙-OpenMP并行技术

C/C++ - 字符输入输出和字符确认

C/C++语言 - 运算符、表达式和语句

C/C++ - 函数

最简单的MPI程序 Hello world(C)

WWW PHP Comments Literals Identifiers Keywords Variables Constants Data Types Operators & Expressions 2

3.1 num = 3 ch = 'C' 2

02

C C

1 LINUX IDE Emacs gcc gdb Emacs + gcc + gdb IDE Emacs IDE C Emacs Emacs IDE ICE Integrated Computing Environment Emacs Unix Linux Emacs Emacs Emacs Un

C 1

, 7, Windows,,,, : ,,,, ;,, ( CIP) /,,. : ;, ( 21 ) ISBN : -. TP CIP ( 2005) 1

CC213

第3章.doc

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数

C/C++ 语言 - 循环

C++ 程式設計

ebook

CC213

untitled

IntelBook_cn.doc

エスポラージュ株式会社 住所 : 東京都江東区大島 東急ドエルアルス大島 HP: ******************* * 关于 Java 测试试题 ******

C/C++程序设计 - 字符串与格式化输入/输出

提纲 Classical Problems of Synchronization 1 Classical Problems of Synchronization 2 3 4

ebook15-2

Fun Time (1) What happens in memory? 1 i n t i ; 2 s h o r t j ; 3 double k ; 4 char c = a ; 5 i = 3; j = 2; 6 k = i j ; H.-T. Lin (NTU CSIE) Referenc

新・解きながら学ぶJava

Microsoft PowerPoint - os_4.ppt

前言 编写 OpenMP 编译原理及实现技术 教材是深圳大学 计算机科学与技术国家特色专业建设点 的建设内容之一 该教材和相应课程的设计目的有三点 : 衔接本科 编译原理 课程 扩展 OpenMP 并行语言编译的知识 增强学生的动手实践和编程能力, 书中以 OpenMP 的一个开源编译器 OMPi

WWW PHP

C/C++ - 文件IO

PowerPoint 演示文稿

Microsoft Word - 第3章.doc

工 序 的 是 ( ) A. 卷 筒 切 筒 装 药 造 粒 B. 搬 运 造 粒 切 引 装 药 C. 造 粒 切 引 包 装 检 验 D. 切 引 包 装 检 验 运 输 7. 甲 公 司 将 其 实 施 工 项 目 发 包 给 乙 公 司, 乙 公 司 将 其 中 部 分 业 务 分 包 给

ebook8-30

Microsoft PowerPoint - RT0950_EliminatingRubyGILthroughHTM_Slides_ja.ppt

投影片 1

《嵌入式系统设计》教学大纲

2 2 3 DLight CPU I/O DLight Oracle Solaris (DTrace) C/C++ Solaris DLight DTrace DLight DLight DLight C C++ Fortran CPU I/O DLight AM

3.1 并行程序设计基础与样例_软件学院_徐悦甡_第一部分

epub83-1

C C C The Most Beautiful Language and Most Dangerous Language in the Programming World! C 2 C C C 4 C Project 30 C Project 3 60 Project 40

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

Java

(A)3 4 (B)5 6 (C)7 9 (D)10 2 (E) (A) (B) (C) (D) (E) ( ) ( ) ( ) (A) (B) (C) (D) (E) (A) (B) (C) (D) (E). (A) (B) (C) (D) (E). (A) (B) (C) (D) (

mvc

科学计算的语言-FORTRAN95

C

untitled

C

51 C 51 isp 10 C PCB C C C C KEIL

C语言的应用.PDF

EK-STM32F

第5章修改稿

Windows RTEMS 1 Danilliu MMI TCP/IP QEMU i386 QEMU ARM POWERPC i386 IPC PC104 uc/os-ii uc/os MMI TCP/IP i386 PORT Linux ecos Linux ecos ecos eco

第 15 章 程 式 編 写 語 言 15.1 程 式 編 写 語 言 的 角 色 程 式 編 寫 語 言 是 程 式 編 寫 員 與 電 腦 溝 通 的 界 面 語 法 是 一 組 規 則 讓 程 式 編 寫 員 將 字 詞 集 合 起 來 電 腦 是 處 理 位 元 和 字 節 的 機 器, 與

Microsoft PowerPoint - multicore curriculum of sspku.ppt

新版 明解C言語入門編

版权所有 2004 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,California 95054, U.S.A. 保留所有权利 美国政府权利 - 商业软件 政府用户应遵守 Sun Microsystems, Inc. 标准许可证协

并行程序设计基础

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.07.doc

( CIP) /. :, ( ) ISBN TP CIP ( 2005) : : : : * : : 174 ( A ) : : ( 023) : ( 023)

untitled

Chapter 9: Objects and Classes

版权所有 2005 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, California 95054, U.S.A. 保留所有权利 美国政府权利 - 商业软件 政府用户应遵循 Sun Microsystems, Inc. 的标准许可

untitled

CHAPTER VC#

2/80 2

<4D F736F F D20A1BE A1BF C4EABDADCBD5D7CFBDF0C5A9B4E5C9CCD2B5D2F8D0D0B9C9B7DDD3D0CFDEB9ABCBBEB8FAD7D9C6C0BCB6B1A8B8E6A3A8B8FAD7D A3A9>

1 Project New Project 1 2 Windows 1 3 N C test Windows uv2 KEIL uvision2 1 2 New Project Ateml AT89C AT89C51 3 KEIL Demo C C File

<4D F736F F F696E74202D BDE1B9B9BBAFB3CCD0F2C9E8BCC D20D1ADBBB7>

BOOL EnumWindows(WNDENUMPROC lparam); lpenumfunc, LPARAM (Native Interface) PowerBuilder PowerBuilder PBNI 2

CH01.indd

Microsoft Word - n doc

untitled

先生別耍我

W. Richard Stevens UNIX Sockets API echo Sockets TCP OOB IO C struct C/C++ UNIX fork() select(2)/poll(2)/epoll(4) IO IO CPU 100% libevent UNIX CPU IO

6 C51 ANSI C Turbo C C51 Turbo C C51 C51 C51 C51 C51 C51 C51 C51 C C C51 C51 ANSI C MCS-51 C51 ANSI C C C51 bit Byte bit sbit

int *p int a 0x00C7 0x00C7 0x00C int I[2], *pi = &I[0]; pi++; char C[2], *pc = &C[0]; pc++; float F[2], *pf = &F[0]; pf++;

Microsoft Word - PS2_linux_guide_cn.doc

<4D F736F F D D342DA57CA7DEA447B14D2DA475B57BBB50BADEB27AC3FEB14DA447B8D5C344>

c_cpp

前言 C# C# C# C C# C# C# C# C# microservices C# More Effective C# More Effective C# C# C# C# Effective C# 50 C# C# 7 Effective vii

sp_overview.pptx

新版 明解C++入門編

Microsoft Word - 物件導向編程精要.doc

ebook50-15

Java 1 Java String Date

Microsoft PowerPoint - OPVB1基本VB.ppt

Transcription:

并行计算 Parallel Computing 主讲人徐云 Spring, 2019

第四篇并行程序设计 第十三章并行程序设计基础第十四章共享存储系统并行编程第十五章分布存储系统并行编程第十六章并行程序设计环境与工具

第十四章共享存储系统并行编程 14.1 ANSI X3H5 共享存储模型 14.2 POSIX 线程模型 14.3 OpenMP 模型 国家高性能计算中心 ( 合肥 )

编程模型的作用 规定程序的执行模型 SPMD, SMP 等 如何表达并行性 DOACROSS, FORALL, PARALLEL, INDEPENDENT 如何表达同步 Lock, Barrier, Semaphore, Condition Variables 如何获得运行时的环境变量 threadid, num of processes 国家高性能计算中心 ( 合肥 )

ANSI X3H5 共享存储模型历史 Started in the mid-80 s with the emergence of shared memory parallel computers with proprietary directive driven programming environments; 更早的标准化结果 PCF 共享存储器并行 Fortran; 1993 年制定的概念性编程模型 ; Language Binding C; Fortran 77; Fortran 90 国家高性能计算中心 ( 合肥 )

X3H5 模型中并行语句规定 并行块 ( 工作共享构造 ); 并行块 (psections... end psections) 并行循环 (pdo... Endo pdo) 单进程 (psingle... End psingle) 可嵌套 非共享块重复执行 ; 隐式路障 显式路障和阻挡操作 ; 共享 / 私有变量 ; 线程同步 ; 门插销 (latch): 临界区 锁 :test,lock,unlock 事件 : wait,post,clear 序数 (ordinal): 顺序 国家高性能计算中心 ( 合肥 )

X3H5: 并行性构造之例 Program main! 程序以顺序模式开始, 此时只有一个 A!A 只由基本线程执行, 称为主线程 parallel! 转换为并行模式, 派生出多个子线程 ( 一个组 ) B!B 为每个组员所复制 psections! 并行块开始 section C! 一个组员执行 C section D! 一个组员执行 D end psections! 等待 C 和 D 都结束 psingle! 暂时转换成顺序模式 E!E 由一个组员执行 end psingle! 转回并行模式 pdo i=1,6!pdo 构造开始 F(i)! 组员共享 F 的六次迭代 end pdo no wait! 无隐式路障同步 G! 更多的复制代码 end parallel! 转为顺序模式 H! 初始化进程单独执行 H...! 可能有更多的并行构造 End 国家高性能计算中心 ( 合肥 )

线程 P Q R A 隐式路障同步 B B B C D 隐式路障同步隐式路障同步无隐式路障同步 F(1:2) G E F(3:4) G F(5:6) G 隐式路障同步 国家高性能计算中心 ( 合肥 ) H

第十四章共享存储系统并行编程 14.1 ANSI X3H5 共享存储模型 14.2 POSIX 线程模型 14.3 OpenMP 模型 国家高性能计算中心 ( 合肥 )

POSIX线程模型 POSIX可移植操作系统接口 Portable Operating System Interface of UNIX IEEE/ANSI标准 IEEE POSIX 1003.1c-1995线程标准 Unix/NT操作系统层上的 针对SMP机器 多种UNIX OS支持 Sun OS(Solaris) AIX VMS等 Win32 NT Thread支持 GetThreadHandle,SetThreadPriority,SuspendThread,ResumeThread TLS(线程局部存储) TlsAlloc, TlsSetValue LinuxThreads 支持: clone sys_clone 线程层概念 用户线程 内核线程 (LWP)(一到一 一到多 多到多) 国家高性能计算中心 合肥

What Are Threads? Shared state (memory, files, etc.) Threads General-purpose solution for managing concurrency. Multiple independent execution streams. Shared state. Preemptive scheduling. Synchronization (e.g. locks, conditions). 国家高性能计算中心 ( 合肥 )

And more Cont. 线程共享相同的内存空间 与标准 fork() 相比 线程带来的开销很小 内核无需单独复 制进程的内存空间或文件描述符等等 这就节省了大量的 CPU 时间 和进程一样 线程将利用多 CPU 支持内存共享无需使用繁琐的 IPC 和其它复杂的通信机制 Linux clone不可移植 Pthread可移植 POSIX 线程标准不记录任何 家族 信息 无父无子 如 果要等待一个线程终止 就必须将线程的 tid 传递给 pthread_join() 线程库无法为您断定 tid 国家高性能计算中心 合肥

国家高性能计算中心 ( 合肥 ) POSIX Threads: Basics and Examples by Uday Kamath http://www.coe.uncc.edu/~abw/parallel /pthreads/pthreads.html POSIX 线程详解 : 一种支持内存共享的简单和快捷的工具 by Daniel Robbins http://www.cn.ibm.com/developerwor ks/linux/thread/posix_thread1/index.sht ml

线程调用 线程管理 POSIX Solaris 2 pthread_create thr_create pthread_exit thr_exit pthread_kill thr_kill pthread_join thr_join pthread_self thr_self 国家高性能计算中心 ( 合肥 )

线程调用 线程同步和互斥 POSIX Solaris 2 pthread_mutex_init mutex_init pthread_ mutex_destroy mutex_destroy pthread_ mutex_lock mutex_lock pthread_ mutex_trylock mutex_trylock pthread_ mutex_unlock mutex_unlock pthread_cond_init pthread_cond_destroy pthread_cond_wait pthread_cond_timedwait pthread_cond_signal pthread_cond_broadcast 国家高性能计算中心 ( 合肥 )

Pthreads 实现计算 的实例 1 国家高性能计算中心 ( 合肥 )

Pthreads 实现计算 的实例 2 国家高性能计算中心 ( 合肥 )

第十四章共享存储系统并行编程 14.1 ANSI X3H5 共享存储模型 14.2 POSIX 线程模型 14.3 OpenMP 模型 OpenMP 概述 OpenMP 编程风络 OpenMP 编程简介 运行库例程与环境变量 OpenMP 计算实例 国家高性能计算中心 ( 合肥 )

OpenMP 概述 OpenMP 应用编程 接口 API 是在共享 存储体系结构上的 一个编程模型 ; 最新版本 5.0; 包含编译制导 (Compiler Directive) 运行库例程 (Runtime Library) 和环境变量 (Environment Variables) ; 支持增量并行化 (Incremental Parallelization)

OpenMP 体系结构 应 用 用 户 编译制导 环境变量 运行库例程 OS 线程

什么是 OpenMP 什么是 OpenMP 应用编程接口 API(Application Programming Interface ); 由三个基本 API 部分 ( 编译指令 运行部分和环境变量 ) 构成 ; 是 C/C++ 和 Fortan 等的应用编程接口 ; 已经被大多数计算机硬件和软件厂家所标准化 OpenMP 不包含的性质 不是建立在分布式存储系统上的 ; 不是在所有的环境下都是一样的 ; 不是能保证让多数共享存储器均能有效的利用

OpenMP 的历史 1994 年, 第一个 ANSI X3H5 草案提出, 被否决 ; 1997 年,OpenMP 标准规范代替原先被否决的 ANSI X3H5, 被人们认可 ; 1997 年 10 月公布了与 Fortran 语言捆绑的第一个标准规范 ; 1998 年 11 月 9 日公布了支持 C 和 C++ 的标准规范 ; 目前 Fortran77 Fortran90 C C++ 语言的实现规范已经完成 ; 2018 年 11 月发布了 OpenMP 5.0 版本 ; 资源网站 :http://www.openmp.org http://phase.hpcc.jp/omni/

OpenMP 的目标 标准性 简洁实用 使用方便 可移植性

OpenMP 5.0 is a major leap forward

OpenMP 并行编程模型 基于线程的并行编程模型 (Programming Model); OpenMP 使用 Fork-Join 并行执行模型 主线程 F O R K J O I N F O R K J O I N 并行域 并行域

OpenMP 程序结构 基于 Fortran 语言的 OpenMP 程序的结构 PROGRAM HELLO INTEGER VAR1, VAR2, VAR3!Serial code!beginning of parallel section. Fork a team of threads.!specify variable scoping!$omp PARALLEL PRIVATE(VAR1, VAR2) SHARED(VAR3)!Parallel section executed by all threads!all threads join master thread and disband!$omp END PARALLEL!Resume serial code END

OpenMP 程序结构 基于 c/c++ 语言的 OpenMP 程序的结构 #include <omp.h> main (){ int var1, var2, var3; /*Serial code*/ /*Beginning of parallel section. Fork a team of threads*/ /*Specify variable scoping */ #pragma omp parallel private(var1, var2) shared(var3) { /*Parallel section executed by all threads*/ /*All threads join master thread and disband*/ } /*Resume serial code */ }

一个简单的 OpenMP 程序实例 基于 C/C++ 语言的 OpenMP 程序结构的一个具体实现 #include "omp.h" int main(int argc, char* argv[]) { int nthreads, tid; int nprocs; char buf[32]; /* Fork a team of threads */ #pragma omp parallel private(nthreads, tid) { /* Obtain and print thread id */ tid = omp_get_thread_num(); printf("hello World from OMP thread %d\n", tid); /* Only master thread does this */ if (tid==0) { nthreads = omp_get_num_threads(); printf("number of threads %d\n", nthreads); } } return 0; }

一个简单的 OpenMP 程序实例 运行结果 (setenv OMP_NUM_THREADS 8) Hello World from OMP thread 0 Number of threads 8 Hello World from OMP thread 4 Hello World from OMP thread 5 Hello World from OMP thread 6 Hello World from OMP thread 7 Hello World from OMP thread 2 Hello World from OMP thread 1 Hello World from OMP thread 3

OpenMP 程序性能举例 void test() { int a=0; clock_t t1=clock(); for ( int i=0; i<100000000; i++ ) { a=i+1; } clock_t t2=clock(); printf("test Time=%d\n", t2-t1); } int main(int argc, char *argv[]) { clock_t t1=clock(); #pragma omp parallel for for ( int j=0; j<2; j++) { test(); } clock_t t2=clock(); printf("test Time=%d\n", t2-t1); test(); return(); } 运行结果如下 : Test Time=297 Test Time=297 Test Time=297 Test Time=297

编译制导 语句格式 #pragma omp directive-name [clause,...] newline 制导指令前缀 对所有的 OpenMP 语句都需要这样的前缀 OpenMP 制导指令 在制导指令前缀和子句之间必须有一个正确的 OpenMP 制导指令 子句 在没有其它约束条件下, 子句可以无序, 也可以任意的选择 这一部分也可以没有 换行符 表明这条制导语句的终止

编译制导 作用域 静态扩展 文本代码在一个编译制导语句之后, 被封装到一个结构块中 孤立语句 一个 OpenMP 的编译制导语句不依赖于其它的语句 动态扩展 包括静态范围和孤立语句

作用域 动态范围 静态范围 for 语句出现在一个封闭的并行域中 #pragma omp parallel { } #pragma omp for for( ){ } sub1(); sub2(); 孤立语句 critical 和 sections 语句出现在封闭的并行域之外 void sub1() { #pragma omp critical } void sub2() { #pragma omp sections }

并行域结构 并行域中的代码被所有的线程执行 ; 具体格式 #pragma omp parallel [clause[[,]clause] ]newline clause= if (scalar_expression) private (list) shared (list) default (shared none) firstprivate (list) reduction (operator: list) copyin (list)

共享任务结构 共享任务结构将它所包含的代码划分给线程组的各成员来执行 并行 for 循环 ; 并行 sections; 串行执行 主线程 主线程 FORK FORK FORK 主线程 DO/for loop 线程列 SECTIONS 线程列 SINGLE 线程列 JOIN JOIN JOIN 主线程 主线程 主线程

for 编译制导语句 for 语句指定紧随它的循环语句必须由线程组并行执行 ; 语句格式 #pragma omp for [clause[[,]clause] ] newline [clause]= Schedule(type [,chunk]) ordered private (list) firstprivate (list) lastprivate (list) shared (list) reduction (operator: list) nowait

for 编译制导语句 示例 : int j=0; #pragma omp parallel { #pragma omp for for (j=0; j<4; j++) { printf("j=%d, ThreadId=%d\n", omp_get_thread_num();} } 运行结果 : j=1, ThreadId=1 j=3, ThreadId=3 j=2, ThreadId=2 j=0, ThreadId=0

for 编译制导语句 schedule 子句描述如何将循环的迭代划分给线程组中的线程 ; 如果没有指定 chunk 大小, 迭代会尽可能的平均分配给每个线程 ; type 为 static, 循环被分成大小为 chunk 的块, 静态分配给线程 ; type 为 dynamic, 循环被动态划分为大小为 chunk 的块, 动态分配给线程 ; type 为 guided, 采用启发式调度, 每次分配给线程迭代次数不同, 开始比较大, 以后逐渐减小 ; type 为 runtime, 允许在运行时确定调度类型

Sections 编译制导语句 sections 编译制导语句指定内部的代码被划分给线程组中的各线程 ; 不同的 section 由不同的线程执行 ; Section 语句格式 : #pragma omp sections [ clause[[,]clause] ] newline { [#pragma omp section newline] [#pragma omp section newline] }

Sections 编译制导语句 clause= private (list) firstprivate (list) lastprivate (list) reduction (operator: list) nowait 在 sections 语句结束处有一个隐含的路障, 使用了 nowait 子句除外

Sections 编译制导语句 #include <omp.h> #define N 1000 int main (){ int i; float a[n], b[n], c[n]; /* Some initializations */ for (i=0; i < N; i++) a[i] = b[i] = i * 1.0; #pragma omp parallel shared(a,b,c) private(i) { #pragma omp sections nowait { #pragma omp section for (i=0; i < N/2; i++) c[i] = a[i] + b[i]; #pragma omp section for (i=n/2; i < N; i++) c[i] = a[i] + b[i]; } /* end of sections */ } /* end of parallel section */ }

single 编译制导语句 single 编译制导语句指定内部代码只有线程组中的一个线程执行 ; 线程组中没有执行 single 语句的线程会一直等待代码块的结束, 使用 nowait 子句除外 ; 语句格式 : #pragma omp single [clause[[,]clause] ] newline clause= private(list) firstprivate(list) nowait

组合的并行共享任务结构 parallel for 编译制导语句 ; parallel sections 编译制导语句

parallel for 编译制导语句 Parallel for 编译制导语句表明一个并行域包含一个独立的 for 语句 ; 语句格式 #pragma omp parallel for [clause ] newline clause= if (scalar_logical_expression) default (shared none) schedule (type [,chunk]) shared (list) private (list) firstprivate (list) lastprivate (list) reduction (operator: list) copyin (list)

parallel for 编译制导语句 #include <omp.h> #define N 1000 #define CHUNKSIZE 100 int main () { int i, chunk; float a[n], b[n], c[n]; /* Some initializations */ for (i=0; i < N; i++) a[i] = b[i] = i * 1.0; chunk = CHUNKSIZE; #pragma omp parallel for \ shared(a,b,c,chunk) private(i) \ schedule(static,chunk) for (i=0; i < n; i++) c[i] = a[i] + b[i]; }

parallel sections 编译制导语句 parallel sections 编译制导语句表明一个并行域包含单独的一个 sections 语句 ; 语句格式 #pragma omp parallel sections [clause ] newline clause= default (shared none) shared (list) private (list) firstprivate (list) lastprivate (list) reduction (operator: list) copyin (list) ordered

同步结构 master 制导语句 ; critical 制导语句 ; barrier 制导语句 ; atomic 制导语句 ; flush 制导语句 ; ordered 制导语句

master 制导语句 master 制导语句指定代码段只有主线程执行 ; 语句格式 #pragma omp master newline

critical 制导语句 critical 制导语句表明域中的代码一次只能执行一个线程 ; 其他线程被阻塞在临界区 ; 语句格式 : #pragma omp critical [name] newline

critical 制导语句 #include <omp.h> main() { int x; x = 0; #pragma omp parallel shared(x) { #pragma omp critical x = x + 1; } /* end of parallel section */ }

barrier 制导语句 barrier 制导语句用来同步一个线程组中所有的线程 ; 先到达的线程在此阻塞, 等待其他线程 ; barrier 语句最小代码必须是一个结构化的块 ; 语句格式 #pragma omp barrier newline

barrier 制导语句 barrier 正确与错误使用比较 错误 if (x == 0) #pragma omp barrier 正确 if (x == 0) { #pragma omp barrier }

atomic 制导语句 atomic 制导语句指定特定的存储单元将被原子更新 ; 语句格式 #pragma omp atomic newline atomic 使用的格式 x binop = expr x++ ++x x-- --x x 是一个标量 示例 : int i, nvar=0; expr 是一个不含对 x 引用的标量表达式, 且不被重载 binop 是 +,*,-,/,&,^,,>>,or<< 之一, 且不被重载 #pragma omp parallel for shared(nvar) for (i=0; i<1000; i++) { #pragma omp atomic nvar+=1; } 注 : 比较一下与临界区方法的性能

flush 制导语句 flush 制导语句用以标识一个同步点, 用以确保所有的线程看到一致的存储器视图 ; 语句格式 #pragma omp flush (list) newline flush 将在下面几种情形下隐含运行,nowait 子句除外 barrier critical: 进入与退出部分 ordered: 进入与退出部分 parallel: 退出部分 for: 退出部分 sections: 退出部分 single: 退出部分

ordered 制导语句 ordered 制导语句指出其所包含循环的执行 ; 任何时候只能有一个线程执行被 ordered 所限定部分 ; 只能出现在 for 或者 parallel for 语句的动态范围中 ; 语句格式 : #pragma omp ordered newline 示例 #pragma omp parallel for ordered schdule(static, 2) for (i=0; i<10; i++) #pragma omp ordered printf("i=%ld\n", i);

threadprivate 编译制导语句 threadprivate 语句使一个全局文件作用域的变量在并行域内变成每个线程私有 ; 每个线程对该变量复制一份私有拷贝 ; 语句格式 : #pragma omp threadprivate (list) newline

threadprivate 编译制导语句 复制全局变量为各自线程私有 int counter=0; #pragma omp threadprivate(counter) int increment_counter() { counter++; return(counter++); } 复制静态变量为各自线程私有 int increment_counter() { static int counter=0; #pragma omp threadprivate(counter) counter++; return(counter++); }

数据域属性子句 变量作用域范围 ; 数据域属性子句 : private 子句 ; shared 子句 ; default 子句 ; firstprivate 子句 ; lastprivate 子句 ; copyin 子句 ; reduction 子句

private 子句 private 子句表示它列出的变量对于每个线程是局部的 语句格式 : private(list) private 和 threadprivate 区别 PRIVATE THREADPRIVATE 数据类型变量变量 位置在域或共享任务单元开始在块或整个文件区域的例程的定义上 持久么否是 扩充性 只是词法的 - 除非作为子程序的参数而传递 动态范围 初始化使用 FIRSTPRIVATE 使用 COPYIN

private 和 threadprivate 区别 int global=111; #pragma omp threadprivate(global) int main() { global=222; #pragma omp parallel copyin(global) { printf("thread number %d global=%d\n",\ omp_get_thread_num(),global); global=omp_get_thread_num()+10; } printf("global=%d\n",global); printf("parallel again\n"); #pragma omp parallel printf("thread number %d global=%d\n",\ omp_get_thread_num(),global); printf("global=%d\n",global); return 0;} 运行结果 : Thread number 0 global=222 Thread number 3 global=222 Thread number 1 global=222 Thread number 2 global=222 global=10 parallel again Thread number 0 global=10 Thread number 3 global=13 Thread number 1 global=11 Thread number 2 global=12 global=10

private 和 threadprivate 区别 #include <omp.h> int alpha[10], beta[10], i; #pragma omp threadprivate(alpha) int main () { /* First parallel region */ #pragma omp parallel private(i,beta) for (i=0; i < 10; i++) alpha[i] = beta[i] = i; /* Second parallel region */ #pragma omp parallel printf("alpha[3]= %d and beta[3]=%d\n",alpha[3],beta[3]); } 思考 : 上机运行结果, 并分析

shared 子句 shared 子句表示它所列出的变量被线程组中所有的线程共享 ; 所有线程都能对它进行读写访问 ; 语句格式 : shared (list)

default 子句 default 子句让用户自行规定在一个并行域的静态范围中所定义变量的 shared 和 private 缺省性质 ; 语句格式 : default (shared none)

firstprivate 子句 firstprivate 子句是 private 子句的配合操作 ; 对变量做原子初始化 ; 语句格式 : firstprivate (list)

lastprivate 子句 lastprivate 子句是 private 子句的配合操作 ; 将变量从最后的循环迭代或段复制给原始的变量 ; 语句格式 : lastprivate (list)

copyin 子句 copyin 子句用来为线程组中所有线程的 threadprivate 变量赋相同的值 ; 主线程该变量的值作为初始值 ; 语句格式 : copyin(list)

reduction 子句 reduction 子句使用指定的操作对其列表中出现的变量进行归约 ; 初始时, 每个线程都保留一份私有拷贝 ; 在结构尾部根据指定的操作对线程中的相应变量进行归约, 并更新该变量的全局值 ; 语句格式 : reduction (operator: list)

reduction 子句 #include <omp.h> int main () { int i, n, chunk; float a[100], b[100], result; /* Some initializations */ n = 100; chunk = 10; result = 0.0; for (i=0; i < n; i++) { a[i] = i * 1.0; b[i] = i * 2.0; } #pragma omp parallel for default(shared) private(i)\ schedule(static,chunk) reduction(+:result) for (i=0; i < n; i++) result = result + (a[i] * b[i]); printf("final result= %f\n",result); }

reduction 子句 Reduction 子句的格式 x=x op expr x = expr op x (except subtraction) x binop = expr x++ ++x x-- --x x 是一个标量 expr 是一个不含对 x 引用的标量表达式, 且不被重载 binop 是 +,*,-,/,&,^, 之一, 且不被重载 op 是 +,*,-,/,&,^,,&&,or 之一, 且不被重载

子句 / 编译制导语句总结 编译制导 子句 PARALLEL DO/for SECTIONS SINGLE PARALLEL DO/for PARALLEL SECTIONS IF PRIVATE SHARED DEFAULT FIRSTPRIVA TE LASTPRIVAT E REDUCTION COPYIN SCHEDULE ORDERED NOWAIT

运行库例程与环境变量 运行库例程 OpenMP 标准定义了一个应用编程接口来调用库中的多种函数 ; 对于 C/C++, 在程序开头需要引用文件 omp.h 环境变量 OMP_SCHEDULE: 只能用到 for,parallel for 中 它的值就是处理器中循环的次数 ; OMP_NUM_THREADS: 定义执行中最大的线程数 ; OMP_DYNAMIC: 通过设定变量值 TRUE 或 FALSE, 来确定是否动态设定并行域执行的线程数 ; OMP_NESTED: 确定是否可以并行嵌套

OpenMP 计算实例 使用并行域并行化的程序 #include <omp.h> static long num_steps = 100000; double step; #define NUM_THREADS 2 void main () { int i; double x, pi, sum[num_threads]; step = 1.0/(double) num_steps; omp_set_num_threads(num_threads); #pragma omp parallel { double x; int id; id = omp_get_thread_num(); for (i=id, sum[id]=0.0;i< num_steps; i=i+num_threads){ x = (i+0.5)*step; sum[id] += 4.0/(1.0+x*x); } } for(i=0, pi=0.0;i<num_threads;i++) pi += sum[i] * step; }

使用并行域并行化的程序假设有 2 个线程参加计算 : 线程 0: 迭代 0 迭代 2 迭代 4 迭代 6 线程 1: 迭代 1 迭代 3 迭代 5 迭代 7

OpenMP 计算实例 使用共享任务结构并行化的程序 #include <omp.h> static long num_steps = 100000; double step; #define NUM_THREADS 2 void main () { int i; double x, pi, sum[num_threads]; step = 1.0/(double) num_steps; omp_set_num_threads(num_threads); #pragma omp parallel { double x; int id; id = omp_get_thread_num(); sum[id] = 0; #pragma omp for for (i=0;i< num_steps; i++){ x = (i+0.5)*step; sum[id] += 4.0/(1.0+x*x); } } for(i=0, pi=0.0;i<num_threads;i++) pi += sum[i] * step; }

使用共享任务结构并行化的程序 假设 2 个线程参加并行计算 : 线程 0: 迭代 0-49999 线程 1: 迭代 50000-99999

OpenMP 计算实例 使用 private 子句和 critical 部分并行化的程序 #include <omp.h> static long num_steps = 100000; double step; #define NUM_THREADS 2 void main () { int i; double x, sum, pi=0.0; step = 1.0/(double) num_steps; omp_set_num_threads(num_threads); #pragma omp parallel private (x, sum) { id = omp_get_thread_num(); for (i=id,sum=0.0;i< num_steps;i=i+num_threads){ x = (i+0.5)*step; sum += 4.0/(1.0+x*x); } #pragma omp critical pi += sum*step } }

OpenMP 计算实例 使用并行归约得出的并行程序 #include <omp.h> static long num_steps = 100000; double step; #define NUM_THREADS 2 void main () { int i; double x, pi, sum = 0.0; step = 1.0/(double) num_steps; omp_set_num_threads(num_threads); #pragma omp parallel for reduction(+:sum) private(x) for (i=0;i<num_steps; i++){ x = (i+0.5)*step; sum = sum + 4.0/(1.0+x*x); } pi = step * sum; }

国家高性能计算中心 ( 合肥 ) OpenMP 与其他标准的比较

OpenMP 的优点与缺点 优点 提供了一个可用的编程标准 ; 可移植性, 简单, 可扩展性 ; 灵活支持多线程, 具有负载平衡的潜在能力 ; 支持 Orphan Scope, 使程序更具有模块化 缺点 只适用于硬件共享存储型的机器 ; 动态可变的线程数使得支持起来困难 国家高性能计算中心 ( 合肥 )