炼数成金 门户 CUDA 查看内容

OpenMP指令之同步构造(Parallel)

2015-9-11 13:13| 发布者: 炼数成金_小数| 查看: 1425| 评论: 0|原作者: gengshenghong|来自: CSDN

摘要: Parallel指令作用(并行构造Parallel Construct)parallel指令,用于构造一个并行块,在并行块中的代码会被多个线程执行,parallel是最基本的OpenMP中构造并行的方法。在分析parallel指令的详细使用之前,先看下面的 ...

测试 编程 数学

Parallel指令。
(1)Parallel指令作用(并行构造Parallel Construct)
parallel指令,用于构造一个并行块,在并行块中的代码会被多个线程执行,parallel是最基本的OpenMP中构造并行的方法。
在分析parallel指令的详细使用之前,先看下面的例子,来了解一下OpenMP:
int main(int argc, char *argv[])  
{  
        printf("Masterthread started\n");  
#pragma omp parallel  
        {  
               printf("hello,OpenMP\n");  
        }// End of parallel region  
        printf("Masterthread finished\n");  
        return(0);  
}  
输出结果是什么?
需要注意的是,OpenMP使用了parallel之后,表示多个线程同时执行里面的代码,所以,才会有上面这样的结果,这和传统的win32的多线程方式理解上不太一样。当然,这个例子会让人想,parallel里面的代码,都会多个线程去执行,那有什么实际用处,为何需要用多个线程去执行一样的代码!那就需要结合其他的指令了,可以在并行里面使用其他指令做文章,让它按照预料的去执行。

关于Paralled的工作,其说明如下(我就不翻译了):
1. When a thread reaches aPARALLEL directive, it creates a team of threads and becomes themaster of the team. The master is amember of that team andhas thread number 0 within that team.
2. Starting from the beginning of this parallel region, the code isduplicated and all threads will execute that code.
3. There is an implied barrier at the end of a parallel section. Only the masterthread continues execution past this point.
4. If any thread terminates within a parallel region, all threads in the teamwill terminate, and the work done up until that point is undefined.
说明:在并行区域末尾有一个隐含的等待/同步(barrier本身也是一个OpenMP的指令,后面会讨论),在等待后只有主线程会继续执行。另外,关于第四点,“如果任何一个线程终止,那么其它所有线程都会终止”,目前我还不太理解这句话,我想,这里的终止和我理解的“不执行”是不一样的概念吧,不然,莫非,所有的线程必须花相同的时间执行完代码(待理解后更新)。

(2)Parallel指令详解
下面是paralled指令的完整格式:
#pragma omp parallel [clause...]  newline  
                     if (Scalar_expression)  
                     private (list)  
                     shared (list)  
                     default (shared | none)  
                     firstprivate (list)  
                     reduction (operator: list)  
                     copyin (list)  
                     num_threads(integer-expression)  
structured_block  
知道了parallel的作用,那么接下来就是分析这些子句的作用和parallel的一些问题了。

问题一:线程的数量?
从上面的代码中,很容易 看到,并行区域被执行了四次,也就是有四个线程在运行这段代码。那么,OpenMP是如何确定线程的数量的呢?
OpenMP的遇到parallel指令后创建的线程team的数量由如下过程决定:

1. if子句的结果
2. num_threads的设置
3. omp_set_num_threads()库函数的设置
4. OMP_NUM_THREADS环境变量的设置
5. 编译器默认实现(一般而言,默认实现的是总线程数等于处理器的核心数)
需要说明的是,上面的五点是依次优先级降低的,这也是很容易理解的。因为上面的程序我的测试环境是4核,所以才有了上面的结果,是由编译器的默认实现决定的。另外,这里的if子句,显然只能是true和false,那么if子句本身是不确定线程数量的,而是是否允许进行并行,如果为true,才会根据2,3,4来确定生成线程的数量,否则就不会生成多个线程(默认没有if的时候会进行并行)。

下面的代码是测试这几个决定条件的例子:
#include  
int main(int argc, char *argv[])  
{  
    printf("Masterthread started\n");  
  
#pragma omp parallel if(false)        // disable paralled  
    {  
        printf("hello,OpenMP, serial code\n");  
    }// End of parallel region  
  
  
#pragma omp parallel           // decided bydefault implementation  
    {  
        printf("hello,OpenMP, paralled code 1\n");  
    }// End of parallel region  
  
    omp_set_num_threads(2);  
#pragma omp parallel if(true) //decided by omp_set_num_threads  
    {  
        printf("hello,OpenMP, paralled code 2\n");  
    }// End of parallel region  
  
#pragma omp parallel if(true) num_threads(3) // decided by num_threads  
    {  
        printf("hello,OpenMP, paralled code 3\n");  
    }// End of parallel region  
  
    printf("Masterthread finished\n");  
  
    return(0);  
}  
结果如下:
问题二:线程的动态调整?DynamicThreads
还没理解这个函数!omp_get_dynamic/omp_set_dynamic/OMP_DYNAMIC

问题三:嵌套并行区域?NestedParallel Regions
还没理解!
(3)if子句和num_threads子句
上面已经看到了这两个子句的作用,if子句用于设置并行块是否并行执行。num_threads子句设置并行区域的线程数量。这两个子句比较简单,而且基本上应该只会在parallel关键字中出现(从OpenMP的spec查询只知道了parallel使用它们)。其它的子句,是一类和数据有关的子句,也是OpenMP编程中很重要的一部分,后面会单独学习。

(4)OpenMP Tutorial的例子:
#include  
  
int main()  
{  
    int nthreads, tid;  
  
    /* Fork a team of threads with each thread having a private tid variable */  
#pragma omp parallel private(tid)  
    {  
        /* Obtain and print thread id */  
        tid = omp_get_thread_num();  
        printf("Hello World from thread = %d\n", tid);  
  
        /* Only master thread does this */  
        if (tid == 0)   
        {  
            nthreads = omp_get_num_threads();  
            printf("Number of threads = %d\n", nthreads);  
        }  
    }  /* All threads join master thread and terminate */  
}  
这里用到了两个函数omp_get_thread_num()和omp_get_num_threads(),看起来很像的两个函数。omp_get_thread_num是获取当前线程的线程id(从结果也可以看到主线程的线程id是0)。omp_get_num_threads是获取线程数目。

总结:
1. parallel指令用于定义一个并行区域。
2. parallel并行区域是否并行由if子句决定。
3. parallel并行区域内生成的线程数量依次决定于:num_threads子句、omp_set_num_threads()函数、OMP_NUM_THREADS环境变量、编译器实现(一般为核心数)。只有前一个没有指定的时候,才使用后面的来决定,所以默认不进行任何设置,就是根据编译器实现来决定。
4. if和num_threads是两个子句,目前的结论是只用于parallel中.

待解决问题:
动态调整线程和线程嵌套的理解?在后面的更深入学习后在关于OpenMP函数学习的部分进行分析。

鲜花

握手

雷人

路过

鸡蛋

最新评论

热门频道

  • 大数据
  • 商业智能
  • 量化投资
  • 科学探索
  • 创业

即将开课

热门文章

     

    GMT+8, 2020-1-21 18:50 , Processed in 0.159394 second(s), 23 queries .