并行计算-OPENMP(windows)

news2024/11/25 16:35:46

         并行计算(Parallel Computing)是指同时使用多种计算资源解决计算问题的过程,是提高计算机系统计算速度和处理能力的一种有效手段。它的基本思想是用多个处理器来协同求解同一问题,即将被求解的问题分解成若干个部分,各部分均由一个独立的处理机来并行计算。并行计算系统既可以是专门设计的、含有多个处理器的超级计算机,也可以是以某种方式互连的若干台的独立计算机构成的集群。通过并行计算集群完成数据的处理,再将处理的结果返回给用户。

        OpenMP是由OpenMP Architecture Review Board牵头提出的,用于共享内存并行系统的多处理器程序设计的一套指导性编译处理方案。OpenMP支持的编程语言包括C、C++和Fortran。OpenMp提供了对并行算法的高层的抽象描述,程序员通过在源代码中加入专用的pragma来指明自己的意图,由此编译器可以自动将程序进行并行化,并在必要之处加入同步互斥以及通信。当选择忽略这些pragma,或者编译器不支持OpenMp时,程序又可退化为通常的程序(一般为串行),代码仍然可以正常运作,只是不能利用多线程来加速程序执行。

        在VS中使用OPENMP需要打开Open MP支持开关,如下图VS2019中打开方式。

 Hello, omp! 如下代码会根据运行机器上的处理器开对应数量的线程进行运行。

#include <iostream>
#include <omp.h>
using namespace std;
#include <windows.h>
int main()
{
#pragma omp parallel
    {
        DWORD dwThread = GetCurrentThreadId();
        printf("ThreadID:%d  threadIndex:%d, Hello, omp!\r\n", \
            dwThread, omp_get_thread_num());
    }
    system("pause");
}

Open MP函数

函数名

函数 功能说明

omp_set_num_threads

设置即将出现的并行区域中的线程数,除非由 num_threads 子句重写。

omp_get_num_threads

返回并行区域中的线程数。

omp_get_max_threads

如果在代码中的该位置定义了没有 num_threads 的并行区域,则返回等于或大于可用线程数的整数。

omp_get_thread_num

返回在其线程组中执行的线程的线程编号。

omp_get_num_procs

返回调用函数时可用的处理器数。

omp_in_parallel

如果从并行区域内调用,则返回非零值。

omp_set_nested

启用或者禁用嵌套并行。

omp_get_nested

判断嵌套并行是否启用。

锁相关函数

函数名

函数功能说明

omp_init_lock

初始化锁

omp_destroy_lock

取消初始化锁

omp_set_lock

阻塞线程执行,直到锁可用

omp_unset_lock

释放锁

omp_test_lock

尝试设置锁但不阻塞线程执行

Open MP指令

函数名

函数功能说明

omp_init_lock

初始化锁

omp_destroy_lock

取消初始化锁

omp_set_lock

阻塞线程执行,直到锁可用

omp_unset_lock

释放锁

omp_test_lock

尝试设置锁但不阻塞线程执行

#include <iostream>
#include <omp.h>
using namespace std;
#include <windows.h>

void OMPTestAPI()
{
    int max_threads = omp_get_max_threads();
    int num_threads = omp_get_num_threads();
    int num_procs = omp_get_num_procs();


    printf("Max threads: %d\n", max_threads);
    printf("Num threads: %d\n", num_threads);
    printf("Num Procs:%d\n", num_procs);
    omp_set_num_threads(6);
    int nInparallel = omp_in_parallel();
    printf("Inparallel:%d\n", nInparallel);

#pragma omp parallel
    {
        nInparallel = omp_in_parallel();
        printf("Inparallel:%d\n", nInparallel);
        num_threads = omp_get_num_threads();
        int thread_id = omp_get_thread_num();
        printf("Thread ID: %d, maxthread num:%d\n", thread_id, max_threads);
    }
}

int nest_test() {
    int nNest = omp_get_nested();
    printf("Nest state:%d\n", nNest);
    omp_set_nested(1);  // 启用嵌套并行

#pragma omp parallel num_threads(2)
    {
        printf("Outer parallel region\n");

        nNest = omp_get_nested();
        printf("After SetNest Nest state:%d\n", nNest);
#pragma omp parallel num_threads(2)
        {
            printf("Inner parallel region\n");
        }
    }
}

void atomic_Cmd()
{
    int count = 0;
#pragma omp parallel num_threads(10)
    {
#pragma omp atomic
        count++;
    }
    printf_s("Number of threads: %d\n", count);
}

void for_Cmd()
{
    int count = 0;
    omp_set_num_threads(2);
    
    //并行for
#pragma omp parallel
#pragma omp  for
//#pragma omp parallel for
    for (int i = 0; i < 4; i++)
    {
        ++count;
        printf_s("Thread num:%d, count:%d\r\n", omp_get_thread_num(), count);
    }
    
    //普通 for
    count = 0;
    for (int i = 0; i < 4; i++)
    {
        ++count;
        printf_s("ThreadID:%d, count:%d\r\n", GetCurrentThreadId(), count);
    }
}

void master_Cmd()
{
    DWORD dwThreadID = GetCurrentThreadId();
    printf("main thread id is %d\r\n", dwThreadID);
#pragma omp parallel num_threads(3)
    {
        printf("Hello from thread %d\n", omp_get_thread_num());
#pragma omp master
        {
            printf("Hello from master thread %d, threadid:%d\n", omp_get_thread_num(), GetCurrentThreadId());
            // 只有主线程执行下面的代码
            // 执行一些仅需执行一次的工作
        }
    }
}

void barrier_Cmd()
{
#pragma omp parallel num_threads(4)
    {
        printf("Hello from thread %d\n", omp_get_thread_num());
        
        //等待
#pragma omp barrier
        printf("World from thread %d\n", omp_get_thread_num());
    }
}

void critical_Cmd()
{
    int shared_var = 0;

#pragma omp parallel num_threads(4)
    {
        int thread_num = omp_get_thread_num();
        printf("Thread %d is executing before the critical section\n", thread_num);

#pragma omp critical
        {
            // 进入临界区代码块
            printf("Thread %d is inside the critical section\n", thread_num);
            shared_var++;
            printf("Shared variable incremented by Thread %d: %d\n", thread_num, shared_var);
            // 退出临界区代码块
        }

        printf("Thread %d is executing after the critical section\n", thread_num);
    }
}

void flush_Cmd()
{
    int shared_var = 0;

#pragma omp parallel num_threads(20)
    {
#pragma omp critical
        {
            // 对共享变量进行修改
            shared_var++;
            printf("Thread %d: shared_var = %d\n", omp_get_thread_num(), shared_var);
        }

        // 执行 flush 操作以确保共享变量的修改对所有线程可见
//#pragma omp flush

// 访问共享变量
        printf("Thread %d: shared_var = %d\n", omp_get_thread_num(), shared_var);
    }

//    int shared_var = 0;
//
//#pragma omp parallel num_threads(2)
//    {
//        int thread_num = omp_get_thread_num();
//
//        if (thread_num == 0) {
//            // 线程0写入共享变量(写入操作1)
//            shared_var = 42;
#pragma omp flush(shared_var)
//            // 写入操作1完成后,强制刷新到主存,使其对其他线程可见
//        }
//
//#pragma omp barrier
//
//        if (thread_num == 1) {
//            // 线程1读取共享变量(读取操作1)
//            // 在读取之前,需要使用 flush 指令确保对 shared_var 的最新写入全部对线程1可见
//#//pragma omp flush(shared_var)
//
//            printf("Thread %d reads shared_var: %d\n", thread_num, shared_var);
//        }
//    }

}

void ordered_Cmd()
{
#pragma omp parallel num_threads(5)
    {
        int thread_num = omp_get_thread_num();
#pragma omp for ordered
        for (int i = 0; i < 4; i++) {
#pragma omp ordered
            {
                printf("Thread %d is executing iteration %d\n", thread_num, i);
            }
        }
    }
}

void section_Cmd()
{
#pragma omp parallel num_threads(4)
    {
#pragma omp sections
        {
#pragma omp section
            {
                printf("This is Section 1, executed by Thread %d\n", omp_get_thread_num());
            }

#pragma omp section
            {
                printf("This is Section 2, executed by Thread %d\n", omp_get_thread_num());
            }

#pragma omp section
            {
                printf("This is Section 3, executed by Thread %d\n", omp_get_thread_num());
            }
        }
    }


//#pragma omp parallel sections num_threads(4)
//    {
//        printf_s("Hello from thread %d\n", omp_get_thread_num());
//#pragma omp section
//        printf_s("Hello from thread %d\n", omp_get_thread_num());
//    }
}

void single_Cmd()
{
#pragma omp parallel num_threads(4)
    {
#pragma omp single
        {
            printf("This is executed by Thread %d\n", omp_get_thread_num());
        }
    }
}
int nx = 0; // 全局变量x
#pragma omp threadprivate(nx)

int g = 2;

#pragma omp threadprivate(g)  

void threadprivate_Cmd()
{
    /* Explicitly turn off dynamic threads */
    //omp_set_dynamic(0);
    DWORD dwID = GetCurrentThreadId();
    printf("start g:%d, ThreadID:%d\r\n", g, dwID);
    printf("Masterthread started\n\n");
    
#pragma omp parallel 
    {
        dwID = GetCurrentThreadId();
        g = omp_get_thread_num();
        printf("tid: %d, Theadid:%d\n", g, dwID);
    } // End of parallel region  
    printf("mid g:%d\r\n", g);
#pragma omp parallel  
    {
        int temp = g * g+1;
        printf("tid : %d, tid*tid: %d\n", g, temp);
    } // End of parallel region  

    printf("Masterthread finished\n");
    printf("end g:%d\r\n", g);
}


omp_lock_t simple_lock;

int Lock_test () {
    omp_init_lock(&simple_lock);

#pragma omp parallel num_threads(4)
    {
        int tid = omp_get_thread_num();

        while (!omp_test_lock(&simple_lock))
            printf_s("Thread %d - failed to acquire simple_lock\n",
                tid);

        printf_s("Thread %d - acquired simple_lock\n", tid);

        printf_s("Thread %d - released simple_lock\n", tid);
        omp_unset_lock(&simple_lock);
    }

    omp_destroy_lock(&simple_lock);
}

参考资料:

https://learn.microsoft.com/zh-cn/cpp/parallel/openmp/reference/openmp-environment-variables?view=msvc-170

https://blog.csdn.net/lovely_yoshino/article/details/127688670

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习(一)

目录 一、特征工程的作用 二、深度学习的应用 三、得分函数 四、损失函数 五、前向传播 六、反向传播 一、特征工程的作用 数据特征决定了模型的上限预处理和特征提取是最核心的算法与参数选择决定了如何逼近这个上限 二、深度学习的应用 无人驾驶人脸识别分辨率重构 深…

国产龙芯2k1000开发板运行SylixOS嵌入式实时系统--迅为电子

龙芯生态体系越来越完善&#xff0c;继RK3568开发板成功搭载SylixOS国产实时操作系统后&#xff0c;迅为的国产龙芯2K1000开发平台也可以流畅运行SylixOS国产实时操作系统了。 SylixOS 采用抢占式、多任务、硬实时的方式来设计整个操作系统。已广泛适用于电力、工业自动化、轨道…

为什么要配置环境变量(深析)

为什么要配置环境变量&#xff08;深析&#xff09; 前言&#xff1a;大家学习java首先听到的就是jdk&#xff0c;配置环境变量&#xff0c;当时我听到这个也一脸雾水&#xff0c;这是个什么东西&#xff0c;当时就稀里糊涂跟着老师一步步下载安装&#xff0c;弄好了也不知道是…

安全基础 --- html基础标签 + DNS工作原理

html基础标签 &#xff08;1&#xff09;id id属性是元素在网页内的唯一标识符。 比如&#xff0c;网页可能包含多个<p>标签&#xff0c;id属性可以指定每个<p>标签的唯一标识符。 <p id"p1"></p> <p id"p2"></p>…

UE4/5C++多线程插件制作(十四、MTPAbandonable)

MTPAbandonable 在头文件中创建新的文件夹,MTPAbandonable,里面是MTPAbandonable.h,cpp也一样如此: h实现 构造函数接受一个FSimpleDelegate类型的参数InThreadDelegate,用于指定任务在后台线程中执行时要执行的操作。 DoWork()函数定义了任务的具体执行逻辑,需要根据…

NLog同时输出到文件、控制台、RichTextBox

效果 项目 VS2010.net4.0NLogNLog.Windows.Forms 代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using NLog;namespac…

【Docker 网络】

文章目录 一、Docker 网络1、Docker 网络实现原理2、查看容器的输出和日志信息3、Docker 的网络模式4、网络模式详解1&#xff0e;host模式2&#xff0e;container模式3&#xff0e;none模式4&#xff0e;bridge模式5&#xff0e;自定义网络1、创建自定义网络 二、资源控制1&am…

初识TDMQ

目录 一&#xff1a;需求背景二&#xff1a;相关文档三&#xff1a;验证TDMQ广播消息 一&#xff1a;需求背景 目前公司需要将决策引擎处理的结果&#xff0c; 一部分数据交给下游分析/入黑/通知等功能。因此就需要决策引擎生产结果让多方下游去消费。 而我需要实现下游的一部…

数据类型的分类

数据类型的分类 java中的 变量 按照数据类型来分类&#xff1a; 基本数据类型&#xff08;8种&#xff09;&#xff08;primitive type&#xff09;&#xff1a; 整型&#xff1a;byte、short、int、long、浮点型&#xff1a;float、double字符型&#xff1a;char布尔型&#x…

/var/empty/sshd must be owned by root and not group or world-writable

/var/empty/sshd must be owned by root and not group or world-writable 这个是权限的问题 可采取以下两步解决 chown -R root.root /var/empty/sshd chmod 744 /var/empty/sshd service sshd restart

80v转5v芯片-电动车/汽车降压芯片方案

Q: 什么是80v转5v芯片&#xff1f;什么它在电动车和汽车中有应用需求&#xff1f; A: 80v转5v芯片是一种电源转换芯片&#xff0c;可以将输入电压范围为9v至100v的直流电源转换为输出电压为5v&#xff0c;并且可以进行可调。这种芯片在电动车和汽车领域有广泛的应用需求。电动…

Python+pytest+requests 自动化测试框架

目录 前言&#xff1a; 环境准备 简单 Demo yml 文件读取功能 数据层 业务层 测试用例层 前言&#xff1a; Python 是一种广泛使用的编程语言&#xff0c;它可以用于开发各种软件和应用程序。pytest 是一个广泛使用的自动化测试框架&#xff0c;它可以帮助我们更轻松地…

【Java】如何理解 Spring 核心概念: 什么是 IoC, 什么是 DI?

文章目录 前言一、什么是Spring1, 什么是容器2, 什么是IoC 二、如何理解IoC1, 传统方式的代码编写2, 控制反转的代码编写3, 再谈IoC 三、什么是DI总结 前言 各位读者好, 我是小陈, 这是我的个人主页, 希望我的专栏能够帮助到你: &#x1f4d5; JavaSE基础: 基础语法, 类和对象,…

网络安全学习(ing)

根据网站后缀猜测开发语言及服务常见端口及对应的服务 22 ssh 445 smb 漏洞ms17-010 永恒之蓝 3306 mysql 3389 rdp远程桌面连接服务 80 http 443 https &#xff08;一&#xff09;SSH爆破—模拟攻击 1.信息收集 nmap扫描目标主机的端口&#xff1a; nmap IP 发现22端口开放…

再次认识结构体

> 作者简介&#xff1a;დ旧言~&#xff0c;目前大一&#xff0c;现在学习Java&#xff0c;c&#xff0c;c&#xff0c;Python等 > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 望小伙伴们点赞&#x1f44d;收藏✨加关注哟&#x1f495;&#x1…

软件工程学术顶会——ICSE 2023 议题(网络安全方向)清单与摘要

按语&#xff1a;IEEE/ACM ICSE全称International Conference on Software Engineering&#xff0c;是软件工程领域公认的旗舰学术会议&#xff0c;中国计算机学会推荐的A类国际学术会议&#xff0c;Core Conference Ranking A*类会议&#xff0c;H5指数74&#xff0c;Impact s…

Android 在一个APP里打开另一个APP

前言 不知道你们有没有注意过&#xff0c;每次打开一些软件的时候都会有广告引导页&#xff0c;有时候手滑点到了&#xff0c;会有进入手机上的另一个APP&#xff0c;这有没有引起你的注意呢&#xff1f; 运行效果图 # 正文 为了测试这个功能&#xff0c;首先要创建两个项目&…

019 - limit

limit&#xff1a;限制返回结果数量&#xff1b; 该LIMIT子句可用于约束SELECT语句返回的行数 。 LIMIT接受一个或两个数字参数&#xff0c;这些参数必须都是非负整数常量&#xff0c;但以下情况除外&#xff1a; 在准备好的语句中&#xff0c;LIMIT 可以使用? 占位符标记指…

双端队列(deque)与优先队列(priority_queue)

文章目录 一.双端队列——deque1.deque的优点与缺点2.deque的原理 二.优先队列——priority_queue1.什么是优先队列&#xff1f;2.优先队列的基本使用3.什么是仿函数&#xff1f;4.优先队列的模拟实现 一.双端队列——deque 在上一章stack、queue的模拟实现中&#xff0c;我们…