MPI 集体通信(collective communication)

1、MPI调用接口

(1)广播MPI_BCAST

(2)散发MPI_SCATTER

(3)收集MPI_GATHER

(4)归约MI_REDUCE

MPI_REDUCE将组内每个进程输入缓冲区中的数据按给定的操作op进行运算,并将其结果返回到序列号为root的进程的输出缓冲区中。

(5)MPI_ALLREDUCE

MPI_Allreduce 与 MPI_Reduce 相同,不同之处在于它不需要根进程 ID(因为结果分配给所有进程)。 

MPI_Allreduce 等效于先执行 MPI_Reduce,然后执行 MPI_Bcast。 

2. 例子

(1)利用MPI_Scatter和MPI_Gather计算0, 1, 2, ..., 99的平均值

思路:

  1. 在根进程(进程0)上生成一个数组0, 1, 2, ..., 99。
  2. 把所有数字用MPI_Scatter分发给4进程,每个进程得到25个数字。
  3. 每个进程计算它们各自得到的数字的平均数。
  4. 根进程用MPI_Gather收集各进程的平均数,然后计算这4个平均数的平均数,得出最后结果。
// Program that computes the average of an array of elements in parallel using
// MPI_Scatter and MPI_Gather
//
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <mpi.h>
#include <assert.h>// Creates an array of 0, 1, 2, ..., 99
float *create_array(int num_elements) {float *array_nums = (float *)malloc(sizeof(float) * num_elements);for (int i = 0; i < num_elements; i++) {array_nums[i] = i;}return array_nums;
}// Computes the average of an array of numbers
float compute_avg(float *array, int num_elements) {float sum = 0.f;int i;for (i = 0; i < num_elements; i++) {sum += array[i];}return sum / num_elements;
}int main(int argc, char** argv) {MPI_Init(NULL, NULL);int world_rank;MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);int world_size;MPI_Comm_size(MPI_COMM_WORLD, &world_size);assert(world_size == 4);// Create a random array of elements on the root process. Its total// size will be the number of elements per process times the number// of processesfloat *array_nums = NULL;if (world_rank == 0) {array_nums = create_array(100);}// For each process, create a buffer that will hold a subset of the entire arrayint num_elements_per_proc = 25;float *sub_array_nums = (float *)malloc(sizeof(float) * num_elements_per_proc);assert(sub_array_nums != NULL);// Scatter the random numbers from the root process to all processes in// the MPI worldMPI_Scatter(array_nums, num_elements_per_proc, MPI_FLOAT, sub_array_nums,num_elements_per_proc, MPI_FLOAT, 0, MPI_COMM_WORLD);// Compute the average of your subsetfloat sub_avg = compute_avg(sub_array_nums, num_elements_per_proc);// Gather all partial averages down to the root processfloat *sub_avgs = NULL;if (world_rank == 0) {sub_avgs = (float *)malloc(sizeof(float) * world_size);assert(sub_avgs != NULL);}MPI_Gather(&sub_avg, 1, MPI_FLOAT, sub_avgs, 1, MPI_FLOAT, 0, MPI_COMM_WORLD);// Now that we have all of the partial averages on the root, compute the// total average of all numbers. Since we are assuming each process computed// an average across an equal amount of elements, this computation will// produce the correct answer.if (world_rank == 0) {float avg = compute_avg(sub_avgs, world_size);printf("Avg of all elements is %f\n", avg);// Compute the average across the original data for comparisonfloat original_data_avg =compute_avg(array_nums, num_elements_per_proc * world_size);printf("Avg computed across original data is %f\n", original_data_avg);}// Clean upif (world_rank == 0) {free(array_nums);free(sub_avgs);}free(sub_array_nums);MPI_Barrier(MPI_COMM_WORLD);MPI_Finalize();
}

编译命令:

mpicc -o avg.c avg

运行命令:

mpirun -n 4 ./avg

输出结果:

(2)利用MPI_Reduce计算0, 1, 2, ..., 99的平均值

使用 MPI_Reduce 可以简化上一个例子的代码中,各进程平均数求和的写法。

在下面的代码中,每个进程都会创建随机数并计算和保存在 local_sum 中。 然后使用 MPI_SUM 将 local_sum 归约至根进程。 然后,全局平均值为 global_sum / (world_size * num_elements_per_proc)

// Program that computes the average of an array of elements in parallel using
// MPI_Scatter and MPI_Reduce
//
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <mpi.h>
#include <assert.h>// Creates an array of 0, 1, 2, ..., 99
float *create_array(int num_elements)
{float *array_nums = (float *)malloc(sizeof(float) * num_elements);for (int i = 0; i < num_elements; i++){array_nums[i] = i;}return array_nums;
}// Computes the average of an array of numbers
float compute_avg(float *array, int num_elements)
{float sum = 0.f;int i;for (i = 0; i < num_elements; i++){sum += array[i];}return sum / num_elements;
}int main(int argc, char **argv)
{MPI_Init(NULL, NULL);int world_rank;MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);int world_size;MPI_Comm_size(MPI_COMM_WORLD, &world_size);assert(world_size == 4);// Create a random array of elements on the root process. Its total// size will be the number of elements per process times the number// of processesfloat *array_nums = NULL;if (world_rank == 0){array_nums = create_array(100);}// For each process, create a buffer that will hold a subset of the entire arrayint num_elements_per_proc = 25;float *sub_array_nums = (float *)malloc(sizeof(float) * num_elements_per_proc);assert(sub_array_nums != NULL);// Scatter the random numbers from the root process to all processes in// the MPI worldMPI_Scatter(array_nums, num_elements_per_proc, MPI_FLOAT, sub_array_nums,num_elements_per_proc, MPI_FLOAT, 0, MPI_COMM_WORLD);/*--------------- Use MPI_Reduce --------------- */// Sum the numbers locallyfloat local_sum = 0;int i;for (i = 0; i < num_elements_per_proc; i++){local_sum += sub_array_nums[i];}// Print the random numbers on each processprintf("Local sum for process %d - %f, avg = %f\n",world_rank, local_sum, local_sum / num_elements_per_proc);// Reduce all of the local sums into the global sumfloat global_sum;MPI_Reduce(&local_sum, &global_sum, 1, MPI_FLOAT, MPI_SUM, 0,MPI_COMM_WORLD);// Print the resultif (world_rank == 0){printf("Total sum = %f, avg = %f\n", global_sum,global_sum / (world_size * num_elements_per_proc));// Compute the average across the original data for comparisonfloat original_data_avg =compute_avg(array_nums, num_elements_per_proc * world_size);printf("Avg computed across original data is %f\n", original_data_avg);}// Clean upif (world_rank == 0){free(array_nums);}free(sub_array_nums);MPI_Barrier(MPI_COMM_WORLD);MPI_Finalize();
}

输出结果:

(3)计算0, 1, 2, ..., 99的标准差

标准差定义:

  1. 首先计算所有数字的平均值,用MPI_Allreduce
  2. 累计每个数字与平均值的偏差,用MPI_Reduce
  3. 求平均
// Program that computes the standard deviation of an array of elements in parallel using
// MPI_Scatter, MPI_Allreduce and MPI_Reduce
//
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <mpi.h>
#include <math.h>
#include <assert.h>// Creates an array of 0, 1, 2, ..., 99
float *create_array(int num_elements)
{float *array_nums = (float *)malloc(sizeof(float) * num_elements);for (int i = 0; i < num_elements; i++){array_nums[i] = i;}return array_nums;
}// Computes the average of an array of numbers
float compute_avg(float *array, int num_elements)
{float sum = 0.f;int i;for (i = 0; i < num_elements; i++){sum += array[i];}return sum / num_elements;
}int main(int argc, char **argv)
{MPI_Init(NULL, NULL);int world_rank;MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);int world_size;MPI_Comm_size(MPI_COMM_WORLD, &world_size);assert(world_size == 4);// Create a random array of elements on the root process. Its total// size will be the number of elements per process times the number// of processesfloat *array_nums = NULL;if (world_rank == 0){array_nums = create_array(100);}// For each process, create a buffer that will hold a subset of the entire arrayint num_elements_per_proc = 25;float *sub_array_nums = (float *)malloc(sizeof(float) * num_elements_per_proc);assert(sub_array_nums != NULL);// Scatter the random numbers from the root process to all processes in// the MPI worldMPI_Scatter(array_nums, num_elements_per_proc, MPI_FLOAT, sub_array_nums,num_elements_per_proc, MPI_FLOAT, 0, MPI_COMM_WORLD);/*--------------- Use MPI_Allreduce --------------- */float local_sum = 0;for (int i = 0; i < num_elements_per_proc; ++i) {local_sum += sub_array_nums[i];}// Reduce all of the local sums into the global sum in order to// calculate the meanfloat global_sum;MPI_Allreduce(&local_sum, &global_sum, 1, MPI_FLOAT, MPI_SUM,MPI_COMM_WORLD);float mean = global_sum / (num_elements_per_proc * world_size);// Compute the local sum of the squared differences from the meanfloat local_sq_diff = 0;for (int i = 0; i < num_elements_per_proc; i++){local_sq_diff += (sub_array_nums[i] - mean) * (sub_array_nums[i] - mean);}// Reduce the global sum of the squared differences to the root// process and print off the answerfloat global_sq_diff;MPI_Reduce(&local_sq_diff, &global_sq_diff, 1, MPI_FLOAT, MPI_SUM, 0,MPI_COMM_WORLD);// The standard deviation is the square root of the mean of the// squared differences.if (world_rank == 0){float stddev = sqrt(global_sq_diff /(num_elements_per_proc * world_size));printf("Mean - %f, Standard deviation = %f\n", mean, stddev);}// Clean upif (world_rank == 0){free(array_nums);}free(sub_array_nums);MPI_Barrier(MPI_COMM_WORLD);MPI_Finalize();
}

输出结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/652886.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么是协方差矩阵?

协方差矩阵&#xff08;Covariance Matrix&#xff09;是一个用于衡量多个变量之间相互关系的工具&#xff0c;在统计学和数据分析领域中非常重要。这个矩阵展现了每一对变量之间的协方差。协方差是衡量两个变量如何一起变化的度量&#xff1b;如果两个变量的协方差是正的&…

第四篇:怎么写express的路由(接口+请求)

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 &#x1f4d8; 引言&#xff1a; &#x1f4…

【Flink-1.17-教程】-【四】Flink DataStream API(7)输出算子(Sink)

【Flink-1.17-教程】-【四】Flink DataStream API&#xff08;7&#xff09;输出算子&#xff08;Sink&#xff09; 1&#xff09;连接到外部系统2&#xff09;输出到文件3&#xff09;输出到 Kafka4&#xff09;输出到 MySQL&#xff08;JDBC&#xff09;5&#xff09;自定义 …

C++力扣题目416--分割等和子集 1049--最后一块石头的重量II

416. 分割等和子集 力扣题目链接(opens new window) 题目难易&#xff1a;中等 给定一个只包含正整数的非空数组。是否可以将这个数组分割成两个子集&#xff0c;使得两个子集的元素和相等。 注意: 每个数组中的元素不会超过 100 数组的大小不会超过 200 示例 1: 输入: […

k8s-配置管理

一、ConfigMap 1.1 创建ConfigMap 1.2 在环境种使用ConfigMap ConfigMap最为常见的使用方式就是在环境变量和Volume中引用。 1.3 在Volume中引用ConfigMap 在Volume中引用ConfigMap&#xff0c;就是通过文件的方式直接将ConfigMap的每条数据填入Volume&#xff0c;每条数据是…

【JavaSE篇】——数组的定义与使用

目录 本章的目标&#xff1a; &#x1f388;数组的基本概念 &#x1f36d;创建数组 &#x1f36d;数组的初始化 &#x1f36d;数组的使用 &#x1f449;数组中元素访问 &#x1f449;遍历数组 &#x1f388;数组是引用类型 &#x1f36d;初始JVM的内存分布 &#x1f…

【周赛】第382场周赛

&#x1f525;博客主页&#xff1a; A_SHOWY&#x1f3a5;系列专栏&#xff1a;力扣刷题总结录 数据结构 云计算 数字图像处理 力扣每日一题_ 从这一场&#xff08;第382场周赛&#xff09;周赛开始记录&#xff0c;目标是尽快达到准确快速AC前三道题&#xff0c;每场比赛…

Windows XP x86 sp3 安装 Google Chrome 49.0.2623.112 (正式版本) (32 位)

1 下载地址&#xff1b; https://dl.google.com/release2/h8vnfiy7pvn3lxy9ehfsaxlrnnukgff8jnodrp0y21vrlem4x71lor5zzkliyh8fv3sryayu5uk5zi20ep7dwfnwr143dzxqijv/49.0.2623.112_chrome_installer.exe 2 直接 双击 49.0.2623.112_chrome_installer.exe 安装&#xff1b; 3 …

第二百九十二回

文章目录 1. 概念介绍2. 方法与细节2.1 实现方法2.2 具体细节 3. 示例代码4. 内容总结 我们在上一章回中介绍了"如何混合选择图片和视频文件"相关的内容&#xff0c;本章回中将介绍如何混合选择多个图片和视频文件.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1…

BGP:04 fake-as

使用 fake-as 可以将本地真实的 AS 编号隐藏&#xff0c;其他 AS 内的对等体在指定本端对等体所在的AS 编号时&#xff0c;应该设置成这个伪AS 编号。 这是实验拓扑&#xff0c;IBGP EBGP 邻居都使用物理接口来建立 基本配置&#xff1a; R1: sys sysname R1 int loo0 ip add…

带libc源码gdb动态调试(导入glibc库使得可执行文件动态调试时可看见调用库函数源码)

文章目录 查看源码是否编译时有-g调试信息和符号表在 gdb 中加载 debug 文件/符号表将 debug 文件放入 ".debug" 文件夹通过 gdb 命令 set debug-file-directory directories GCC的gcc和g区别指定gcc/g&#xff0c;glibc的版本进行编译指定gcc/g的版本指定glibc的和l…

小电影网站上线之nginx配置不带www域名301重定向到www域名+接入腾讯云安全防护edgeone

背景 写了个电影网站&#xff08;纯粹搞着玩的&#xff09;&#xff0c;准备买个域名然后上线&#xff0c;但是看日志经常被一些恶意IP进行攻击&#xff0c;这里准备接入腾讯云的安全以及加速产品edgeone&#xff0c;记录下当时的步骤。 一、nginx配置重定向以及日志格式 ng…

【数据分析】Excel中使用VBA进行宏编程

目录 0 准备工作1 VBA简介1.1 Excel VBA应用程序的构成1.2 事件驱动1.3 宏1.3.1 创建宏1.3.2 宏安全 2 VBA基础2.1 注释2.2 数据类型2.2.1 基本数据类型2.2.2 枚举类型2.2.3 用户自定义数据类型 2.2 变量2.3 常量2.4 运算符2.5 程序结构2.6 过程2.7 函数 3 Excel应用程序开发流…

【Apollo CyberRT】源码分析之 “component” 模块

代码位置 apollo/cyber/component 功能 在自动驾驶系统中&#xff0c;模块&#xff08;如感知、定位、控制系统等&#xff09;在 Cyber ​​RT 下以 Component 的形式存在。不同 Component 之间通过 Channel 进行通信。Component 概念不仅解耦了模块&#xff0c;还为将模块拆…

实现图片分块化(使用einops库)

背景介绍 在进行机器学习的模型训练任务的时候&#xff0c;针对图像数据集的处理&#xff0c;常常会对数据集进行分块的操作&#xff1b;具体到模型结构中&#xff0c;在ViT框架中&#xff0c;把每一个图像看作是一个的patch&#xff0c;每一个patch可以当作是一个NLP领域的一…

mac上搭建hbase伪集群

1. 前言 之前我们已经搭建过了 hbase单点环境&#xff0c;(单机版搭建参见&#xff1a; https://blog.csdn.net/a15835774652/article/details/135569456) 但是 为了模拟一把集群环境 我们还是尝试搭建一个伪集群版 2. 环境准备 jdk环境 1.8hdfs &#xff08;hadoop环境 可选…

Android双指缩放ScaleGestureDetector检测放大因子大图移动到双指中心点ImageView区域中心,Kotlin(2)

Android双指缩放ScaleGestureDetector检测放大因子大图移动到双指中心点ImageView区域中心&#xff0c;Kotlin&#xff08;2&#xff09; 在 Android ScaleGestureDetector检测双指缩放Bitmap基于Matrix动画移动到双指捏合中心点ImageView区域中心&#xff0c;Kotlin-CSDN博客 …

程序员开发要素—Java篇

这是个预留板块&#xff0c;打算写一写作为程序员的基本要素和技术。主要包含基本工具&#xff0c;基础知识&#xff0c;基础插件应用&#xff0c;环境搭建等内容。 具体内容后续补充完整&#xff0c;Ps&#xff1a;请假申请已提交https://blog.csdn.net/qq_18237141/article/…

跟着小德学C++之TOTP

嗨&#xff0c;大家好&#xff0c;我是出生在达纳苏斯的一名德鲁伊&#xff0c;我是要立志成为海贼王&#xff0c;啊不&#xff0c;是立志成为科学家的德鲁伊。最近&#xff0c;我发现我们所处的世界是一个虚拟的世界&#xff0c;并由此开始&#xff0c;我展开了对我们这个世界…

网络安全B模块(笔记详解)- 越权与下载

1.使用渗透机场景kali中工具扫描服务器场景,将web端口号当作Flag提交; 2.使用渗透机场景windows7访问服务器场景mingling.php,将页面中的Flag提交; 3.使用渗透机场景windows7访问服务器场景mingling.php,分析页面内容,查看系统配置信息,并将产品id的最后5位数作为Flag提…