-
Notifications
You must be signed in to change notification settings - Fork 1
/
hw1.cc
154 lines (115 loc) · 4.27 KB
/
hw1.cc
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include <cstdio>
#include <mpi.h>
#include <math.h>
#include <stdlib.h>
#include <algorithm>
#include <time.h>
int merge(float *data, int data_length, float *remote, int remote_length, float *all){
int i, j=0;
for (int i = 0; i < data_length; i++){
all[i] = data[i];
j++;
}
for (int i=0; i < remote_length; i++){
all[j] = remote[i];
j++;
}
std::sort(all, all+data_length+remote_length);
return 0;
}
void MPI_Odd_Even_Sort(int size, int localn, int mod, float *data, int sendrank, int recvrank, MPI_Comm comm){
int rank;
float *remote = (float*) malloc(sizeof(float)*localn);
float *all = (float*) malloc(sizeof(float)*(localn*2+mod));
const int mergetag = 1;
const int sortedtag = 2;
MPI_Comm_rank(comm, &rank);
//printf("go!\n");
//如果現在的rank是送的rank 那他就要負責送跟收到時候已經排序好的
if(rank==sendrank){
MPI_Send(data, localn, MPI_FLOAT, recvrank, mergetag, MPI_COMM_WORLD);
MPI_Recv(data, localn, MPI_FLOAT, recvrank, sortedtag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}
else{
MPI_Recv(remote, localn, MPI_FLOAT, sendrank, mergetag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
if(rank!=size-1)
merge(data, localn, remote, localn, all);
else
merge(data, localn+mod, remote, localn, all);
MPI_Send(&(all[0]), localn, MPI_FLOAT, sendrank, sortedtag, MPI_COMM_WORLD);
if(rank==size-1)
for(int i=localn; i<localn*2+mod;i++)
data[i-localn] = all[i];
else{
for(int i=localn; i<localn*2;i++)
data[i-localn] = all[i];
}
}
}
int main(int argc, char** argv) {
MPI_Init(&argc,&argv);
int rank, size;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Status status;
MPI_File f, out;
int n = atoi(argv[1]);
MPI_File_open(MPI_COMM_WORLD, argv[2], MPI_MODE_RDONLY, MPI_INFO_NULL, &f);
MPI_File_open(MPI_COMM_WORLD, argv[3], MPI_MODE_CREATE|MPI_MODE_WRONLY, MPI_INFO_NULL, &out);
//all_time = tt2.tv_nsec - tt1.tv_nsec;
//printf("consumes %ld ms!\n", (tt2.tv_nsec - tt1.tv_nsec)/1000000);
int partition = n/size;
int mod = n%size;
if(rank==size-1)
partition+=mod;
float *data = (float*) malloc(sizeof(float)*partition);
if(rank==size-1)
partition-=mod;
//read file
if(rank!=size-1)
MPI_File_read_at(f, sizeof(float)*partition*rank, data, partition, MPI_FLOAT, MPI_STATUS_IGNORE);
else
MPI_File_read_at(f, sizeof(float)*partition*rank, data, partition+mod, MPI_FLOAT, MPI_STATUS_IGNORE);
//struct timespec tt1, tt2;
//clock_gettime(CLOCK_REALTIME, &tt1);
//local先做qsort
if(rank!=size-1)
std::sort(data, data+partition);
else
std::sort(data, data+partition+mod);
int i;
//odd-even sort
for(i=0;i<=size;i++){
if((i+rank)%2==0){//phase和rank同質 同為奇數 同為偶數 phase奇數 就奇數做 phase偶數就偶數做
if(rank<size-1){
MPI_Odd_Even_Sort(size, partition, mod, data, rank, rank+1, MPI_COMM_WORLD);
}
}
else if(rank>0){ //和當前phase不同質
MPI_Odd_Even_Sort(size, partition, mod, data, rank-1, rank, MPI_COMM_WORLD);
}
}
//clock_gettime(CLOCK_REALTIME, &tt2);
//printf("consumes %ld ms!\n", (tt2.tv_nsec - tt1.tv_nsec)/1000000);
//一個一個rank寫入檔案
if(rank!=size-1){
MPI_File_write_at(out, sizeof(float)*partition*rank, data, partition, MPI_FLOAT, MPI_STATUS_IGNORE);
}
else{
MPI_File_write_at(out, sizeof(float)*partition*rank, data, partition+mod, MPI_FLOAT, MPI_STATUS_IGNORE);
}
//檢查有沒有錯
/*
float *result = (float*) malloc(sizeof(float)*n);
MPI_Gather(data, n / size, MPI_FLOAT, result, n / size, MPI_FLOAT, 0, MPI_COMM_WORLD);
if (rank == 0){
for (int j=0; j<n-1; j++){
printf("%f ",result[j]);
}
printf("%f\n", result[n-1]);
}*/
MPI_File_close(&f);
MPI_File_close(&out);
return MPI_SUCCESS;
MPI_Finalize();
}