chap3OpenMP多线程编程讲义.ppt
文本预览下载声明
* threadprivate(list)是全程序有效的,是永久量,即多个并行域有效,当thread num为0时,因为和主线程同线程,所以对list里面变量的修改会影响到全局变量。 private(list)只对当前并行域有效,是临时量,对list里面变量的修改不会影响到全局变量。 for循环前的变量k和循环区域内的变量k其实是两个不同的变量。用private子句声明的私有变量的初始值在并行区域的入口处是未定义的,它并不会继承同名共享变量的值。出现在reduction子句中的参数不能出现在private子句中。 多个并行域之间,或者并行域内部的函数调用之间如果需要在线程内部共享全局变量,必须用threadprivate。如果不将全局变量声明为threadprivate而是声明为private,则在子函数调用时子函数内的全局变量传递不到子函数外面。 循环并行化开始的时候,私有变量具有主线程中的同名变量的值 循环并行化后将私有变量返回给主线程中的同名变量 从打印结果可以看出,并行区域内的私有变量k继承了外面共享变量k的值100作为初始值,并且在退出并行区域后,共享变量k的值保持为100未变。 循环并行化开始的时候,私有变量具有主线程中的同名变量的值 循环并行化后将私有变量返回给主线程中的同名变量 * OpenMP在使用规约操作时,只需在变量前指明规约操作的类型以及规约的变量 将上下文切换、调度开销、同步开销降到最低。 对于schedule(static,size)的含义,OpenMP会给每个线程分配size次迭代计算。这个分配是静态的,“静态”体现在这个分配过程跟实际的运行是无关的,可以从逻辑上推断出哪几次迭代会在哪几个线程上运行。具体而言,对于一个N次迭代,使用M个线程,那么,[0,size-1]的size次的迭代是在第一个线程上运行,[size, size + size -1]是在第二个线程上运行,依次类推。那么,如果M太大,size也很大,就可能出现很多个迭代在一个线程上运行,而某些线程不执行任何迭代。需要说明的是,这个分配过程就是这样确定的,不会因为运行的情况改变,比如,我们知道,进入OpenMP后,假设有M个线程,这M个线程开始执行的时间不一定是一样的,这是由OpenMP去调度的,并不会因为某一个线程先被启动,而去改变for的迭代的分配,这就是静态的含义。 barrier指导语句用来同步一个线程组中所有的线程 先到达的线程在此阻塞,等待其他线程 某些处理需要规定执行的顺序 典型的情况:在一次循环的过程中 一大部分的工作是可以并行执行的,而其余的工作需要等到前面的工作全部完成之后才能够执行 omp_lock_t lock; int counter=0; void inc_counter() { printf(“thread id=%d\n”,omp_get_thread_num()); for (int i=0; i1000; i++) { omp_set_lock(lock); counter++; omp_unset_lock(lock); } } 例 void dec_counter() { printf(“thread id=%d\n”,omp_get_thread_num()); for (int i=0; i1000; i++) { omp_set_lock(lock); counter--; omp_unset_lock(lock); } } int main() { omp_init_lock(lock); #pragma omp parallel sections { #pragma omp section inc_counter(); #pragma omp section dec_counter(); } omp_destroy_lock(lock); printf(“counter=%d\n”, counter); } 例 隐含的同步屏障 每一个并行区域都有一个隐含的同步屏障。 隐含的同步屏障: #pragma omp for #pragma omp single #pragma omp sections nowait子句:可以避免不必要的同步屏障。 6.4 同步屏障 #pragma omp parallel { #pragma omp for nowait for( int i=1; isize; ++i) x[i]=(y[i]+z[i])/2; printf(“finished\n”); } 6.4 同步屏障 6.4 同步屏障(barrier)
显示全部