一、Jacobi迭代
#include<stdio.h>
#include<mpi.h>
#include<stdlib.h> #define totalsize 16
#define mysize totalsize / 4
#define steps 10
int main(int argc, char** argv)
{
int rank, size, i, j, begin_col, end_col;
//除分块大小外,还包括左右两边各一列
float a[totalsize][mysize + 2], b[totalsize][mysize + 2];
float temp[totalsize];//临时数组
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank); printf("Process %d of %d is alive\n", rank, size); //数组初始化
for (i = 0; i < totalsize; i++)
for (j = 0; j < mysize + 2; j++)
a[i][j] = 0;
if (rank == 0)
{
for (i = 0; i < totalsize; i++)
a[i][1] = 8.0;
}
if (rank == 3)
{
for (i = 0; i < totalsize; i++)
a[i][mysize] = 8.0;
}
for (i = 1; i < mysize + 1; i++)
{
a[0][i] = 8.0;
a[totalsize - 1][i] = 8.0;
}
//Jacobi 迭代
for (int n = 1; n <= steps; n++)
{
//从右边的邻居得到数据
if (rank < 3)
{
MPI_Recv(&temp[0], totalsize, MPI_FLOAT, rank + 1, 10, MPI_COMM_WORLD, &status);
for (i = 0; i < totalsize; i++)
a[i][mysize + 1] = temp[i];
}
//向左侧的邻居发送数据
if (rank > 0)
{
for (i = 0; i < totalsize; i++)
temp[i] = a[i][1];
MPI_Send(&temp[0], totalsize, MPI_FLOAT, rank - 1, 10, MPI_COMM_WORLD);
}
//向右侧的邻居发送数据
if (rank < 3)
{
for (i = 0; i < totalsize; i++)
temp[i] = a[i][mysize];
MPI_Send(&temp[0], totalsize, MPI_FLOAT, rank + 1, 10, MPI_COMM_WORLD);
}
//从左侧的邻居得到数据
if (rank > 0)
{
MPI_Recv(&temp[0], totalsize, MPI_FLOAT, rank - 1, 10, MPI_COMM_WORLD, &status);
for (i = 0; i < totalsize; i++)
a[i][0] = temp[i];
}
begin_col = 1;
end_col = mysize;
if (rank == 0) begin_col = 2;
if (rank == 3) end_col = mysize - 1;
for (i = 1; i < totalsize - 1; i++)
for (j = begin_col; j <= end_col; j++)
b[i][j] = 0.25 * (a[i][j + 1] + a[i][j - 1] + a[i + 1][j] + a[i - 1][j]);
for (i = 1; i < totalsize - 1; i++)
for (j = begin_col; j <= end_col; j++)
a[i][j] = b[i][j];
}
MPI_Barrier(MPI_COMM_WORLD);
printf("Process %d:\n", rank);
for (i = 0; i < totalsize; i++)
{
for (j = 1; j <= mysize; j++)
printf("%.2fP%d\t", a[i][j], rank);
printf("\n");
}
MPI_Finalize();
return 0;
}
二、用捆绑发送接收实现Jacobi 迭代
#include<stdio.h>
#include<mpi.h>
#include<stdlib.h> #define totalsize 16
#define mysize totalsize / 4
#define steps 10
int main(int argc, char** argv)
{
int rank, size, i, j, begin_col, end_col;
//除分块大小外,还包括左右两边各一列
float a[totalsize][mysize + 2], b[totalsize][mysize + 2];
float temp[totalsize],temp1[totalsize];//临时数组
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank); printf("Process %d of %d is alive\n", rank, size); //数组初始化
for (i = 0; i < totalsize; i++)
for (j = 0; j < mysize + 2; j++)
a[i][j] = 0;
if (rank == 0)
{
for (i = 0; i < totalsize; i++)
a[i][1] = 8.0;
}
if (rank == 3)
{
for (i = 0; i < totalsize; i++)
a[i][mysize] = 8.0;
}
for (i = 1; i < mysize + 1; i++)
{
a[0][i] = 8.0;
a[totalsize - 1][i] = 8.0;
}
//Jacobi 迭代
for (int n = 1; n <= steps; n++)
{
//从左向右平移数据
if (rank == 0)
{
for (i = 0; i < totalsize; i++)
temp[i] = a[i][mysize];
MPI_Send(&temp[0], totalsize, MPI_FLOAT, rank + 1, 10, MPI_COMM_WORLD); }
else if (rank == 3)
{
MPI_Recv(&temp[0], totalsize, MPI_FLOAT, rank - 1, 10, MPI_COMM_WORLD, &status);
for (i = 0; i < totalsize; i++)
a[i][1] = temp[i];
}
else
{
for (i = 0; i < totalsize; i++)
temp[i] = a[i][1];
MPI_Sendrecv(&temp[0], totalsize, MPI_FLOAT, rank - 1, 10, &temp1[0], totalsize, MPI_FLOAT, \
rank + 1, 10, MPI_COMM_WORLD, &status);
for (i = 0; i < totalsize; i++)
a[i][1] = temp1[i];
}
//从右向左平移数据
if (rank == 0)
{
MPI_Recv(&temp[0], totalsize, MPI_FLOAT, rank + 1, 10, MPI_COMM_WORLD, &status);
for (i = 0; i < totalsize; i++)
a[i][mysize] = temp[i];
}
else if (rank == 3)
{
for (i = 0; i < totalsize; i++)
temp[i] = a[i][1];
MPI_Send(&temp, totalsize, MPI_FLOAT, rank - 1, 10, MPI_COMM_WORLD);
}
else
{
for (i = 0; i < totalsize; i++)
temp[i] = a[i][1];
MPI_Sendrecv(&temp[0], totalsize, MPI_FLOAT, rank + 1, 10, &temp1[0], totalsize, MPI_FLOAT, \
rank - 1, 10, MPI_COMM_WORLD, &status);
for (i = 0; i < totalsize; i++)
a[i][mysize] = temp1[i];
}
begin_col = 1;
end_col = mysize;
if (rank == 0) begin_col = 2;
if (rank == 3) end_col = mysize - 1;
for (i = 1; i < totalsize - 1; i++)
for (j = begin_col; j <= end_col; j++)
b[i][j] = 0.25 * (a[i][j + 1] + a[i][j - 1] + a[i + 1][j] + a[i - 1][j]);
for (i = 1; i < totalsize - 1; i++)
for (j = begin_col; j <= end_col; j++)
a[i][j] = b[i][j];
}
MPI_Barrier(MPI_COMM_WORLD);
printf("Process %d:\n", rank);
for (i = 0; i < totalsize; i++)
{
for (j = 1; j <= mysize; j++)
printf("%.2fP%d\t", a[i][j], rank);
printf("\n");
}
MPI_Finalize();
return 0;
}
矩阵乘
#include <stdio.h>
#include "mpi.h"
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h> #define SIZE 5
//生成随机矩阵
int** generate_matrix(int size)
{
int num = 0, m;
int** matrix;
matrix = (int**)malloc(sizeof(int*) * size);
for (m = 0; m < size; m++)
matrix[m] = (int*)malloc(sizeof(int) * size);
int i, j;
srand(time(NULL) + rand());
for (i = 0; i < size; i++)
{
for (j = 0; j < size; j++)
{
matrix[i][j] = rand() % 20;
}
}
return matrix;
}
//输出矩阵
void print_matrx(int** a, int size)
{
int i, j;
for (i = 0; i < size; i++)
{
for (j = 0; j < size; j++)
{
printf("%d ", a[i][j]);
}
printf("\n");
}
printf("\n");
}
//矩阵相乘([参考](https://blog.csdn.net/qq_35614920/article/details/80570839))
int* Multiplication(int** a, int b[], int size)
{
int* result;
result = (int*)malloc(sizeof(int) * size);
int i, m, n, sum = 0;
for (m = 0; m < size; m++)
{
for (n = 0; n < size; n++)
{
sum += a[n][m] * b[n];
}
result[m] = sum;
sum = 0;
}
return result;
}
int main(int argc, char** argv)
{
int size, rank, dest;
MPI_Comm comm = MPI_COMM_WORLD;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_size(comm, &size);
MPI_Comm_rank(comm, &rank); int** matrix1;
int** matrix2;
int send_buff[SIZE* SIZE];
matrix1 = generate_matrix(size);
matrix2 = generate_matrix(size);
if (rank == 0)
{
printf("matrix1 is :\n");
print_matrx((int**)matrix1, size); printf("matrix2 is :\n");
print_matrx((int**)matrix2, size); int j, k, tmp = 0;
for (j = 0; j < size; j++)
for (k = 0; k < size; k++)
{
send_buff[tmp] = matrix1[j][k];
tmp++;
}
}
int rbuf[SIZE];
int* result;
result = (int*)malloc(sizeof(int) * size);
//分发列
MPI_Scatter(send_buff, size, MPI_INT, rbuf, size, MPI_INT, 0, comm);
result = Multiplication((int**)matrix2, rbuf, size);
MPI_Barrier(comm);//等待所有进程计算结束
int* recv_buff;
recv_buff = (int*)malloc(sizeof(int) * size * size);
MPI_Barrier(comm);
MPI_Gather(result, size, MPI_INT, recv_buff, size, MPI_INT, 0, comm);//收集各列数据
//根进程进行输出
if (rank == 0)
{
printf("\nresult is :\n");
int m, n, tmp = 0;
for (m = 0; m < size; m++)
{
for (n = 0; n < size; n++)
{
printf("%d ", recv_buff[tmp]);
tmp++;
}
printf("\n");
}
printf("\n");
}
MPI_Finalize();
return 0;
}

MPI实现Jacobi的更多相关文章

  1. 雅克比迭代算法(Jacobi Iterative Methods) -- [ mpi , c++]

    雅克比迭代,一般用来对线性方程组,进行求解.形如: \(a_{11}*x_{1} + a_{12}*x_{2} + a_{13}*x_{3} = b_{1}\) \(a_{21}*x_{1} + a_ ...

  2. 【MPI学习4】MPI并行程序设计模式:非阻塞通信MPI程序设计

    这一章讲了MPI非阻塞通信的原理和一些函数接口,最后再用非阻塞通信方式实现Jacobi迭代,记录学习中的一些知识. (1)阻塞通信与非阻塞通信 阻塞通信调用时,整个程序只能执行通信相关的内容,而无法执 ...

  3. 【MPI学习2】MPI并行程序设计模式:对等模式 & 主从模式

    这里的内容主要是都志辉老师<高性能计算之并行编程技术——MPI并行程序设计> 书上有一些代码是FORTAN的,我在学习的过程中,将其都转换成C的代码,便于统一记录. 这章内容分为两个部分: ...

  4. 查找素数Eratosthenes筛法的mpi程序

    思路: 只保留奇数 (1)由输入的整数n确定存储奇数(不包括1)的数组大小: n=(n%2==0)?(n/2-1):((n-1)/2);//n为存储奇数的数组大小,不包括基数1 (2)由数组大小n.进 ...

  5. kmeans算法并行化的mpi程序

    用c语言写了kmeans算法的串行程序,再用mpi来写并行版的,貌似参照着串行版来写并行版,效果不是很赏心悦目~ 并行化思路: 使用主从模式.由一个节点充当主节点负责数据的划分与分配,其他节点完成本地 ...

  6. MPI Maelstrom - POJ1502最短路

    Time Limit: 1000MS Memory Limit: 10000K Description BIT has recently taken delivery of their new sup ...

  7. MPI之求和

    // MPI1.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include "mpi.h" #include &l ...

  8. VS2012下配置MPI

    并行处理结课实验,要用到MPI编程,我的电脑和VS2012都是64位的,以为MPICH也得是64位才行,结果饶了很大的弯——配置正确,添加引用之后,仍然无法识别MPI函数. 后来换了个32位的MPIC ...

  9. MPI+WIN10并行试运行

    系统:2015 win10专业版 x64 MPI安装包:mpich2-1.4.1p1-win-x86-64.man 将后缀改为.msi 以管理员身份安装 安装过程一路默认,注意<behappy为 ...

随机推荐

  1. abs,all,any函数的使用

    ''' abs函数:如果参数为实数,则返回绝对值 如果参数为复数,则返回复数的模 ''' a = 6 b = -6 c = 0 # print("a = {0} , b = {1} , c ...

  2. PHP date_interval_format() 函数

    ------------恢复内容开始------------ 计算两个日期间的间隔,然后格式化时间间隔: 实例 <?php $date1=date_create("2013-01-01 ...

  3. 《Python与量化投资:从基础到实战》PDF高清完整版-PDF|网盘下载附提取码

    本书主要讲解如何利用Python进行量化投资,包括对数据的获取.整理.分析挖掘.信号构建.策略构建.回测.策略分析等.本书也是利用Python进行数据分析的指南,有大量的关于数据处理分析的应用,并将重 ...

  4. luogu 6046 纯粹容器 期望dp

    LINK:纯粹容器 一道比较不错的期望题目. 关键找到计算答案的方法. 容易发现对于每个点单独计算答案会好处理一点. 暴力枚举在第k轮结束统计情况 然后最后除以总方案数即可. 考虑在第k轮的时候结束 ...

  5. vue cli4构建基于typescript的vue组件并发布到npm

    基于vue cli创建一个vue项目 首先安装最新的vue cli脚手架, npm install --global @vue/cli npm WARN optional SKIPPING OPTIO ...

  6. python1.1列表知识点:

    #定义列表[]a=[1,2,3,4,5,6,7,"hello","world"]#列表索引从0开始,指定位置提取元素print(a[3])print(a) #列 ...

  7. 消息队列和事件循环(Event Loop)

    产生原因 为什么会有消息队列和事件循环呢?首先最关键的一点在于JS是个单线程,并且主线程非常繁忙,既要处理 DOM,又要计算样式,还要处理布局,同时还需要处理 JavaScript 任务以及各种输入事 ...

  8. JVM系列之:从汇编角度分析Volatile

    目录 简介 重排序 写的内存屏障 非lock和LazySet 读的性能 总结 简介 Volatile关键字对熟悉java多线程的朋友来说,应该很熟悉了.Volatile是JMM(Java Memory ...

  9. “随手记”APP与已经发布的记账软件“鲨鱼记账”的差距

    我们使用并观察了“鲨鱼记账”APP,发现,我们的软件真的还有很多不足的地方.就功能这方面来说:“鲨鱼记账”APP有更多的收入.支出分类:就界面来说:“鲨鱼记账”APP有比我们优美太多的页面和背景.但是 ...

  10. Docker初探之常用命令

    在正式使用Docker之前,我们先来熟悉下Docker中常用的命令,因为对Docker的操作就如同操作Linux一样,大部分操作通过命令完成. 一.登录 为什么要使用登录? 因为我们使用Docker, ...