MPI编程实例(PI、AllGather、排序)
来源:互联网 发布:软件测试行业怎么样 编辑:程序博客网 时间:2024/06/05 12:02
1.MPI 简介
MPI(Message Passing Interface)是目前最重要的一个基于消息传递的并行编程工具,它具有移植性好、功能强大、效率高等许多优点,而且有多种不同的免费、高效、实用的实现版本,几乎所有的并行计算机厂商都提供对它的支持,成为了事实上的并行编程标准。
MPI是一个库,而不是一门语言,因此对MPI的使用必须和特定的语言结合起来进行。MPI不是一个独立的自包含系统,而是建立在本地并行程序设计环境之上,其进程管理和I/O均由本地并行程序设计环境提供。例如,MPI可以建立在IBM SP2的POE/MPL之上,也可以建立在Intel Paragon的OSF/NX。除了这些商业版本的MPI实现,还有一些免费版的MPI实现,主要有MPICH,LAM和CHIMP。
2.实验环境
本文是在KD机群上跑的实验,在Windows下也可搭建MPI运行环境,本文在这里不做详细介绍。
编译mpi程序: mpicc demo.c –o demo.o;运行mpi程序: mpirun -np 4 ./demo.o
3.实例
(1)用MPI编程实现PI的计算。
算法描述:键盘输入步骤次数 n,并把 n 广播给本通信环境中的所有进程,通过MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); 各个进程计算自己的mypi = width * sum; 通过 MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);由进程 0 进行归约,把每个进程计算出来的 mypi 进行相加(MPI_SUM),赋给pi 。
#include<stdio.h>#include<mpi.h>#include<math.h>int main(int argc, char *argv[]){ int my_rank, num_procs; int i, n = 0; double sum, width, local, mypi, pi; double start = 0.0, stop = 0.0; int proc_len; char processor_name[MPI_MAX_PROCESSOR_NAME]; MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &num_procs); MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); MPI_Get_processor_name(processor_name, &proc_len); printf("Process %d of %d\n", my_rank, num_procs); if(my_rank == 0){ printf("please give step number n:"); scanf("%d", &n); printf("\n"); start = MPI_Wtime(); } // printf("Process %d of %d\n", my_rank, num_procs); MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); width = 1.0 / n; sum = 0.0; for(i = my_rank; i < n; i += num_procs){ local = width * ((double)i + 0.5); sum += 4.0 / (1.0 + local * local); } mypi = width * sum; MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); if(my_rank == 0){ printf("PI is %.20f\n", pi); stop = MPI_Wtime(); printf("Time: %f on %s\n", stop-start, processor_name); fflush(stdout); } MPI_Finalize(); return 0;}
(2)采用MPI_SEND和MPI_RECV编写代码来实现MPI_Allgather的功能,并写一个完整的MPI程序测试并对比实现和MPI原有实现的性能。
算法描述:对每一个进程pi,使用MPI_Send向其他所有进程发送消息,同时使用MPI_Recv从其他所有进程接收消息。
#include<stdio.h>#include<stdlib.h>#include"mpi.h"#include<memory.h>void MPI_Allgather_my(int * senddata, int sendcount, MPI_Datatype senddatatype, int * recvdata, int recvcount, MPI_Datatype recvdatatype, MPI_Comm comm){int rank, size, i;MPI_Request request;MPI_Status status;MPI_Comm_rank(MPI_COMM_WORLD, &rank);MPI_Comm_size(MPI_COMM_WORLD, &size);for(i = 0; i < size; i++){if(i != rank){MPI_Send( senddata, sendcount, senddatatype, i, 1, MPI_COMM_WORLD );MPI_Recv( recvdata + i*recvcount, recvcount, recvdatatype, i, 1, MPI_COMM_WORLD, &status );}}memcpy(recvdata+rank*recvcount,senddata,sizeof(senddatatype)*sendcount);}int main(int argc, char* argv[]){int i, rank, size, tag = 1;int senddata[500] = {1}, recvdata[500*32];double start_time, end_time, s_t, e_t;int count = 500;MPI_Init(&argc, &argv);MPI_Comm_rank(MPI_COMM_WORLD, &rank);MPI_Comm_size(MPI_COMM_WORLD, &size);start_time = MPI_Wtime();MPI_Allgather_my(senddata, count, MPI_INT, recvdata, count, MPI_INT, MPI_COMM_WORLD);end_time = MPI_Wtime();MPI_Reduce(&start_time, &s_t, 1, MPI_DOUBLE, MPI_MIN, 0, MPI_COMM_WORLD);MPI_Reduce(&end_time, &e_t, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);if(rank == 0){printf("myallgather : count = %d total time = %f\n", count, e_t - s_t);}MPI_Barrier(MPI_COMM_WORLD);start_time = MPI_Wtime();MPI_Allgather(senddata, count, MPI_INT, recvdata, count, MPI_INT, MPI_COMM_WORLD);end_time = MPI_Wtime();MPI_Reduce(&start_time, &s_t, 1, MPI_DOUBLE, MPI_MIN, 0, MPI_COMM_WORLD);MPI_Reduce(&end_time, &e_t, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);if(rank == 0){printf("allgather : count = %d total time = %f\n", count, e_t - s_t);}MPI_Finalize();return 0;}
(3)利用MPI实现一个大数据量的排序算法。
算法描述:使用MPI_Send 和MPI_Receive 来进行数据的通信,使用MPI_Send 函数将数据分成n 个部分传送给n 个进程(n 为通信域Comm 包括的进程个数),然后各个
进程对各自所含数据进行快速排序,再使用MPI_Receiv 函数将各个进程都排好的数据传送给进程0,最后在进程0 中进行快排序。
#include <stdio.h> #include <sys/time.h> #include <stdlib.h> #include <time.h> #include <mpi.h> #define length 1000000 void swap(int *data, int i, int j) { int temp = data[i]; data[i] = data[j]; data[j] = temp; } int partition(int *data, int start, int end) { if (start >= end) return 0; int pivotValue = data[start]; int low = start; int high = end - 1; while (low < high) { while (data[low] <= pivotValue && low < end) low++; while (data[high] > pivotValue && high > start) high--; if (low < high) swap(data, low, high); } swap(data, start, high); return high; } void quicksort(int *data, int start, int end) { if (end-start+1 < 2) return; int pivot = partition(data, start, end); quicksort(data, start, pivot); quicksort(data, pivot+1, end); } int main(int argc, char *argv[]) { MPI_Init(&argc, &argv); int rank, size; MPI_Comm_rank (MPI_COMM_WORLD, &rank); MPI_Comm_size (MPI_COMM_WORLD, &size); srand(time(0)); int *data = (int*)malloc(sizeof(int)*length); int i; for (i=0; i<length/size; i++) data[i] = rand(); MPI_Status status; if (rank == 0) { for (i=1; i<size; i++) MPI_Recv(data+i*length/size, length/size, MPI_INT, i, MPI_ANY_TAG, MPI_COMM_WORLD, &status); } else { MPI_Send(data, length/size, MPI_INT, 0, 0, MPI_COMM_WORLD); } struct timeval start, end; gettimeofday(&start, 0); int s; int localDataSize = length; int pivot; for (s=size; s > 1; s /= 2) { if (rank % s == 0) { pivot = partition(data, 0, localDataSize); MPI_Send(data+pivot, localDataSize - pivot,MPI_INT, rank + s/2, 0, MPI_COMM_WORLD); localDataSize = pivot; } else if (rank % s == s/2) { MPI_Recv(data, length, MPI_INT, rank - s/2, MPI_ANY_TAG, MPI_COMM_WORLD, &status); MPI_Get_count(&status, MPI_INT, &localDataSize); } } quicksort(data, 0, localDataSize); gettimeofday(&end, 0); if (rank == 0) { float time = (end.tv_sec - start.tv_sec) + 0.000001*(end.tv_usec - start.tv_usec); printf("Time: %f s\n", time); } MPI_Finalize(); return 0;}
4.小结
陈国良等.并行算法实践[M].北京:高等教育出版社,2004.1.
- MPI编程实例(PI、AllGather、排序)
- MPI之聚合通信-Scatter,Gather,Allgather
- 并行计算mpi [ PI ]
- MPI计算pi值π
- MPI编程--使用最简单的基本函数计算PI值
- MPI编程
- MPI编程
- MPI并行编程基础小结(window下搭建MPI环境,vs配置mpi)
- MPI并行编程计算π值及PSRS排序
- JBPM流程实例(PI)Process Instance
- Mpi与Cuda混合编程(Makefile)
- MPI入门实例讲解
- MPI 堆排序
- MPI 归并排序
- MPI 枚举排序实现
- MPI编程简介
- MPI编程简介
- MPI基本编程框架
- 根文件系统的构建与分析
- codeferces 149D Coloring Brackets 区间dp
- FFmpeg完美编译
- 不懂技术的人不要对懂技术的人说这很容易实现
- poj 2955 Brackets 区间dp
- MPI编程实例(PI、AllGather、排序)
- apache Kafka中partition的leader为-1情况分析
- 数据结构回顾:B、B-、B+、B*-Tree
- 23种经典设计模式UML类图汇总
- [南阳理工OJ91]阶乘之和
- 2015‘互联网+中国’峰会——马化腾主题演讲
- 备忘 socks 转http
- 软件设计的复杂度
- SQL Server中,WITH AS的使用