当前位置: 首页 > article >正文

(done) 并行计算学习 (Day1: 两个简单的 OpenMP 例子)

来源:https://dazuozcy.github.io/posts/introdution-to-openmp-intel/#1-%E6%A6%82%E8%BF%B0


一个比较有意义的模型
在这里插入图片描述
Master thread 在经过 parallel Task1 后也仅仅只保留 Master thread。
或者说,在进入 Fork 阶段之前,以及进入 Join 阶段时,都只有 Master thread 运行


直接看练习


练习1:并行化 Hello World

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

int main()
{
  #pragma omp parallel
  {
    int ID = omp_get_thread_num();
    printf("hello(%d)", ID);
    printf(" world(%d) \n", ID);
  }
  return 0;
}

使用 OpenMP 编译上面的 Hello World C 文件

gcc -fopenmp foo.c
export OMP_NUM_THREADS=4
./a.out

#pragma omp parallel 申请默认数量的线程。 omp_get_thread_num() 返回每个线程的唯一标识。范围是[0,N]。

这里我遇到过错误信息:“error: invalid branch to/from OpenMP structured block”
该错误信息通常出现在使用 OpenMP 并行编程模型时,特别是在处理并行区域的分支(例如 if 或 goto)时出现了问题。为了理解这个错误,首先需要了解 OpenMP 并行区域的基本工作方式。

OpenMP 中的 结构化块(structured blocks)是指在并行区域中使用的控制流结构,例如循环(for)、并行区域(parallel)、并行部分(sections)等。结构化块有严格的规则,以便 OpenMP 能正确地对代码进行并行化处理。

该错误的含义是 尝试在 OpenMP 的结构化块中进行不允许的跳转或分支操作。以下是可能引发该错误的情况:

  • 从 OpenMP 结构化块跳出或跳入:在 OpenMP 的结构化块(如 parallel、for、sections)内,如果有跳转语句(例如 goto 或 break),可能会被认为是不合法的。OpenMP 要求这些结构化块中的控制流是受控的,因此不允许跳转。
  • 条件分支(if)的使用不当:某些情况下,在 OpenMP 并行区域中使用 if 语句时可能会导致这个错误,尤其是当 if 语句导致跳转到不允许的地方时。例如,如果你在并行区域内根据某个条件来跳转到外部的代码区域,而不是保持结构化代码块的完整性,就可能触发这个错误。

练习2:把下面这个串行版本的计算Pi值的程序改成并行版本。

void calc_pi_serial()
{
    long num_steps = 0x20000000;
    double sum = 0.0;
    double step = 1.0 / (double)num_steps;
	
	// 圆周率计算原理:圆周率的积分公式
	// 使用梯形法逼近积分的值
    double start = omp_get_wtime( );    
    for (long i = 0; i < num_steps; i++) {
        double x = (i + 0.5) * step;
        sum += 4.0 / (1.0 + x * x);
    }    
    double pi = sum * step;
    
    printf("pi: %.16g in %.16g secs\n", pi, omp_get_wtime() - start);
    // will print "pi: 3.141592653589428 in 5.664520263002487 secs"
}

给了一个修改为并行的例子:

#define NUM_THREADS 2

void calc_pi_omp_v1()
{
    long num_steps = 0x20000000;
    double sum[NUM_THREADS] = { 0.0 };
    double step = 1.0 / (double)num_steps;
    int nthreads;
    double start = omp_get_wtime( );    
    
    omp_set_num_threads(NUM_THREADS);
    #pragma omp parallel
    {
        int id = omp_get_thread_num();
        int nthrds = omp_get_num_threads();
        if (id == 0) { // master thread
            nthreads = nthrds;
        }
        for (long i = id; i < num_steps; i += nthrds) {
            double x = (i + 0.5) * step;
            sum[id] += 4.0 / (1.0 + x * x);
        }  
    }
    double pi = 0;
    for (int i = 0; i < nthreads; i++) {
        pi += sum[i]*step;
    }
    
    printf("pi: %.16g in %.16g secs\n", pi, omp_get_wtime() - start);
}

上述并行版本可以得到正确的结果,但是当NUM_THREADS的值配置的更大的时候,耗时反而增加了。

原因是伪共享(false sharing)。



http://www.kler.cn/a/513617.html

相关文章:

  • Github 2025-01-20 开源项目周报 Top15
  • WebSocket 和 Socket 的区别
  • RV1126+FFMPEG推流项目(8)AENC音频编码模块
  • HTML语言的计算机基础
  • React Context 实现全局组件注册
  • C++ 内存分配和管理(八股总结)
  • JavaWeb开发(十五)实战-生鲜后台管理系统(二)注册、登录、记住密码
  • 【C++】揭秘类与对象的内在机制(核心卷之深浅拷贝与拷贝构造函数的奥秘)
  • 《从入门到精通:蓝桥杯编程大赛知识点全攻略》(五)-数的三次方根、机器人跳跃问题、四平方和
  • Python 进阶 - Excel 基本操作
  • 智能系统的感知和决策
  • 第15篇:从入门到精通:Python标准库详解
  • LeetCode 热题 100_全排列(55_46_中等_C++)(递归(回溯))
  • 简识JVM私有内存区域栈、数据结构
  • 蓝桥杯R格式--高精度算法模拟
  • 【MySQL】 常见数据类型
  • 10倍数据交付提升 | 通过逻辑数据仓库和数据编织高效管理和利用大数据
  • C#程序关闭时保证所有线程结束的方法
  • elasticsearch 数据导出/导入
  • 【记录】记录项目中的问题
  • Linux常用汇总
  • windows下修改docker的镜像存储地址
  • 易语言模拟真人鼠标轨迹算法 - 防止游戏检测
  • Axios HTTP库基础教程:从安装到GET与POST请求的实现
  • 二十八、Qos服务质量
  • 优化使用 Flask 构建视频转 GIF 工具