矩阵向量乘法MPI程序的性能评估

news2025/4/5 17:57:25

文章目录

  • 前言
  • 一、实验代码
  • 二、实验运行效果
  • 三、问题以及思考
  • 总结


前言

要求:对矩阵向量乘法MPI程序进行不同输入规模、不同进程数的执行和计时,并对得到运行时间进行计算分析,据此评价该程序的强扩展性和弱扩展性。最后总结学习心得,撰写实验报告。
提示:分布式程序的各进程执行进度不同步,为了较为准确地计时,需要在计时开始时插入一个Barrier,最后取各进程计时结果的最大值。为方便矩阵的生成和计算结果的验证,可以通过自定义函数直接生成单位矩阵和元素全为1的向量用于计算。要特别注意注意C语言中传递二维数组给函数时,只能以一维数组的形式传递,并在函数内部把一维数组视为二维数组使用。


一、实验代码

代码如下:

#include<stdio.h>
#include<mpi.h>
#include<stdlib.h>

void Get_input(int my_rank,int *m,int *n)
{
	if(my_rank==0){
		printf("Please enter m,n:\n");
		scanf("%d %d",m,n);
	}
	MPI_Bcast(m,1,MPI_INT,0,MPI_COMM_WORLD);
	MPI_Bcast(n,1,MPI_INT,0,MPI_COMM_WORLD);
}





void Get_matrix(int n, int m, double *local_matrix, int local_m, int my_rank)
{
    double *A;
    if (!my_rank)
    {
        A = (double *)malloc(m * n * sizeof(double));
        printf("Please enter the matrix:\n");
        for (int i = 0; i < m; ++i)
            for (int j = 0; j < n; ++j)
                scanf("%lf", &A[i * n + j]);
    }
	
    MPI_Scatter(A, local_m * n, MPI_DOUBLE, local_matrix, local_m * n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
}


void Print_matrix(int my_rank,int n,int m,int local_m,double *local_matrix,MPI_Comm comm)
{
	double *matrix = NULL;
	int i,j;
	if(my_rank==0)
	{
		matrix = malloc(m*n*sizeof(double));
		MPI_Gather(local_matrix,local_m*n,MPI_DOUBLE,matrix,local_m*n,MPI_DOUBLE,0,comm);
		printf("The matrix is:\n");
		for(i=0;i<m;++i)
		{
			for(j=0;j<n;++j)
			{
				printf("%f ",matrix[i*n+j]);
			}
			printf("\n");
		}
		free(matrix);
	}
	else{
		MPI_Gather(local_matrix,local_m*n,MPI_DOUBLE,matrix,local_m*n,MPI_DOUBLE,0,comm);
	}
}

void Get_vector(int my_rank,int n,int local_n,double *local_vector,MPI_Comm comm)
{
	double *vector = NULL;
	int i;
	if(my_rank==0)
	{
		vector=(double *)malloc(n*sizeof(double));
		printf("Please enter the vector:\n");
		for(i=0;i<n;i++)
		{
			scanf("%lf",&vector[i]);
		}
	}
	printf("\n");
	MPI_Scatter(vector,local_n,MPI_DOUBLE,local_vector,local_n,MPI_DOUBLE,0,comm);
}




void Print_vector(int my_rank,int n,int local_n,double *local_vector,MPI_Comm comm)
{
	double *vector = NULL;
	int i,j;
	if(my_rank==0)
	{
		vector = malloc(n*sizeof(double));
		MPI_Gather(local_vector,local_n,MPI_DOUBLE,vector,local_n,MPI_DOUBLE,0,comm);
		printf("The vector is:\n");
		for(i=0;i<n;i++){
			printf("%f ",vector[i]);
		}
		printf("\n");
		free(vector);
	}
	else{
		MPI_Gather(local_vector,local_n,MPI_DOUBLE,vector,local_n,MPI_DOUBLE,0,comm);
	}
}



void Mat_vect_mult(double *local_matrix,double *local_vector,double *local_y,int local_m,int n,int local_n,MPI_Comm comm)
{
	int local_i,j;
	double *x;
	
	x=malloc(n*sizeof(double));
	
	MPI_Allgather(local_vector,local_n,MPI_DOUBLE,x,local_n,MPI_DOUBLE,comm);
	
	for(local_i=0;local_i<local_m;local_i++)
	{
		local_y[local_i]=0.0;
		for(j=0;j<n;j++)
		{
			local_y[local_i]+=local_matrix[local_i*n+j]*x[j];
		}
	}
	free(x);
}
void Print_y(int my_rank,double *local_y,int m,int local_m,MPI_Comm comm)
{
	double *y=NULL;
	int i;
	if(my_rank==0){
		y=malloc(m*sizeof(double));
		MPI_Gather(local_y,local_m,MPI_DOUBLE,y,local_m,MPI_DOUBLE,0,comm);
		printf("The vector y is:\n");
		for(i=0;i<m;i++)
		{
			printf("%lf ",y[i]);
		}
		printf("\n");
		free(y);
	}
	else{
		MPI_Gather(local_y,local_m,MPI_DOUBLE,y,local_m,MPI_DOUBLE,0,comm);
	}
}

int main()
{
	int comm_sz,my_rank,i;
	int m,n,local_m,local_n;
	double *local_matrix,*local_vector;
	double *local_y;
	double start,end;
	
	MPI_Init(NULL,NULL);
	MPI_Comm_size(MPI_COMM_WORLD,&comm_sz);
	MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
	
	Get_input(my_rank,&m,&n);
	local_m=m/comm_sz;
	local_n=n/comm_sz;
	local_matrix=(double *)malloc(local_m*n*sizeof(double));
	local_vector=(double *)malloc(local_n*sizeof(double));
	local_y=(double *)malloc(local_m*sizeof(double));

	Get_matrix(n,m,local_matrix,local_m,my_rank);
	Print_matrix(my_rank,n,m,local_m,local_matrix,MPI_COMM_WORLD);
	Get_vector(my_rank,n,local_n,local_vector,MPI_COMM_WORLD);
	Print_vector(my_rank,n,local_n,local_vector,MPI_COMM_WORLD);
	MPI_Barrier(MPI_COMM_WORLD);
	start = MPI_Wtime();
	Mat_vect_mult(local_matrix,local_vector,local_y,local_m,n,local_n,MPI_COMM_WORLD);
	MPI_Barrier(MPI_COMM_WORLD); 
    end = MPI_Wtime();
	Print_y(my_rank,local_y,m,local_m,MPI_COMM_WORLD);
	
	MPI_Finalize();
	if (my_rank == 0) {
    printf("Runtime = %f\n", end-start);
}
	return 0;
}

二、实验运行效果

串行效果:(64*64的全是3的矩阵与向量1相乘1个进程)
在这里插入图片描述

并行效果:(64*64的全是3的矩阵与向量1相乘2个进程)
在这里插入图片描述

并行效果:(64*64的全是3的矩阵与向量1相乘4个进程)
在这里插入图片描述

反复多次换数据规模进行实验,罗列出表格。


三、问题以及思考

本次实验难度不大,因为在原来的基础上只需要增加计算时间的工具,稍微有难度的地方则是在于由于一般的数据计算时间极快,并不能发现,所以输入的矩阵规模一定要大,但由于我设计的程序是用手动输入所以十分繁琐,不得已通过Python编写了一个写矩阵的程序,在通过全选的方式复制粘贴到矩阵输入处,不过还是十分繁琐,所以一定要注意可以在刚开始就使用读取txt文件的方式,这样能大大简便使用的难度。


总结

该程序实验规模不变,进程数增加,运行时间线性减少,不能维持恒定效率所以该程序不是强可扩展性,但是规模以一定速率扩大效率没有随着进程数增加而降低,所以该程序是可扩展的,该程序规模变大可以通过增加进程数保持效率不变,所以该程序是弱可扩展性的。

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

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

相关文章

feign调用get请求的接口时,出现“Request method ‘POST‘ not supported“

上面是错误的写法 下面是正确的写法 其实就是在feign接口的参数中加了个SpringQueryMap注解 SpringQueryMap是微服务之间调用&#xff0c;使用openfeign通过GET请求方式来处理通过实体类来传参情况的注解。 注意&#xff1a;被SpringQueryMap注解的对象只能有一个 如果需要传…

vulhub-struts2-S2-001 远程代码执行漏洞复现

漏洞原理 该漏洞因用户提交表单数据并且验证失败时&#xff0c;后端会将用户之前提交的参数值使用OGNL表达式%{value}进行解析&#xff0c;然后重新填充到对应的表单数据中。如注册或登录页面&#xff0c;提交失败后一般会默认返回之前提交的数据&#xff0c;由于后端使用%{va…

Python 中常用的数据类型及相关操作详解

文章目录 列表&#xff08;Lists&#xff09;创建列表访问列表元素添加元素到列表删除列表元素切片&#xff08;Slicing&#xff09;其他常用操作 元组&#xff08;Tuples&#xff09;创建元组访问元组元素元组长度其他常用操作 字符串&#xff08;Strings&#xff09;创建字符…

低成本渲染提速!掌握这6点,不换电脑也能迅速提升渲染速度

之前一期给大家分享过影响渲染速度的三个“大坑”: 渲染干货 | 渲染速度太慢&#xff1f;很有可能你是踩了这些坑https://blog.csdn.net/LhcyyVSO/article/details/131191936 本期再来谈谈如何在不换电脑配置的情况下&#xff0c;以更低的成本提升你的渲染速度&#xff0c;毕…

无人机电池能不能上高铁以及什么型号的电池可以上高铁

无人机电池能不能上高铁以及什么型号的电池可以上高铁 高铁关于电池的限制电池参数介绍可上高铁的无人机锂电池6S电池3S电池 高铁关于电池的限制 2022年7月1日起施行的《铁路旅客禁止、限制携带和托运物品目录》规定,充电宝、锂电池单块额定能量不超过100Wh 电池参数介绍 明…

致创业者,亚马逊云科技中国峰会“创业者之日”邀您相聚

IDC预测&#xff0c;到2025年全球数据规模将达到175 ZB&#xff0c;这为人工智能模型训练提供了海量数据资源&#xff0c;全球AI产业迅速发展为创业者们带来了巨大的机遇&#xff0c;但也提出了全新的挑战。新的市场、高效的工具和智能的资源&#xff0c;开辟了创新的领域和商业…

和鲸社区数据分析每周挑战【第九十四期:中风患病预测分析】

和鲸社区数据分析每周挑战【第九十四期&#xff1a;中风患病预测分析】 文章目录 和鲸社区数据分析每周挑战【第九十四期&#xff1a;中风患病预测分析】一、前言1、背景描述2、数据说明3、数据集预览 二、数据读取和数据预处理三、探索性数据分析1、绘制相关性矩阵2、中风患病…

1 os|linxu常用命令|vim编辑器

文章目录 oslinux 常用命令用户配置切换用户添加用户设置&#xff08;修改&#xff09;密码删除用户总结 目录以及文件操作查看文件或者目录改变工作目录显示当前工作目录创建目录删除空目录拷贝文件或者目录移动文件或者目录删除文件或者目录修改目录或者文件的权限文字设定法…

年过30的我,今年也遇到了职场危机 ...

在软件测试行业摸爬滚打这么多年&#xff0c;即将人到中年&#xff0c;也会和大家一样面临转型或者跳槽的问题。这里总结了一下自我的看法。 对于找工作这个事情&#xff0c;有这么个普遍现象。工作供求无法匹配~ 1、对于测试招聘者&#xff0c;特别是一、二线互联网公司的招…

12.动态规划:子集状压DP和位运算

参考&#xff1a; 0x3f&#xff1a;从集合论到位运算&#xff0c;常见位运算技巧分类总结&#xff01;https://leetcode.cn/circle/discuss/CaOJ45/ 状态压缩DP详细讲解 https://zhuanlan.zhihu.com/p/599427567 【动态规划学习】状压/子集 DP https://leetcode.cn/circle/arti…

zabbix-4-触发器

4.触发器 4.1什么是触发器 当监控的值发现变化后&#xff0c;对应的值不符合预期&#xff0c;则应该通过触发器通知管理人员介入&#xff1b; 比如&#xff1a;监控TCP的80端口&#xff0c;如果存活则符合预期&#xff0c;如果不存活则不符合预期&#xff0c;应该通过触发器通…

从一个线上 Android Bug 回看 Fragment 的基础知识

作者&#xff1a;Kotlin上海用户组 公司的项目在最近遇到了一个与 Fragment 有关的线上 crash&#xff0c;导致这个问题的根本原因比较复杂&#xff0c;导致修复方案的可选项非常有限&#xff0c;不过这个问题的背景、crash 点&#xff0c;以及修复过程都非常有趣&#xff0c;值…

unittest教程__Python+unittest+ddt_实现数据驱动测试(7)

我们设计测试用例时&#xff0c;会出现测试步骤一样&#xff0c;只是其中的测试数据有变化的情况&#xff0c;比如测试登录时的账号密码。这个时候&#xff0c;如果我们依然使用一条case一个方法的话&#xff0c;会出现大量的代码冗余&#xff0c;而且效率也会大大降低。此时&a…

知网英语类专刊《中学生英语》是正规刊物吗?

知网英语类专刊《中学生英语》是正规刊物吗&#xff1f; 《中学生英语》是经国家新闻出版署批准在国内公开发行的教育类学术期刊&#xff0c;由教育部主管&#xff0c;华中师范大学主办的国家级期刊&#xff0c;是正规刊物。 《中学生英语》是中国外语教学期刊质量检测网络入…

南京贸易企业增值税居高不下,该如何解决?

南京贸易企业增值税居高不下&#xff0c;该如何解决&#xff1f; 《税筹顾问》专注于园区招商&#xff0c;您的贴身节税小能手&#xff0c;合理合规节税&#xff01; 南京作为省会城市&#xff0c;近年来由于芯片、生物医药等产业的发展而跻身前十&#xff0c;随着它在教育、军…

【探索 Kubernetes|作业管理篇 系列 11】控制器的核心功能

前言 大家好&#xff0c;我是秋意零。 上一篇结束了 Pod 对象的内容。 今天要探讨的内容是 “控制器”&#xff0c;它是 Kubernetes 编排最核心的功能。理解了 “控制器”&#xff0c;你就能理解 Deployment、StatefulSet、DaemontSet、Job、CroJob 控制器对象。 最近搞了一…

使用parcel搭建threejs开发环境

一、什么是parcel parcel官网&#xff1a;https://www.parceljs.cn/ Parcel是一个快速、零配置的Web应用打包器&#xff0c;可将JavaScript、CSS、HTML和图像等静态文件打包到一个捆绑文件中。它的主要目标是简化Web应用程序的打包过程&#xff0c;使开发人员可以更快速地创建…

测试开发工是做什么的?2023年往后测试之路发展前景?

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 现在公司企业对测…

Linux目录分类说明

在Linux根目录下一般包括如下目录&#xff0c;这里就这些目录的特点做一些归纳。&#xff08;centos8为例&#xff09; 一、/var目录 /var目录是一个包含经常变化的文件的目录。它是Variable的缩写&#xff0c;也有些人解释为Versioned Archives。通常包含以下内容&#xff1a;…

Groovy基础教程

一、概述 Groovy是一种基础JVM(Java虚拟机)的敏捷开发语言&#xff0c;他结合了Python、Ruby和Smalltalk的特性&#xff0c;Groovy代码能够于Java代码很好的结合&#xff0c;也能用于扩展现有代码。由于其运行在JVM的特性&#xff0c;Groovy可以使用其他Java语言编写法的库。 …