并行计算-OPENMP(windows)

news/2024/11/17 20:52:06/

         并行计算(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 atomiccount++;}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 forfor (int i = 0; i < 4; i++){++count;printf_s("Thread num:%d, count:%d\r\n", omp_get_thread_num(), count);}//普通 forcount = 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 barrierprintf("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 orderedfor (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.ppmy.cn/news/977597.html

相关文章

idea如何解决导入的项目不是Maven工程(文件下面没有蓝色的方格)二

简介&#xff1a; Maven项目导入&#xff0c;idea不识别项目 解决方法&#xff1a; 选中pom.xml -- 右键 -- Add as Maven Project

supersqli

这个题&#xff0c;其实之前做过&#xff0c;这里只是换了个名字而已 输入1&#xff0c;提交后可以明显发现url发生变化 &#xff0c;可以猜测SQL注入 源码提示sqlmap是没有灵魂的&#xff0c;说明确实是sql注入 万能密码可以可以到&#xff0c;所包含的表 利用order by查看&a…

Spring Cache的介绍以及使用方法、常用注解

一、Spring Cache介绍 Spring Cache是一个框架&#xff0c;实现了基于注解的缓存功能&#xff0c;只需要简单地加一个注解&#xff0c;就能实现缓存功能. Spring Cache提供了一层抽象&#xff0c;底层可以切换不同的cache实现。具体就是通过CacheManager接口来统一不同的缓存…

将pdf转换成word怎么转换?掌握这几个转换方法就够了

将pdf转换成word怎么转换&#xff1f;将 PDF 转换成 Word 文档是一个常见的需求&#xff0c;我们需要编辑 PDF 文件中的文字内容&#xff0c;但是 PDF 文件并不方便直接编辑。下面介绍几个转换方法。 方法一&#xff1a;使用迅捷 PDF 转换器 这是一款专业的 PDF 转换工具&…

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

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

【C#】并行编程实战:使用 Visual Studio 调试任务

并行编程可以提高应用程序的性能&#xff0c;但是调试起来会更困难&#xff0c;这一点在之前的章节中我们已经有了很直观的感受。对于程序而言&#xff0c;保证程序的正确性和保证性能同样重要。 本章将介绍可以在 Visual Studio 中的调试工具&#xff08;包括 Thread 窗口、Ta…

jmeter-断言

断言作用&#xff1a;让脚本自动化执行过程中&#xff0c;能够自动判定执行结果是否正确&#xff0c;需要添加断言 响应断言 添加方式&#xff1a;测试计划–》线程组–》HTTP请求–》(右键添加)断言–》响应断言 案例 请求:https://www.baidu.com 检查&#xff1a;让程序检查…

云端环境跑通BaseLine

云端环境跑通BaseLine 一、实验流程实践 1.报名 报名日期&#xff1a;2023年7月17日&#xff0c;参与AI夏令营第一期 彳 z h i 亍 c h u &#xff0c;都为第四声 \overset{zhi}{彳}\overset{chu}{亍}&#xff0c;都为第四声 彳zhi亍chu&#xff0c;都为第四声 怎么报名的&a…