并行计算-OPENMP(windows)

这篇具有很好参考价值的文章主要介绍了并行计算-OPENMP(windows)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

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

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

并行计算-OPENMP(windows),windows,并行计算,OpenMP

 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文章来源地址https://www.toymoban.com/news/detail-603654.html

到了这里,关于并行计算-OPENMP(windows)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++】OpenMP简介

    1、program作用 #pragma 是 C 和 C++ 语言中的一个预处理指令。它主要用于向编译器发送特定的信息或者指示,以便控制编译过程。#pragma 通常与编译器特定的选项或功能一起使用,因此它的具体行为和实现可能因不同的编译器而有所不同。 #pragma 的语法如下: 其中,directive_name

    2024年02月05日
    浏览(30)
  • Ubuntu安装OpenMP及案例

    进入官网OpenMP,下载稳定版本。 解压后进入文件夹,运行 ./configure --prefix=/home/jame/Public/openmp (自定义路径) 编译运行 路径配置 添加 案例测试 进入 /home/jame/Downloads/openmpi-4.1.5/examples 运行(使用四个线程运行) 直接参考指令教程。 个人测试代码: CMakeLists关键配置:

    2024年02月01日
    浏览(28)
  • 性能优化-OpenMP基础教程(三)

    本文主要介绍OpenMP并行编程的环境变量和实战、主要对比理解嵌套并行的效果。 🎬个人简介:一个全栈工程师的升级之路! 📋个人专栏:高性能(HPC)开发基础教程 🎀CSDN主页 发狂的小花 🌄人生秘诀:学习的本质就是极致重复! 目录 一、OpenMP是什么? 1 OpenMP的主要特点

    2024年02月03日
    浏览(37)
  • 性能优化-OpenMP基础教程(一)

    本文主要介绍OpenMP并行编程技术,编程模型、指令和函数的介绍、以及OpenMP实战的几个例子。希望给OpenMP并行编程者提供指导。 🎬个人简介:一个全栈工程师的升级之路! 📋个人专栏:高性能(HPC)开发基础教程 🎀CSDN主页 发狂的小花 🌄人生秘诀:学习的本质就是极致

    2024年02月03日
    浏览(47)
  • MacOS安装openMP报错【已解决】

    error: Target “WLBG” links to: OpenMP::OpenMP_CXX but the target was not found. Possible reasons include: * There is a typo in the target name. * A find_package call is missing for an IMPORTED target. * An ALIAS target is missing. 最开始是报这个错,我以为是cmakeLists出错了,target_link_libraries里面加了 OpenMP::OpenMP_CXX 。但是我照

    2024年04月14日
    浏览(30)
  • MPI和OpenMP实现蒙特卡罗算法

    基本思想 当所求解问题是某种随机事件出现的概率,或者是某个随机变量的期望值时,通过某种“实验”的方法,以这种事件出现的频率估计这一随机事件的概率,或者得到这个随机变量的某些数字特征,并将其作为问题的解。 数学应用: 通常蒙特·卡罗方法通过构造符合

    2024年02月05日
    浏览(37)
  • MacOS M1芯片openmp库出现mach-o file, but is an incompatible architecture (have ‘arm64‘, need ‘x86_64‘问题解决

    报错如下所示: ImportError: dlopen(/Users/Xuan/Developer/DLTools/GPRModule/gprMax/fields_updates_ext.cpython-310-darwin.so, 0x0002): tried: ‘/Users/Xuan/Developer/DLTools/GPRModule/gprMax/fields_updates_ext.cpython-310-darwin.so’ (mach-o file, but is an incompatible architecture (have ‘arm64’, need ‘x86_64’)), ‘/System/Volumes/Preboot/Cr

    2024年02月16日
    浏览(48)
  • 并行计算(一)——并行计算机系统及结构模型

    SMP、COW、PVP、MPP计算机相关_神.秘.人的博客-CSDN博客_并行向量处理机 在下面的讲解之前,我们先看一下并行计算的量纲。 1.1.1 并行计算和计算机科学 随着计算机和计算机学科的发展,所有的学科都转向定量化和精确化,因此也出现了很多计算开头的学科,如计算数学、计算

    2024年01月23日
    浏览(41)
  • 并行计算与云计算的结合:实现高效计算

    并行计算和云计算都是当今计算技术的重要组成部分,它们各自具有独特的优势和应用场景。并行计算可以在多个处理单元之间分配任务,以提高计算效率,而云计算则可以通过分布式资源共享和虚拟化技术,实现计算资源的灵活性和可扩展性。随着数据量的增加和计算任务

    2024年04月11日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包