OpenMP自学笔记(三)OpenMP基础概念与并行计算入门

OpenMP程序设计基础

首先,我们说了OpenMP在Linux下的编译/运行方法

g++ -fopenmp -o hello.o hello.cpp
./hello.o

接着,我们聊到了OpenMP程序结构,与C语言相同,由main函数开始,return 0为结束(整体来看为串行)
我们在串行区,通过编译指导语句#pragma omp parallel [字句] {语句块},来构造并行区
换言之,OpenMP程序结构:

串行→并行→串行

指令parallel构造并行区:(此处开始由多个线程并行执行)

#pragma omp parallel[字句]
{
代码块(此处开始写并行区的代码)
}

当然,我们还可以在构造并行区前,去指定并行区内线程个数。

omp_set_num_threads(8);

OpenMP常用函数

我们可以通过get_wtime来获取系统时间

omp_get_wtime()

如果我们建立两个变量,start_time和end_time,在程序开始时获得start_time,在程序结束时获得end_time,两时间相减就是程序运行时间。
注:如果程序运行时间较短,可以将时间用double类型的变量进行存储。
如果采用int类型,可能会出现0秒(0.8888s)-0秒(0.1024s)=0秒 这种无意义的时间。

并行计算的算法评价-加速比

并行计算能够提高计算性能,对于实际的应用问题,程序员、使用者,最为关心的就是并行程序相对串行程序的执行速度上的差异。换言之,搞并行快了还是慢了,或,加快的倍数—并行加速比(简称加速比)

Rs=ts/tp
加速比的定义:(程序顺序执行的时间)÷(同一结果的程序并行执行的时间)

并行计算的成本

并行计算是有成本的,比如上学时,老师让大家放学做值日,留下的学生越多,成本越高,但成本高了效率并不一定提升。

比如:资源的有限性,笤帚只有1把,同时只能有1个人(主线程)扫地,那剩下99个人(其他线程)只能等着,而且此时,如果你(班主任)强行让100个人大家都要扫地,那结果只能是大家抢夺笤帚,带来结果不可控。

再比方说:事情是有顺序和依赖性的,比如墩地之前需要扫地,扫不干净没法擦地,这时候墩地的同学(线程2)就只能等着扫地的同学(线程1),这时候2个线程并没有提高效率。

因此,我们来总结一下并行计算的开销(也是OpenMP程序设计必须要思考的问题)
(1)线程的建立和销毁、线程间通信、同步带来的开销
(2)为争夺共享资源而引起竞争造成的开销(此时程序运行结果往往随机,结果已经无意义)
(3)各个CPU工作负载分配的不均衡和内存带宽等因素的限制,导致其他线程等待造成的时间开销

这都是并行程序设计需要思考的最基本的问题。

简单的求π值的并行计算程序

我做了一个通过矩阵来模拟一个正方形,通过正方形内的圆面积,来计算π值的程序。
设计了parallel for,并行区内for循环的优化加速、统计运行时间、采取数组来防止写入统一数据造成冲突等
可以参考一个

//写一个并行计算π的程序
//通过定义法来计算π
#include<iostream>
#include<vector>
#include<omp.h>
using namespace std;

int main()
{
    cout<<"计算pai程序开始"<<endl;
    int i,j;
    int tid=4;
    double pai;
    int lang=3;
    int max=10;
    int temp[tid];
    for(i=0;i<tid;i++)
        temp[i]=0;
    int temps=0;
    for(i=0;i<lang;i++)
        max=max*10;
    //定义一个二维数组
    vector<vector<bool>> array(max);
    for (i = 0; i < array.size(); i++)
        array[i].resize(max);

    //cout<<"计算pai程序开始"<<endl;

    omp_set_num_threads(tid);
    double start_time,end_time;
    start_time=omp_get_wtime();   //获取当前时间
    
    #pragma omp parallel shared(i,j,max,array,temp)
    {
    #pragma omp for 
       
        for(int i=0;i<max;i++){
            for(int j=0;j<max;j++){
                int tid=omp_get_thread_num();
                if(i*i+j*j>max*max){
                    array[i][j]=0;
                }
                else{
                    array[i][j]=1;
                    temp[tid]++;
                }
            }
        }
    }
    for(i=0;i<tid;i++){
        temps=temps+temp[i];
    }
    pai=(4.0*temps)/(max*max);
    end_time=omp_get_wtime();
    cout<<"pai="<<pai<<endl;
    cout<<"time="<<end_time-start_time<<"s"<<endl;

    return 0;
}

这个程序采用矩阵去模拟,空间开销很大,计算精度不高。但是模拟的非常直观,方阵=正方形
后续还有许多效率可以提升的地方,欢迎拍砖!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值