#include
#include
#include //有记时的函数
#include
#include //printf的定义
#include //动态分配内存的
#include
#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;
}