ICC和GCC编译器编译Openmp程序的运行区别

1、背景介绍

  • 硬件和隔核设置:

    Intel E5 V4 14核。
    配置 isolcpus=2,3,4,5,6,7,8,9,10,11,12,13,隔离了 12 个核心,仅保留核心 0 和核心 1 作为普通调度核心。

  • 操作系统

湖南麒麟3.3-3B

  • OpenMP并行配置:

    使用核心 4 到核心 13(10 个核心)运行 OpenMP 并行线程。

  • 调度策略:

    主进程使用 FIFO 调度策略。

  • 编译器和运行时:

    ICC 2015.1 编译的程序能够动态切换。


    GCC 4.8.5编译的程序并行度切换时存在问题

2、现象描述

针对不同的编译器,采用同一份测试程序,来验证并行计算情况,源码如下

/*============================================================================Name        : pthread_test.cAuthor      : Version     :Copyright   : Your copyright noticeDescription : Hello World in C, Ansi-style============================================================================*/#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
#include <error.h>
#include <malloc.h>
#include <netdb.h>
#include <netinet/in.h>
#include <assert.h>
#include <fcntl.h>
#include <getopt.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <unistd.h>#include <sys/stat.h>
#include <sys/types.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <arpa/inet.h>#include <sched.h>
#include <omp.h>#define SIZE 1024
double a[2048][2048]={0};
double b[2048][2048]={0};
double result[2048][2048]={0};int hello1()
{int iLoop =0;int i = 0;int j=0;int k=0;#pragma omp parallel num_threads(10){int thread_id=omp_get_thread_num();int cpu_id=4+ thread_id;cpu_set_t cpuset;CPU_ZERO(&cpuset);CPU_SET(cpu_id,&cpuset);printf("###########CPU CORE %d\n",cpu_id);if( 0 != pthread_setaffinity_np(pthread_self(),sizeof(cpu_set_t),&cpuset)){printf("pthread:set affinity failed\n");exit(EXIT_FAILURE);}}#pragma omp parallel for num_threads(10)for(i=0;i<SIZE;i++){for(j=0;j<SIZE;j++){double sum=0.0;for(k=0;k<SIZE;k++){sum+=a[i][k]*b[k][j];}result[i][j]=sum;}}#pragma omp parallel for num_threads(3)for(i=0;i<SIZE;i++){for(j=0;j<SIZE;j++){double sum=0.0;for(k=0;k<SIZE;k++){sum+=a[i][k]*b[k][j];}result[i][j]=sum;}}#pragma omp parallel for num_threads(10)for(i=0;i<SIZE;i++){for(j=0;j<SIZE;j++){double sum=0.0;for(k=0;k<SIZE;k++){sum+=a[i][k]*b[k][j];}result[i][j]=sum;}}return 0;
}int main()
{int ret = 0;int i = 0,j=0;cpu_set_t cpu_info;pthread_t xdma_t1[5];pthread_attr_t attr1[5];for(i=0;i<SIZE;i++){for(j=0;j<SIZE;j++){a[i][j]=sin(i+j);b[i][j]=cos(i-j);result[i][j]=0.0;}}struct sched_param param;param.sched_priority = 10;if(sched_setscheduler(getpid(), SCHED_RR, &param) == -1){printf("sched_setscheduler() failed!\n");return -1;}if(0 != pthread_create(&xdma_t1,NULL,(void*)hello1,NULL) ){printf("FILE:%s LINE:%d FUNC: CmpDsPCtrl Error!\n",__FILE__,__LINE__);return -1;}else{printf("%s %d Cmp: CmpDsPCtrl Started!\n",__FILE__,__LINE__);}while(1){sleep(1);}return;
}

上述代码中创建了10个核来并行计算,并行计算内容为矩阵乘法,并行度也设计为可动态切换的,即一开始是10线程并行,后面变成3线程并行,最后恢复10线程并行。

ICC编译器运行效果如下:

可以看到ICC编译器编译后的程序能够实现并行度调整,而且在并行度从10变成3的时候线程并没有减少。

GCC编译器运行效果如下:

可以看到,GCC编译器编译后的程序并行度从10变成3时线程自动消失了,后续并行度再提升到10时,增加的线程全部被放到了第一个核上,导致该核心被任务占满,并没有实现10核多线程并行。

3、问题排查

首先,在隔核的情况下,采用FIFO调度策略能将openmp线程调度到隔离核上,这一点与普通线程不一样,普通线程需要配置OMP_PLACE=cores环境变量才行,这一点在chatgpt上面有说明

为什么 FIFO 线程可以在隔离核心上运行?

  1. FIFO 调度策略与普通调度策略的不同
    • FIFO(先进先出)是实时调度策略之一。使用 FIFO 调度策略的线程通常拥有较高的调度优先级,并且会在系统中被优先调度。
    • 默认情况下,普通的进程调度会根据 isolcpus 设置避免在隔离核心上运行非实时线程。但实时线程(例如使用 FIFO 或其他实时调度策略的线程)通常会被允许在这些隔离的核心上运行,前提是该核心并未完全被其他重要进程或中断占用。
  2. 隔离核心与实时线程
    • 即使核心被 isolcpus 隔离,这些核心仍然可以为实时线程提供计算资源。系统不会主动地将实时线程调度到非隔离核心。
    • 由于 FIFO 线程具有较高的优先级,并且实时线程不会被常规调度器干扰,因此它们能够在隔离核心上运行。
  3. OpenMP 与实时线程的交互
    • OpenMP 是一种共享内存并行编程模型,它依赖于底层的线程库(如 pthreads)来管理并行线程的创建和调度。默认情况下,OpenMP 会由普通线程管理,并且其线程调度依赖于操作系统的标准调度器。
    • 当您通过 FIFO 调度策略创建线程时,这些线程由于高优先级,可能会影响 OpenMP 线程的调度,使其能够在隔离核心上执行。具体而言,当 OpenMP 线程创建时,它们的调度被实时线程干扰或优先级提升,可能会导致 OpenMP 线程成功在隔离核心上运行。

为什么 OpenMP 能在 FIFO 线程的帮助下运行?

在隔离核心上运行 OpenMP 并行任务的过程,可能是因为您通过 FIFO 线程干预了线程的调度,导致 OpenMP 线程能够在隔离核心上运行。具体来说:

  • 实时线程的干预:FIFO 线程在高优先级下运行时,可能会“抢占”调度资源,迫使 OpenMP 线程也在隔离核心上执行。这种方式与 OpenMP 默认的调度行为不同,通常情况下,OpenMP 线程只能运行在非隔离核心上。
  • 线程的绑定机制:FIFO 线程被创建时,系统可能会自动将其绑定到隔离的核心上,并确保它们有足够的计算资源。OpenMP 线程也可能继承了这一绑定,或者由于 FIFO 线程的干预,成功地在隔离核心上运行。

如何通过 FIFO 线程确保 OpenMP 并行运行在隔离核心上?

  1. 使用 FIFO 线程创建 OpenMP 线程: 如果你想要明确地确保 OpenMP 线程在隔离核心上运行,可以在 FIFO 线程中创建 OpenMP 线程并进行亲和性设置。例如,可以通过 pthread_setaffinity_np 设置 FIFO 线程绑定到隔离核心,并确保 OpenMP 线程继承该绑定。

其次,openmp库是编译器自带的,ICC使用的和GCC的不一样

  • ICC 2015.1:使用 Intel 提供的 OpenMP 运行时库(libiomp5)。
    • 优点:Intel 的运行时库经过高度优化,在 Intel 硬件上有更好的性能(如线程绑定和负载平衡)。
    • 缺点:在非 Intel 硬件上可能没有显著优势。
  • GCC 4.8.5:使用 GNU 提供的 OpenMP 运行时库(libgomp)。
    • 优点:更通用的实现,在各种硬件上兼容性较好。
    • 缺点:在性能优化上通常不如 Intel 的实现。

最后,ICC和GCC对Openmp线程池的管理方式不一样,如下:

这个问题的根本原因是 ICC 和 GCC 对于 OpenMP 线程池的管理机制不同。具体来说:


1. OpenMP 线程池管理的差异

  • ICC

    • ICC 的 OpenMP 运行时库 (libiomp5) 会维持一个全局的线程池,线程池中的线程在程序运行期间不会轻易销毁。
    • 当并行区域(#pragma omp parallel)的线程数量减少时(例如从 10 减少到 3),多余的线程会被放回线程池,但不会被销毁。这些线程会保持空闲状态,以便后续并行区域使用。
    • 优点:减少线程的创建和销毁开销,适合频繁进入和退出并行区域的场景。
    • 缺点:多余线程仍然会占用资源(如栈空间、内存)。
  • GCC

    • GCC 的 OpenMP 运行时库 (libgomp) 在处理线程时更加灵活。当并行区域的线程数减少时,多余的线程会直接被销毁。
    • 优点:减少资源占用,尤其在线程数频繁变化的情况下。
    • 缺点:频繁销毁和重新创建线程可能增加开销,尤其是在短时间内多次进入并行区域时。

2. 线程绑定和调度机制的不同

  • ICC

    • 在代码中使用了 pthread_setaffinity_np 明确绑定线程到特定的 CPU 核心。这种绑定策略可能导致线程即使处于空闲状态,也不会从系统中移除,因为 ICC 的运行时库需要维护这些绑定关系。
    • ICC 的运行时库会优先尝试保持线程的绑定,以优化线程与 CPU 缓存的亲和性。
  • GCC

    • GCC 通常不主动维护线程的绑定关系,多余的线程可以被更容易地销毁。
    • 如果未明确设置线程亲和性,多余的线程可能被直接释放,回收系统资源。

3. OpenMP 环境变量的影响

ICC 和 GCC 的运行时库对以下环境变量的处理不同:

  • OMP_THREAD_LIMIT:限制 OpenMP 的最大线程数。ICC 更倾向于尊重这个限制,即使减少线程,多余线程也会保持空闲状态。
  • OMP_WAIT_POLICY
    • 在 ICC 中,如果设置为 PASSIVE,线程可能进入休眠状态,但不会被销毁。
    • 在 GCC 中,即使设置为 PASSIVE,线程也可能被销毁。
  • KMP_AFFINITY(ICC 特有):控制线程的绑定行为。即使线程数减少,ICC 运行时库仍然可能保留线程以确保绑定关系。

4. 线程生命周期的实现细节

  • ICC
    • 线程池的实现会复用已经创建的线程,不会轻易销毁。
    • 如果线程绑定到特定 CPU 核心,这种绑定关系会保持,即使线程处于空闲状态。
  • GCC
    • 在线程数减少时,多余的线程会被回收,释放资源。
    • 线程销毁后,绑定关系会自动解除。

总结

  • ICC 编译器在 OpenMP 的实现中,更加注重性能优化和线程的重用。即使减少线程,多余线程也会保持空闲状态,以减少后续并行区域的创建开销。
  • GCC 编译器的实现更注重资源管理,减少不必要的线程占用,但可能在频繁并行区域切换时增加开销。

如果希望 ICC 的行为与 GCC 更接近,可以考虑调整以下设置:

  1. 使用环境变量 KMP_BLOCKTIME=0,使空闲线程立即进入休眠状态。
  2. 调整 OMP_WAIT_POLICY=PASSIVE,减少线程的占用资源。
  3. 避免设置过于严格的线程绑定策略,允许更多的灵活性。

总结:针对INTEL 处理器,还是用ICC来编译Openmp并行计算的程序效果更好,能最大限度的使用CPU资源,实现高效并行计算。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/3377.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

改进果蝇优化算法之一:自适应缩小步长的果蝇优化算法(ASFOA)

自适应缩小步长的果蝇优化算法(ASFOA)是对传统果蝇优化算法的一种重要改进,旨在克服其后期种群多样性不足、容易过早收敛和陷入局部最优等问题。有关果蝇优化算法的详情可以看我的文章:路径规划之启发式算法之二十七:果蝇优化算法(Fruit Fly Optimization Algorithm,FOA…

ubuntu22.04安装注意点

换源方式 22.04默认使用/etc/apt/sources.list而非/etc/apt/sources.list.d # 默认注释了源码镜像以提高 apt update 速度&#xff0c;如有需要可自行取消注释 deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ noble main restricted universe multiverse # deb-src https…

C#表达式和运算符

本文我们将学习C#的两个重要知识点&#xff1a;表达式和运算符。本章内容会理论性稍微强些&#xff0c;我们会尽量多举例进行说明。建议大家边阅读边思考&#xff0c;如果还能边实践就更好了。 1. 表达式 说到表达式&#xff0c;大家可能感觉有些陌生&#xff0c;我们先来举个…

LARGE LANGUAGE MODELS ARE HUMAN-LEVEL PROMPT ENGINEERS

题目 大型语言模型是人类级别的提示工程师 论文地址&#xff1a;https://arxiv.org/abs/2211.01910 项目地址&#xff1a;https://github.com/keirp/automatic_prompt_engineer 摘要 通过对自然语言指令进行调节&#xff0c;大语言模型 (LLM) 显示了作为通用计算机的令人印象深…

基础入门-反弹Shell渗透命令Reverse反向Bind正向利用语言文件下载多姿势

知识点&#xff1a; 1、反弹Shell-项目&命令&语言等 2、系统渗透命令-网络&文件&操作等 一、演示案例-反弹Shell-自带命令&语言代码&三方项目 1、反弹Shell的前提条件 已知存在的漏洞利用或执行命令的地方 2、为什么要反弹Shell? 往往由于很多因…

AI在SEO中的关键词优化策略探讨

内容概要 在当今数字化时代&#xff0c;人工智能&#xff08;AI&#xff09;正逐渐重塑搜索引擎优化&#xff08;SEO&#xff09;行业。AI技术的快速发展使得SEO策略发生了翻天覆地的变化&#xff0c;特别是在关键词优化方面。关键词优化的基本概念是通过选择与用户搜索意图密…

DeepSeek-v3在训练和推理方面的优化

1. 基础架构&#xff1a;MLA&#xff0c;大幅减少了KV cache大小。&#xff08;计算量能不能减少&#xff1f;&#xff09; 2. 基础架构&#xff1a;MoE&#xff0c;同等参数量&#xff08;模型的”能力“&#xff09;下&#xff0c;训练、推理的计算量大幅减少。 3. MoE的load…

【从0带做】基于Springboot3+Vue3的心理健康预约平台

大家好&#xff0c;我是武哥&#xff0c;最近给大家手撸了一个基于SpringBoot3Vue3的心理健康预约平台&#xff0c;可用于毕业设计、课程设计、练手学习&#xff0c;系统全部原创&#xff0c;如有遇到网上抄袭站长的&#xff0c;欢迎联系博主~ 项目演示视频和教程视频 https:…

Mybatis 进阶 / Mybatis—Puls (详细)

目录 一.动态SQL 1.1标签 1.2 标签 1.3标签 1.4标签 1.5标签 1.6标签 mybatis总结&#xff1a; 二.Mybatis-Puls 2.1准备工作 2.2CRUD单元测试 2.2.1创建UserInfo实体类 2.2.2编写Mapper接⼝类 2.2.3 测试类 2.3 常见注解 2.3.1TableName 2.3.2TableField 2.4打印日…

2025.1.16——三、supersqli 绕过|堆叠注入|handler查询法|预编译绕过法|修改原查询法

题目来源&#xff1a;攻防世界supersqli 目录 一、打开靶机&#xff0c;整理已知信息 二、sqlmap解题 step 1&#xff1a;爆数据库 step 2&#xff1a;爆表 二、手工注入解题 step 1&#xff1a;判断注入类型 step 2&#xff1a;判断字段数 step 3&#xff1a;查询数据…

【数据库初阶】MySQL中表的约束(上)

??博主首页&#xff1a; ??专栏首页&#xff1a; 数据库初阶 ??其它专栏&#xff1a; C初阶 | C进阶 | 初阶数据结构 亲爱的小伙伴们&#xff0c;大家好&#xff01;在这篇文章中&#xff0c;我们将深入浅出地为大家讲解 MySQL中表的约束 帮助您轻松入门&#xff0c;快…

HTML基础与实践

目录 HTML 结构 认识 HTML 标签 HTML 文件基本结构 标签层次结构 快速生成代码框架 HTML 常见标签 注释标签 标题标签: h1-h6 段落标签: p 换行标签: br 格式化标签 图片标签: img 超链接标签: a ​编辑链接的几种形式: 表格标签 基本使用 合并单元格 …

初识go语言之指针用法

一、环境准备 安装go语言编译环境&#xff0c;官网地址&#xff1a;https://go.dev/dl/ 或者 https://golang.google.cn/dl/ 点击下载按提示安装即可 vscode 安装go语言扩展 测试 package mainimport "fmt"func main() {fmt.Println("Hello, World!") …

mac 安装 node

brew versions node // 安装 node brew versions node14 // 安装指定版本 卸载node: sudo npm uninstall npm -g sudo rm -rf /usr/local/lib/node /usr/local/lib/node_modules /var/db/receipts/org.nodejs.* sudo rm -rf /usr/local/include/node /Users/$USER/.npm su…

2025.1.16——六、BabySQL 双写绕过|联合注入

题目来源&#xff1a;buuctf [极客大挑战 2019]BabySQL 1 目录 一、打开靶机&#xff0c;分析已知信息 二、手工注入解题 step 1&#xff1a;万能密码 step 2&#xff1a;正常注入&#xff0c;判断字段数 step 3&#xff1a;绕过 step 4&#xff1a;查数据库 step 5&am…

第4章 Kafka核心API——Kafka客户端操作

Kafka客户端操作 一. 客户端操作1. AdminClient API 一. 客户端操作 1. AdminClient API

浅谈云计算21 | Docker容器技术

Docker容器技术 一、 容器技术特性1.1 轻量级特性1.2 隔离性特性 二、容器镜像2.1 容器镜像概述2.1.1 定义与构成2.1.2 分层结构 2.2 联合文件系统2.3 容器镜像的构建与管理2.3.1 容器镜像的构建2.3.2 **构建镜像流程**2.3.3 **应用场景**2.3.4 镜像仓库的应用 2.4 容器镜像的优…

Android CustomTextField

在 Compose 中开发用户界面时&#xff0c;需要处理输入框和键盘的交互&#xff0c;例如在键盘弹出时调整布局位置&#xff0c;避免遮挡重要内容。本篇博客将通过一个完整的示例展示如何实现这一功能。 功能概述 本例实现了一个简单的输入框。当输入框获得焦点或输入文字时&…

[0242].第4-3章:SpringBoot2核心技术笔记

Java学习大纲 1、笔记 第1步&#xff1a;框架初识 [0242-01].第01节&#xff1a;SpringBoot初识 第2步&#xff1a;入门项目 [0242-02].第02节&#xff1a;SpringBoot入门项目[0242-03].第03节&#xff1a;SpringBoot开发技巧 第3步&#xff1a;开发应用 配置文件&#xff1a…

2025.1.15——四、布尔注入

题目来源&#xff1a;ctfhub技能树 目录 一、基本操作&#xff1a;整理已知信息&#xff0c;得到本题为布尔注入 方法一&#xff1a;手工盲注&#xff08;不推荐&#xff09; step 1&#xff1a;判断具体形式 step 2&#xff1a;查询字段数 step 3&#xff1a;通过回显判…