[转]OpenMP中几个容易混淆的函数(线程数量/线程ID/线程最大数)以及并行区域线程数量的确定

说明:这部分内容比较基础,主要是分析几个容易混淆的OpenMP函数,加以理解。

(1)并行区域数量的确定:

在这里,先回顾一下OpenMP的parallel并行区域线程数量的确定,对于一个并行区域,有一个team的线程去执行,那么该分配多少个线程去执行呢?

OpenMP的遇到parallel指令后创建的线程team的数量由如下过程决定:

  1. if子句的结果

  2. num_threads的设置

  3. omp_set_num_threads()库函数的设置

  4. OMP_NUM_THREADS环境变量的设置

  5. 编译器默认实现(一般而言,默认实现的是总线程数等于处理器的核心数)

2、3、4优先级依次降低的,也就是前面的设置可以覆盖后面的设置,当然也是相对而言,num_threads子句只会影响当前的并行区域,而omp_set_num_threads对OMP_NUM_THREADS环境变量的覆盖是在整个程序运行期间全局的。

(2)几个容易混淆的OpenMP函数

1. omp_get_thread_num

获取线程的num,即ID。这里的ID是OpenMP的team内的ID,在OpenMP中,一个team内的线程的ID是俺顺序排列的,0、1、2…

说明:此函数在并行区域外或者并行区域内都可以调用。在并行区域外,获取的是master线程的ID,即为0。在并行区域内,每次执行到此函数,获取的是当前执行线程的ID。

此函数比较容易理解,主要是不要和下面的omp_get_num_threads记混淆了。

2. omp_get_num_threads/omp_set_num_threads

设置/获取线程数量,此set函数是上面确定遇到parallel指令后创建team的线程的决定方式之一,用于覆盖OMP_NUM_THREADS环境变量的设置。

说明:尽管从函数名上看,它们是一对set/get函数,但是要区分它们的含义,set之后马上get,其值不一定等于set的结果,而且大部分情况都是不相等的!

首先来理解omp_set_num_threads():

作用上来说,我们知道它是用于覆盖环境变量OMP_NUM_THREDS的设置的,使用上来说,要注意的是,omp_set_num_threads只能用于并行区域之外,如果用于并行区域之内,在Debug下运行时会输出”User Error 1001: omp_set_num_threads should only be called in serial regions”到控制台,如果是Release模式不会输出,理论上应该是被忽略了。总之,在串行代码区调用omp_set_num_threads来设置线程数量。

然后分析omp_get_num_threads():

用于获取当前线程组(team)的线程数量,如果不在并行区调用,返回1.

这句话就清楚了描述了get的作用了,获取的是当前线程组的线程数量,所以一般会在并行区域调用,其返回的是实际的parallel区域内由上面几大因素决定之后的实际的运行的线程数量,并不是set的值,所以也很容易理解,在串行区调用它会返回1(所以一般也不会在串行区去调用)。

总结:omp_set_num_threads在串行区域调用才会有效,omp_get_num_threads获取当前线程组的线程数量,一般在并行区域调用,在串行区域调用返回为1。两个函数没有本质上的数量关系!

3. omp_get_max_threads:

从函数名看,貌似是”获取最大的线程数量”,是的,那么这个”最大的线程数量”的具体含义呢?下面是OpenMP文档上的一段话:

The omp_get_max_threads routine returns an upper bound on the number of threads that could be used to form a new team if a parallel region without a num_threads clause were encountered after execution returns from this routine。

很清楚的说明了,这个”最大数量”是指在不使用num_threads的情况下,OpenMP形成一个新的team能创建的最大线程数量。从这里要理解到:这个最大数量,是能确定的,与其在并行区域调用,还是在串行区域调用是无关的,因为它是返回OpenMP当前环境下去创建一个”新的”team能创建的可能的最大数量。简单的理解,其实,这个值就是由以下三者确定:omp_set_num_threads、OMP_NUM_THREADS、编译器默认实现。

注意:omp_get_max_threads可以在串行或并行区域内调用,而且其结果是一样的(在其间不调用omp_set_num_threads的情况下),如果有效调用(串行区调用)了omp_set_num_threads,会改变接下来调用omp_get_max_threads的值。另外,omp_get_max_threads的返回值可能会小于omp_set_num_threads。

4. 实例:

下面的例子是使用上面几个函数的例子,根据结果可以分析出上面提到的一些内容:

cpp;gutter:true;</p> <h1>include</h1> <p>int main(int argc, _TCHAR* argv[]) { printf("ID: %d, Max threads: %d, Num threads: %d \n",omp_get_thread_num(), omp_get_max_threads(), omp_get_num_threads()); omp_set_num_threads(5); printf("ID: %d, Max threads: %d, Num threads: %d \n",omp_get_thread_num(), omp_get_max_threads(), omp_get_num_threads());</p> <h1>pragma omp parallel num_threads(5)</h1> <pre><code>{ // omp_set_num_threads(6); // Do not call it in parallel region printf("ID: %d, Max threads: %d, Num threads: %d \n",omp_get_thread_num(), omp_get_max_threads(), omp_get_num_threads()); } printf("ID: %d, Max threads: %d, Num threads: %d \n",omp_get_thread_num(), omp_get_max_threads(), omp_get_num_threads()); omp_set_num_threads(6); printf("ID: %d, Max threads: %d, Num threads: %d \n",omp_get_thread_num(), omp_get_max_threads(), omp_get_num_threads()); return 0; </code></pre> <p>}

[转]OpenMP中几个容易混淆的函数(线程数量/线程ID/线程最大数)以及并行区域线程数量的确定

Original: https://www.cnblogs.com/wlzy/p/10890224.html
Author: ZYVV
Title: [转]OpenMP中几个容易混淆的函数(线程数量/线程ID/线程最大数)以及并行区域线程数量的确定

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/539656/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 【翻译】Thymeleaf – Spring Security集成模块

    来源:thymeleaf/thymeleaf-extras-springsecurity自述文件 这是一个Thymeleaf附加模块,不是Thymeleaf核心的一部分(因此它有自…

    Java 2023年6月6日
    064
  • MySQL中读页缓冲区buffer pool

    Buffer pool 我们都知道我们读取页面是需要将其从磁盘中读到内存中,然后等待CPU对数据进行处理。我们直到从磁盘中读取数据到内存的过程是十分慢的,所以我们读取的页面需要将其…

    Java 2023年6月16日
    081
  • @Import 源码解析

    转发请注明出处: @Import通过快速导入的方式实现把实例加入spring的IOC容器中;一般@EnableXXX注解是通过@Import实现具体的功能(@EnableXXX注解…

    Java 2023年6月8日
    061
  • 云原生下基于K8S声明式GitOps持续部署工具ArgoCD实战-上

    @ 概述 定义 工作原理 主要组件 核心概念 环境准备 概述 安装Kubekey 创建K8S 安装K9S OpenLB 安装ArgoCD 安装 ArgoCD CLI 从Git库中创…

    Java 2023年6月5日
    0110
  • 解决图片上传后,不刷新图片

    后端上传图片后是覆盖原来图片,上传图片后返回的图片访问路径,是和原来是一样的;浏览器有缓存,看到访问的新路径是和原来一样的,所以浏览器访问的是缓存中的图片;可以给返回的访问路径拼接…

    Java 2023年6月8日
    089
  • MVCC原理

    MVCC MVCC (Multi-Version Concurrency Control) ,即多版本并发控制,利用记录的版本链和ReadView,来控制并发事务访问相同记录时的行…

    Java 2023年6月6日
    081
  • nginx 替换

    nginx: [emerg] the “ssl” parameter requires ngx_http_ssl_module in /usr/local/…

    Java 2023年5月30日
    077
  • Mybaits plus 数据库映射java实体三种方式

    前言 数据库一般是用下划线进行设计字段,Java实体一般用驼峰法设计属性。这是不成文的规定。当数据库字段映射java实体会出现问题。下面分别是数据库字段和实体属性。 解决问题三种方…

    Java 2023年6月8日
    0100
  • Java泛型用法总结

    普通泛型 <span class="kwd"><span class="kwd">class<span cla…

    Java 2023年6月13日
    081
  • MQ(消息队列)的使用场景以及常见的MQ

    MQ(消息队列)的使用场景以及常见的MQ 消息中间件通也被称为消息队列服务器,是当今分布式应用架构中经常采用的技术,程序员之间一般叫作消息队列或者 MQ。 消息队列属于面向消息的中…

    Java 2023年5月29日
    068
  • Spring Boot 入门系列(二十二)使用Swagger2构建 RESTful API文档

    前面介绍了如何Spring Boot 快速打造Restful API 接口,也介绍了如何优雅的实现 Api 版本控制,不清楚的可以看我之前的文章:https://www.cnblo…

    Java 2023年5月30日
    0258
  • 基于MybatisPlus代码生成器(2.0新版本)

    一、模块简介 1、功能亮点 实时读取库表结构元数据信息,比如表名、字段名、字段类型、注释等,选中修改后的表,点击 &#x4E00;&#x952E;&#x75…

    Java 2023年6月6日
    092
  • Java基础

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Java 2023年6月5日
    078
  • Restful风格

    Restful 1.REST架构的主要原则 1.1 对网络上所有的资源都有一个资源标志符 1.2 对资源的操作不会改变标识符 1.3 同一资源有多种表现形式(xml、json)、 …

    Java 2023年6月14日
    0102
  • Java8⾼效遍历map_Java8中Map的遍历⽅式总结

    java;gutter:true; public class LambdaMap { private Map map = new HashMap<>(); @Befor…

    Java 2023年5月29日
    070
  • 【Redis】skiplist跳跃表

    有序集合Sorted Set zadd zadd用于向集合中添加元素并且可以设置分值,比如添加三门编程语言,分值分别为1、2、3: 127.0.0.1:6379> zadd …

    Java 2023年6月8日
    078
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球