MPI程序实现

#include <iostream> 
#include <mpi.h> 
#include <time.h>      //有记时的函数
#include <stdlib.h>
#include <stdio.h>     //printf的定义
#include <malloc.h>      //动态分配内存的
#include <fstream>
#define TOTAL_SIZE 1000       //宏定义。C语言不方便改数组大小,因为定义数组大小必须是常量。这里设需要排序的数组长度为1000
#define size TOTAL_SIZE/process_num     //size是每个进程分配的数字的size。TOTAL_SIZE/process_num相当于总数长度除以进程数
using namespace std;
double endwtime;
double startwtime;


void bubblingSort(int arr[], int n) {           //冒泡排序
	int i, j, temp;
	// 每次将一个元素送到末尾,n个元素,执行n次
	for (i = 0; i < n; ++i) {
		// 之前的循环已经将i个元素送到末尾,不需要再次比较,故减去,因为跟后一个元素比较,为了避免溢出,故减一
		for (j = 0; j < n - i - 1; ++j) {
			// 如果当前的元素比后一个元素小,就交换
			if (arr[j] > arr[j + 1]) {
				temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
	//printf("no use?");
}


	
// 归并排序中的并
void MergeSort(int arr[], int start, int end, int s)
{	
	
	int temp[1000];
	if (start >= end)		
		return;	
	int mid = end - s;	

	// 合并两个有序序列	
	int length = 0; // 表示辅助空间有多少个元素
	int i_start = start;
	int i_end = mid;
	int j_start = mid + 1;
	int j_end = end;
	while (i_start <= i_end && j_start <= j_end)	
	{		
		if (arr[i_start] < arr[j_start])
		{			
			temp[length] = arr[i_start];
			length++;			
			i_start++;		
		}		
		else		
		{			
			temp[length] = arr[j_start];
			length++;		
			j_start++;		
		}	
	}	
	while (i_start <= i_end) //还有剩的
	{	
		temp[length] = arr[i_start];
		i_start++;		
		length++;	
	}	
	while (j_start <= j_end)	
	{		
		temp[length] = arr[j_start];
		j_start++;
		length++;			
	}	
	// 把辅助空间的数据放到原空间	
	for (int i = 0; i < length; i++)	
	{		
		arr[start + i] = temp[i];
	}
}



int main(int argc, char* argv[])
{

	int    namelen;
	char   processor_name[MPI_MAX_PROCESSOR_NAME];



	//int RankID;          //用来保存各个进程的编号
	int original_array[TOTAL_SIZE], sorted_array[TOTAL_SIZE];     //original_array[TOTAL_SIZE]用来保存需要排序的原始数组,sorted_array[TOTAL_SIZE]是排序后的数组
	int c;
	srand(time(NULL));         //time(NULL)获取当前时间,然后当作初始种子。所以运行时间点不同,种子就不同
	int world_rank;           //用来保存各个进程的编号
	int process_num;             //保存进程总数的
	string path = "D:\\clouddata\\datacatch.txt";
	string path2 = "D:\\clouddata\\result.txt";
	MPI_Init(&argc, &argv);             //取运行时给的参数。例如mpiexec -n 4 jjj.exe中的-n和4
	MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);            //把所有进程都安排到默认群MPI_COMM_WORLD里,并且每个进程都被分配了一个进程号(0,1,2,3)。
	MPI_Comm_size(MPI_COMM_WORLD, &process_num);            //探测该群里进程的数量,即4个进程,process_num=4。(mpiexec -n 4 jjj.exe中的4即为进程数)
	//上面三句话每次照抄就行

	MPI_Get_processor_name(processor_name, &namelen);



	startwtime = MPI_Wtime();
	//下面是重点
	if (world_rank == 0)    //0号进程来分配任务
	{

		ifstream infile;
		infile.open(path, ios::in);
		if (!infile.is_open())
		{
			cout << "read error" << endl;
			return 0;
		}
		//将数据文件数据存入数组
		//输入数组
		for (int i = 0; i < 1000; i++)
		{
			infile >> original_array[i];
		}
		infile.close();
		//输出数组
		printf("This is the unsorted array: ");
		for (int i = 0; i < 1000; i++)
		{
			cout << original_array[i] << " ";
		}

		

		//for (c = 0; c < TOTAL_SIZE; c++)       //首先随机生成一个数组
		//{
		//	original_array[c] = rand() % TOTAL_SIZE;       //因为随机生成的数都要除以1000求余数,所以最后的生成的随机数组里的数必然是0到999的整数
		//	printf("%d ", original_array[c]);
		//}
		printf("\n");
		printf("\n");
		
		//ofstream f;
		覆盖写入
		//f.open(path, ios::out);
		//for (int ii = 0; ii < TOTAL_SIZE; ii++)
		//{
		//	f << original_array[ii] << " ";
		//}
		//f << endl;
		//f.close();

	}     //if语句执行完,0号进程就得到了原始数组


	int *sub_array = (int *)malloc(size * sizeof(int));   //每个进程都要执行。malloc用于在堆里面分配空间。如果在并行期间声明数组,那么数组占用的内存是不会释放的
														  //这样动态分配内存可以随时取消。这句话要表达的意思是:int sub_array[size]
														   //总的来说就是每个进程定义了一个子数组sub_array[size]
	MPI_Scatter(original_array, size, MPI_INT, sub_array, size, MPI_INT, 0, MPI_COMM_WORLD);     //从原始数组里读size个数到子数组里。
																  //0号进程是源头负责提供数据,同一个群里的所有进程包括0号进程,都要分到size个数。
																  //这样原始数组就切分了

	
	printf("The process %d of %d is on %s\n", world_rank, process_num, processor_name);
	fflush(stdout);
	
    //ctrl+K,ctrl+C 注释多行;ctrl+K,ctrl+U 取消注释多行;
	
	//ofstream f;

	追加写入
	//f.open(path, ios::out | ios::app);
	//for (int ii = 0; ii < TOTAL_SIZE; ii++)
	//{
	//	f << sub_array[ii] << "\t";
	//}
	//f << endl;
	//f.close();


	//for (int ranknum = 0; ranknum < process_num; ranknum++) {
	//	if (world_rank == ranknum) {
	//		int cc;
	//		for (cc = 0; cc < size; cc++)
	//		{
	//			printf("%d ", sub_array[cc]);
	//		}
	//		printf("\n");
	//		
	//		ofstream f;

	//		//追加写入
	//		f.open(path, ios::out | ios::app);
	//		for (int ii = 0; ii < TOTAL_SIZE; ii++)
	//		{
	//			f << sub_array[ii] << "\t";
	//		}
	//		f << endl;
	//		f.close();
	//	}
	//
	//}


	/*ofstream f2;
	f2.open("D:\\clouddata\\datafor" + world_rank, ios::out);
	for (int ii = 0; ii < TOTAL_SIZE; ii++)
	{
		f2 << sub_array[ii] << "\t";
	}
	f2 << endl;
	f2.close();*/



	bubblingSort(sub_array, size);             //每个进程排自己分到的那一块的数据的序
	MPI_Gather(sub_array, size, MPI_INT, sorted_array, size, MPI_INT, 0, MPI_COMM_WORLD);           //把所有子数组收集,放到sorted_array里
																									 //但此时,sorted_array里只是有四段有序数据,整体上还未有序
																									 //可以来一个归并排序里的并部分
	if (world_rank == 0)          //0号进程负责打印sorted_array
	{

		//在这里写最后0号进程的排序
		for (int p = 2; p <= process_num ; p++) 
		{
			MergeSort(sorted_array, 0, p *size - 1, size);   //不是两两归并,而是一直是最前面的跟紧跟着的那一小块合并排序
		}

		endwtime = MPI_Wtime();
		printf("\n");
		printf("\n");
		printf("This is the sorted array: ");
		for (c = 0; c < TOTAL_SIZE; c++)
		{
			printf("%d ", sorted_array[c]);
		}
		printf("\n");
		printf("\n");
		printf("time_use:");
		printf("\ntime=%f\n", endwtime - startwtime);


		ofstream f2;
		//覆盖写入
		f2.open(path2, ios::out);
		for (int ii = 0; ii < TOTAL_SIZE; ii++)
		{
			f2 << sorted_array[ii] << " ";
		}
		f2 << endl;
		f2.close();

	}
	free(sub_array);    //释放临时申请的内存空间
	sub_array = NULL;   //free函数只是释放指针指向的内容,而该指针仍然指向原来指向的地方,此时,指针为野指针,如果此时操作该指针会导致不可预期的错误
	                     //无论如何,保险起见,在使用free函数释放指针指向的空间之后,将指针的值置为NULL
	MPI_Finalize();
	//system("pause");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值