04.forthClass

第四节课

  • 制导语句 其他线程跳过master语句,往下执行 progma omp master

  • pragma omp barrier

  • pragma omp for

    隐式阻断,使用nowait跳过

  • pragma omp critical

    作用域代码一次只能执行一个线程

  • pragma omp atomic

    原子操作,类似critical,稍微高级一点;允许不相关的两个线程同时操作

  • pragma omp parallel for

    将for循环并行化

    • redction(+:ave)对for循环中ave变了进行规约

    • firstprivate(sum) 继承并行区域之外的变量的值,用于在进入并行区域之前进行一次初始化,只是一个拷贝,不会修改并行域之外的值。

    • lastprivate(sum) 在退出并行区域时,需要将其值赋给同名的共享变量

    • private 将一个或多个变量声明为线程的私有变量。每个线程都有它自己的变量私有副本,其他线程无法访问;private变量在进入和退出并行区域是“未定义“的。

critical制导语句

    #include <time.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include "omp.h"
    #define NUM_THREADS 5
    #define PAD 8 //跟CPU内存分配有关
    double step;
    static long num_steps;
    int main()
    {
      clock_t start_t, end_t;
      double total_t;
      start_t = clock();
      num_steps = 100000000;
      double  pi;
      pi=0.0;
      step = 1.0 / (double)num_steps; //将1平分成100000步
      omp_set_num_threads(NUM_THREADS); //设置要使用的线程数目
    #pragma omp parallel  //开始并发执行
      {
        double x,sum;
        int id , i;
        id = omp_get_thread_num(); //获取每个线程的id编号
        sum= 0.0;
        for (i=id; i < num_steps; i = i + NUM_THREADS)
        {
          x = (i - 0.5) * step; 
          sum += 4.0 / (1.0 + x * x);
        }
        #pragma omp critical
        {
          pi+=sum*step;
        }
      }
      end_t = clock();
      total_t = (double)(end_t - start_t) / CLOCKS_PER_SEC;
      printf("运行时间为%fs\t%f\n", total_t, pi);
      return 0;
    }

for reduction循环规约

  #pragma omp parallel  //开始并发执行
    {
      double x,sum;
      int id , i;
      id = omp_get_thread_num(); //获取每个线程的id编号
      sum= 0.0;
      #pragma omp parallel for reduction(+:sum) //for循环规约,多个sum最后会加到最外层的sum
      for (i=id; i < num_steps; i = i + NUM_THREADS)
      {
        x = (i - 0.5) * step; 
        sum += 4.0 / (1.0 + x * x);
      }
        pi+=sum*step;

    }

for 循环 lastprivate(sum)规约

  double sum=0.0;
  #pragma omp parallel  //开始并发执行
    {
      double x,sum;
      int id , i;
      id = omp_get_thread_num(); //获取每个线程的id编号
      #pragma omp parallel for lastprivate(sum) //获取每个初始化的sum=0.0
      for (i=id; i < num_steps; i = i + NUM_THREADS)
      {
        x = (i - 0.5) * step; 
        sum += 4.0 / (1.0 + x * x);
      }
      //
        pi+=sum*step; //这里的sum等于最后一个退出的sum的值,虽然能算出结果,但只是其中一个线程的结果,精度会有所下降
  }

for循环 private(sum)规约

  #pragma omp parallel  //开始并发执行
    {
      double x,sum=1.0;
      int id , i;
      id = omp_get_thread_num(); //获取每个线程的id编号
      #pragma omp parallel for lastprivate(sum)
      for (i=id; i < num_steps; i = i + NUM_THREADS)
      {
        x = (i - 0.5) * step; 
        sum += 4.0 / (1.0 + x * x);
      }
      printf("%f\n",sum);
      pi+=sum*step;

    }
    //最后输出4个1.0

Last updated