在kvm虚拟机上实现mpi计算排序算法

简述

使用cpp调用快排实现在kvm虚拟机上的mpi计算,网络拓扑为树状拓扑。

代码如下

在这里插入代码片#include<iostream>
//#include<windows.h>
#include <unistd.h>
#include<mpi.h>
#include<vector>
#include <algorithm>
#include <ctime>
#include <fstream>
#include<string.h>
using namespace std;
#define TOTAL_SIZE 100000
#define task_count 1000 //总任务分为10个小包
#define Size TOTAL_SIZE/task_count  //每个小包的size
int compare(const void* a, const void* b)
{
	return *(int*)a - *(int*)b;
}
void merge__(int* nums1, int m, int* nums2, int n) {
	int p = m - 1;      // p 指向 nums1[m - 1]
	int q = n - 1;      // q 指向 nums2[n - 1]
	int k = m + n - 1;  // k 指向 nums1[m + n - 1]
	while (p >= 0 && q >= 0) {
		nums1[k--] = nums1[p] > nums2[q] ? nums1[p--] : nums2[q--];
	}
	/* 若 n > m,nums1 遍历完成,将 nums2 中尚未遍历完的元素拷贝到 nums1 中 */
	while (q >= 0) {
		nums1[k--] = nums2[q--];
	}
}

int main(int argc, char* argv[])
{
	int RankID;
	srand(time(NULL));
	int world_rank;
	int process_num;
	int sorted_array[TOTAL_SIZE];
	//int original_array[TOTAL_SIZE];
	MPI_Status status;
	MPI_Request request;
	MPI_Init(&argc, &argv);
	MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
	MPI_Comm_size(MPI_COMM_WORLD, &process_num);
	int namelen;
	char processor_name[MPI_MAX_PROCESSOR_NAME];//设备名
	MPI_Get_processor_name(processor_name, &namelen);

	int key = world_rank;//在通信域中排序用的
	int color=0;
	const char* name = "master0";
	if (!abs(strcmp(processor_name, name)))
	{
		color = 0;
	}
	const char* name0 = "master1";
	if (!abs(strcmp(processor_name, name0)))
	{
		color = 1;
	}
	const char* name1 = "node1";
	const char* name2 = "node2";
	if (!abs(strcmp(processor_name, name1)))
	{
		color = 0;
	}
	if (!abs(strcmp(processor_name, name2)))
	{
		color = 0;
	}
	const char* name3 = "node3";
	const char* name4 = "node4";
	if (!abs(strcmp(processor_name, name3)))
	{
		color = 1;
	}
	if (!abs(strcmp(processor_name, name4)))
	{
		color = 1;
	}
	cout<<"color:"<<color<<",world_rank:"<<world_rank<<",name:"<<processor_name<<endl;
	int sub_array[Size + 1];
	vector<int> task;//任务池中任务号
	vector<int> ended_task;//已经完成的任务号
	int task_data[task_count][Size + 1];
	int end_array[Size + 1];//结束数组
	int length = 0;

	MPI_Comm SplitWorld;
	MPI_Comm_split(MPI_COMM_WORLD, color, key, &SplitWorld);
	int row_size;
	int row_rank;
	MPI_Comm_rank(SplitWorld, &row_rank);
	MPI_Comm_size(SplitWorld, &row_size);
	cout<<"color"<<color<<",world_rank"<<world_rank<<",row_rank"<<row_rank<<",name"<<processor_name<<endl;

	//int test[39] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36 ,37,38,39};
	if (row_rank == 0)
	{
		for (int i = 0; i < task_count; i++)
		{
			if (i >= row_size)
			{
				task.push_back(i);
			}
			ended_task.push_back(i);
		}
		task.push_back(0);
		for (int i = 0; i < task_count; i++)
		{
			for (int j = 0; j < Size; j++)
			{
				//original_array[i* Size+j] = rand() % TOTAL_SIZE;
				task_data[i][j] = rand() % TOTAL_SIZE;
				//cout << task_data[i][j] << " ";
			}//将一维数组化为二维数组 变成需要的任务池
			task_data[i][Size] = i;//最后一位为任务号
			//original_array[i * Size + Size] = i;
			//cout << task_data[i][Size];
			//cout << endl;
		}
		//cout << "**********************************************" << endl;
		for (int k = 0; k < Size + 1; k++)
		{
			end_array[k] = -1;
		}
	}
	//cout << row_rank << ' ' << world_rank << endl;
	MPI_Scatter(task_data, Size + 1, MPI_INT, sub_array, Size + 1, MPI_INT, 0, SplitWorld);

	int flag = 999;
	if (row_rank == 0)
	{
		while (!ended_task.empty())
		{
			//for (int i = 0; i < ended_task.size(); i++)
			//{
			//	cout << ended_task[i];
			//}
			//cout << endl;
			if (task.empty())
			{
				sleep(3);
				//if (world_rank == 0)
				//{
				//	for (int i = 0; i < ended_task.size(); i++)
				//	{
				//		cout << ended_task[i] << ",";
				//	}
				//	cout << endl;
				//}
				for (int i = 1; i < row_size; i++)
				{
					MPI_Iprobe(i, 0, SplitWorld, &flag, &status);
					//cout << "jiedian:" << i << " flag:" << flag << endl;
					if (flag == 1)
					{
						MPI_Recv(sub_array, Size + 1, MPI_INT, MPI_ANY_SOURCE, 0, SplitWorld, &status);
						ended_task.erase(remove(ended_task.begin(), ended_task.end(), sub_array[Size]), ended_task.end());//删除已经完成的任务
						merge__(sorted_array, length, sub_array, Size);
						length = length + Size;
					}
					MPI_Isend(end_array, Size + 1, MPI_INT, i, 20, SplitWorld,&request);
					
				}
				int m;
				for (int i = 0; i < ended_task.size(); i++)
				{
					m = ended_task[0];
					//cout << m;
					qsort(task_data[m], Size, sizeof(int), compare);
					merge__(sorted_array, length, task_data[m], Size);
					length = length + Size;
					ended_task.erase(remove(ended_task.begin(), ended_task.end(), task_data[m][Size]), ended_task.end());//删除已经完成的任务
				}
			}
			else
			{
				MPI_Recv(sub_array, Size + 1, MPI_INT, MPI_ANY_SOURCE, 0, SplitWorld, &status);
				ended_task.erase(remove(ended_task.begin(), ended_task.end(), sub_array[Size]), ended_task.end());//删除已经完成的任务
				merge__(sorted_array, length, sub_array, Size);
				length = length + Size;


				int m = task[0];
				MPI_Isend(task_data[m], Size + 1, MPI_INT, status.MPI_SOURCE, 20, SplitWorld,&request);
				task.erase(remove(task.begin(), task.end(), task_data[m][Size]), task.end());//删除已经发送的任务
				//process.push_back(status.MPI_SOURCE);
				//unfinished_task.push_back(task_data[m][Size]);
			}
		}
	}
	if (row_rank != 0)
	{
		while (1) {
			//for (int k = 0; k < Size + 1; k++)
			//	cout << sub_array[k] << " ";
			//cout << "world " << world_rank << " row " << row_rank << endl;

			//paixu
			qsort(sub_array, Size, sizeof(int), compare);
			MPI_Send(sub_array, Size + 1, MPI_INT, 0, 0, SplitWorld);
			MPI_Recv(sub_array, Size + 1, MPI_INT, 0, 20, SplitWorld, &status);
			if (sub_array[Size] == -1)
				break;
			//for (int k = 0; k < Size + 1; k++)
			//	cout << sub_array[k] << " ";
			//cout << world_rank << endl;
		}
	}

	if (world_rank != 0&&row_rank==0)
	{
		MPI_Send(sorted_array, length, MPI_INT, 0, 30, MPI_COMM_WORLD);
	}
	if (world_rank == 0)
	{
		int temp[TOTAL_SIZE * 2];
		int num;
		MPI_Probe(MPI_ANY_SOURCE, 30, MPI_COMM_WORLD, &status);
		MPI_Get_count(&status, MPI_INT, &num);
		MPI_Recv(temp, num, MPI_INT, status.MPI_SOURCE, 30, MPI_COMM_WORLD, &status);
		merge__(temp, length, sorted_array, num);
		length = length + num;
		ofstream ofs;
		ofs.open("sorted_array.txt", ios::out);
		for (int i = 0; i < length; i++)
		{
			ofs << temp[i] << " ";
		}
		cout << endl << length;
		cout<<"over";
		MPI_Abort(MPI_COMM_WORLD, 110);
	}

	MPI_Finalize();
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Linux虚拟机中配置多节点MPI,需要进行以下步骤: 1. 安装MPI软件包:在每个节点上安装MPI软件包,例如OpenMPIMPICH。 2. 配置网络:确保所有节点都可以相互通信,可以使用ping命令测试。 3. 配置SSH:在每个节点上配置SSH,以便可以在节点之间进行无密码登录。 4. 配置MPI环境变量:在每个节点上设置MPI环境变量,例如PATH和LD_LIBRARY_PATH。 5. 编写MPI程序:编写MPI程序并将其复制到每个节点上。 6. 运行MPI程序:使用mpirun命令在多个节点上运行MPI程序,例如: mpirun -np 4 -hostfile hostfile ./my_mpi_program 其中,-np指定进程数,-hostfile指定节点列表文件,./my_mpi_program指定要运行的MPI程序。 以上是在Linux虚拟机中配置多节点MPI的基本步骤,具体操作可能会因MPI软件包和虚拟机环境而有所不同。 ### 回答2: 要在Linux虚拟机中配置多节点MPI,需要在每个节点上安装相应的MPI软件,如OpenMPIMPICH。首先,需要确保每个节点都可以相互通信,这可以通过设置节点之间的网络连接来实现。此外,还需要在每个节点上设置节点名称和IP地址,以便其他节点可以找到它们。 一旦节点都准备好了,就可以开始配置MPI。首先,需要创建一个运行MPI作业的主机文件。此文件必须包括所有节点的名称和IP地址。这可以通过手动编辑主机文件来完成,也可以使用MPI软件自带的工具来生成。 然后,需要设置MPI环境变量,以便MPI程序可以正确地在多个节点上运行。这包括设置MPI的路径、运行时库和其他相关选项。这些环境变量可以通过编辑.bashrc文件或使用MPI软件提供的配置工具来设置。 最后,可以编写MPI程序并在虚拟机中运行。要确保能够正确地在多个节点上运行,需要使用MPI库提供的函数来实现进程间通信和同步。 总之,在Linux虚拟机中配置多节点MPI需要做很多准备工作,但一旦完成,就可以在多个节点上轻松地运行并行程序。 ### 回答3: MPI(Message Passing Interface)是一种通用的消息传递标准,通常用于编写并行计算程序。在 Linux 虚拟机中配置多节点 MPI 需要进行如下步骤: 1. 配置虚拟机网络 多节点 MPI 通常需要虚拟机之间能够互相通信,因此需要在虚拟机中配置网络。可以选择使用虚拟机自带的网络配置,也可以选择使用桥接网络、NAT 网络或者 Host-Only 网络。具体配置方式可以参考相应虚拟机软件的文档。 2. 安装 MPI 在每个节点上都需要安装 MPI。可以选择 OpenMPIMPICH 等开源 MPI 实现。安装方式可以参考相应 MPI 实现的官方文档。 3. 配置 ssh 公钥认证 MPI 需要在节点之间进行通信,为了方便认证,可以在每个节点上都配置 ssh 公钥认证。具体步骤如下: - 在每个节点上生成 SSH 密钥: ```sh ssh-keygen ``` - 将生成的公钥复制到其他节点上: ```sh ssh-copy-id <username>@<remote-host> ``` - 确认在每个节点上都可以 ssh 到其他节点: ```sh ssh <username>@<remote-host> ``` 4. 配置 hosts 文件 MPI 需要知道每个节点的 IP 地址和主机名,因此需要在每个节点上都配置 hosts 文件。可以将每个节点的 IP 地址和主机名映射到 hosts 文件中。具体配置方式可以参考相应操作系统的文档。 5. 运行 MPI 程序 最后需要在一个节点上启动 MPI 程序,其他节点将连接到该节点上。可以使用类似以下的命令启动 MPI 程序: ```sh mpiexec -n <num_processes> -hostfile <hostfile> <executable> ``` 其中,`-n` 参数指定进程数,`-hostfile` 参数指定节点列表,`<executable>` 参数指定要运行的可执行文件。可以参考相应 MPI 实现的文档了解更多参数和选项。 综上所述,配置多节点 MPI 需要进行网络配置、MPI 安装、ssh 公钥认证、hosts 文件配置和 MPI 程序运行等步骤。需要注意的是,MPI 的配置和运行比较复杂,如果遇到问题可以查看相应的文档或者寻求专业人士的帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值