基于 MPI 的快速排序算法的实现

完整代码:

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <cmath>
#include <mpi.h>

using namespace std;

struct Pair {
	int left;
	int right;
};

const int MAX_PROCESS = 128;
const int NUM = 8000;
const int MAX = 1000000;
const int MIN = 0;

int arr[NUM];
int temp[NUM];

Pair pairs[MAX_PROCESS];

int counter = -1;

void swap(int A[], int i, int j) {
	int temp = A[i];
	A[i] = A[j];
	A[j] = temp;
}

int findpivot(int i, int j) {
	return (i + j) / 2;
}

int partition(int A[], int l, int r, int pivot) {
	do {
		while (A[++l] < pivot);
		while ((r != 0 && (A[--r] > pivot)));
		swap(A, l, r);
	} while (l < r);
	swap(A, l, r);
	return l;
}

void quicksort(int A[], int i, int j, int currentdepth, int targetdepth) {
	if (currentdepth == targetdepth) {
		int rank = ++counter;
		pairs[rank].left = i;
		pairs[rank].right = j;
		cout << pairs[rank].left << " and " << pairs[rank].right << " : rank " << rank << endl;
		return;
	}
	if (j <= i) return;
	int pivotindex = findpivot(i, j);
	swap(A, pivotindex, j);
	int k = partition(A, i - 1, j, A[j]);
	swap(A, k, j);
	quicksort(A, i, k - 1, currentdepth + 1, targetdepth);
	quicksort(A, k + 1, j, currentdepth + 1, targetdepth);
}

void quicksort(int A[], int i, int j) {
	if (j <= i) return;
	int pivotindex = findpivot(i, j);
	swap(A, pivotindex, j);
	int k = partition(A, i - 1, j, A[j]);
	swap(A, k, j);
	quicksort(A, i, k - 1);
	quicksort(A, k + 1, j);
}

int main(int argc, char* argv[]) {
	MPI_Init(&argc, &argv);
	int RANK, SIZE, targetdepth, left, right, REAL_SIZE;

	MPI_Comm_rank(MPI_COMM_WORLD, &RANK);
	MPI_Comm_size(MPI_COMM_WORLD, &SIZE);
	REAL_SIZE = SIZE;
	if (RANK == 0) {
		cout << "Quick sort start..." << endl;
		cout << "Generate random data... ";

		memset(arr, 0, NUM * sizeof(arr[0]));
		srand(time(NULL));
		for (int i = 0; i < NUM; i++) {
			arr[i] = MIN + rand() % (MAX - MIN);
		}
		cout << "Done." << endl;
		targetdepth = log2(SIZE);
		cout << "Rank: " << RANK << endl;
		cout << "Sorting... ";
		quicksort(arr, 0, NUM - 1, 0, targetdepth);
		REAL_SIZE = counter + 1;
		for (int i = 1; i < SIZE; i++) {
			int left = pairs[i].left;
			int right = pairs[i].right;
			MPI_Send(&REAL_SIZE, 1, MPI_INT, i, 99, MPI_COMM_WORLD);
			MPI_Send(&left, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
			MPI_Send(&right, 1, MPI_INT, i, 1, MPI_COMM_WORLD);
			MPI_Send(&arr, NUM, MPI_INT, i, 2, MPI_COMM_WORLD);
		}

		left = pairs[0].left;
		right = pairs[0].right;
		quicksort(arr, left, right);
		cout << "Process " << RANK <<" done."<< endl;
	}

	for (int process = 1; process < REAL_SIZE; process++) {
		if (RANK == process) {
			MPI_Status status;
			MPI_Recv(&REAL_SIZE, 1, MPI_INT, 0, 99, MPI_COMM_WORLD, &status);
			MPI_Recv(&left, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
			MPI_Recv(&right, 1, MPI_INT, 0, 1, MPI_COMM_WORLD, &status);
			MPI_Recv(&arr, NUM, MPI_INT, 0, 2, MPI_COMM_WORLD, &status);
			if (process < REAL_SIZE) {
				quicksort(arr, left, right);
				MPI_Send(&arr, NUM, MPI_INT, 0, 0, MPI_COMM_WORLD);
				cout << "Process " << RANK << " done." << endl;
			}
		}
	}

	if (RANK == 0) {
		for (int i = 1; i < REAL_SIZE; i++) {
			//cout << "Master is ready to receive data from process " << i << endl;
			MPI_Status status;
			MPI_Recv(&temp, NUM, MPI_INT, i, 0, MPI_COMM_WORLD, &status);
			for (int j = pairs[i].left; j <= pairs[i].right; j++) {
				arr[j] = temp[j];
			}
			//cout << "Master has combined data from process " << i << endl;
		}
		cout << "Done." << endl;
		cout << "Result:" << endl;
		int counter = 1;
		int row = 20;

		for (int i = 0; i < NUM; i++, counter++) {
			cout << arr[i] << " ";
			if (arr[i] < arr[max(i - 1, 0)]) {
				cerr << "Invalid! " << arr[i] << " > "<< arr[max(i - 1, 0)] <<" i is "<< i << endl;
			}
			if (counter % row == 0) cout << endl;
		}
	}
	MPI_Finalize();

}

运行截图:

posted @ 2020-01-20 22:57  JustSong  阅读(2056)  评论(0编辑  收藏  举报