【OpenMP】 2.2 线程同步

        OpenMP中的线程时并发执行的,即不同线程时乱序执行的,有时需要并发线程来协调线程组的执行,达到约束线程组之间某些操作的顺序。

        此处还是通过前文【OpenMP】 2.1 简单示例-CSDN博客的例程进行说明。

1 、临界区(critical)

        临界区critical构造定义了一个线程间相互排斥的代码块,即并行构造中一次只能有一个线程执行临界区中的代码块,其余的线程在critical构造处等待,直到之前的线程完成后依次运行。

#include <stdio.h>
#include <omp.h>

#define NTHREADS 4

static long num_steps = 1e9;
double step;

int main() {
    int i, nthreads;
    double pi, full_sum = 0.0;
    double start_time, run_time;

    step = 1.0 / (double) num_steps;
    full_sum = 0.0;
    omp_set_num_threads(NTHREADS);
    start_time = omp_get_wtime();

#pragma omp parallel default(shared)
    {
        int i, id = omp_get_thread_num();
        int numthreads = omp_get_num_threads();
        //创建局部变量x、partial_sum,仅在当前线程内可见
        double x, partial_sum = 0;

        //获取真实线程
        if (id == 0)
            nthreads = numthreads;

        for (i = id; i < num_steps; i += numthreads) {
            x = (i + 0.5) * step;
            partial_sum += 4.0 / (1.0 + x * x);
        }
        // 一次只能有一个线程运行下述代码块,其余线程在此处等待
        // 如果构造中没有添加大括号{},则并行区域只有构造下的一条语句
#pragma omp critical
        full_sum += partial_sum;
    } // end of parallel region

    pi = step * full_sum;
    run_time = omp_get_wtime() - start_time;
    printf("\n pi  \%f in \%f secs \%d threds \n ",
           pi, run_time, nthreads);
}	  

 pi  3.141593 in 0.848268 secs 4 threds 
 
Process finished with exit code 0

        上述示例中通过临界区实现的积分计算,且每个线程只执行一次临界区中的代码;需要注意的是如果并行区域内的代码是频繁遇见critical临界区,将会浪费大量的时间在临界区钱的等待过程中,影响并行性能。

2、栅栏(barrier)

        栅栏可以看做是另一个并行同步指令(与OpenMP构造不同的是它不与结构化的代码块相关联),与临界区不同的是,栅栏是在并行代码段中定义了一个线程间的同步点,即所有线程都要运行到这个点处,程序才可以继续往下进行,否则线程在栅栏构造处等待。

        

#include <iostream>
#include <omp.h>

#define NTHREADS 4

double needs_all_of_Arr(int id, int nthrds, const double Arr[]) {
    double result = 0.;
    for (int i = 0; i < nthrds; ++i) {
        result += Arr[i];
    }
    return result / id;
}


int main() {
    double Arr[NTHREADS], Brr[NTHREADS];
    int numthrds;
    omp_set_num_threads(NTHREADS);
#pragma omp parallel
    {
        int id, nthrds;
        id = omp_get_thread_num();
        nthrds = omp_get_num_threads();
        if (id == 0) numthrds = nthrds;
        Arr[id] = id;
//所有线程都要运行到此处后才可以继续往下执行
#pragma omp barrier
        Brr[id] = needs_all_of_Arr(id, nthrds, Arr);
#pragma omp critical
        std::cout << "当前ID:" << id << "数值 " << Brr[id] << std::endl;
    } // end of parallel region
}
当前ID:2数值 3
当前ID:1数值 6
当前ID:0数值 inf
当前ID:3数值 2

Process finished with exit code 0

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NNNNNathan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值