Skip to content

Commit fd600c5

Browse files
committed
Initial commit
0 parents  commit fd600c5

File tree

32 files changed

+2196
-0
lines changed

32 files changed

+2196
-0
lines changed

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Auto detect text files and perform LF normalization
2+
* text=auto
480 KB
Binary file not shown.

Homework1_Odd-Even_Sort/Makefile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
TARGETS = hw1
2+
CC = mpicc
3+
CXX = mpicxx
4+
CFLAGS = -O3 -lm
5+
CXXFLAGS = -O3 -lm
6+
7+
.PHONY: all
8+
all: $(TARGETS)
9+
10+
.PHONY: clean
11+
clean:
12+
rm -f $(TARGETS)

Homework1_Odd-Even_Sort/hw1.cc

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
#include <boost/sort/spreadsort/float_sort.hpp>
2+
#include <cstdio>
3+
#include <cstdlib>
4+
#include <mpi.h>
5+
6+
/* merge to array "a" */
7+
int merge_front(float *a, int a_num, float *b, int b_num, float *t)
8+
{
9+
int t_num = 0, check = 0;
10+
float *t_i = t;
11+
while (a_num--)
12+
{
13+
if (!t_num)
14+
{
15+
if (b_num && *a > *b)
16+
{
17+
check = 1;
18+
*t_i++ = *a;
19+
*a = *b++;
20+
++t_num;
21+
--b_num;
22+
}
23+
}
24+
else
25+
{
26+
if (b_num && *b < *t)
27+
{
28+
if (*a > *b)
29+
{
30+
check = 1;
31+
*t_i++ = *a;
32+
*a = *b++;
33+
++t_num;
34+
--b_num;
35+
}
36+
}
37+
else
38+
{
39+
if (*a > *t)
40+
{
41+
check = 1;
42+
*t_i++ = *a;
43+
*a = *t++;
44+
}
45+
}
46+
}
47+
++a;
48+
}
49+
return check;
50+
}
51+
52+
/* merge to array "b" */
53+
int merge_rear(float *a, int a_num, float *b, int b_num, float *t)
54+
{
55+
int t_num = 0, check = 0;
56+
float *t_i = t;
57+
a = a + a_num - 1;
58+
b = b + b_num - 1;
59+
while (b_num--)
60+
{
61+
if (!t_num)
62+
{
63+
if (a_num && *b < *a)
64+
{
65+
check = 1;
66+
*t_i++ = *b;
67+
*b = *a--;
68+
++t_num;
69+
--a_num;
70+
}
71+
}
72+
else
73+
{
74+
if (a_num && *a > *t)
75+
{
76+
if (*b < *a)
77+
{
78+
check = 1;
79+
*t_i++ = *b;
80+
*b = *a--;
81+
++t_num;
82+
--a_num;
83+
}
84+
}
85+
else
86+
{
87+
if (*b < *t)
88+
{
89+
check = 1;
90+
*t_i++ = *b;
91+
*b = *t++;
92+
}
93+
}
94+
}
95+
--b;
96+
}
97+
return check;
98+
}
99+
100+
int main(int argc, char **argv)
101+
{
102+
int rank, size, global_data_n, local_data_n, remain_data_n, trans_next_data_n, trans_before_data_n, local_data_start, last_process_id;
103+
MPI_Group WORLD_GROUP, USED_GROUP;
104+
MPI_Comm USED_COMM = MPI_COMM_WORLD;
105+
MPI_File inputFile, outputFile;
106+
107+
MPI_Init(&argc, &argv);
108+
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
109+
MPI_Comm_size(MPI_COMM_WORLD, &size);
110+
111+
/* handle arbitrary number of processes */
112+
global_data_n = atoi(argv[1]);
113+
if (global_data_n < size)
114+
{
115+
MPI_Comm_group(MPI_COMM_WORLD, &WORLD_GROUP);
116+
int range[1][3] = {{0, global_data_n - 1, 1}};
117+
MPI_Group_range_incl(WORLD_GROUP, 1, range, &USED_GROUP);
118+
MPI_Comm_create(MPI_COMM_WORLD, USED_GROUP, &USED_COMM);
119+
// if task isn't in "USED_GROUP", its "USED_COMM" is "MPI_COMM_NULL".
120+
if (USED_COMM == MPI_COMM_NULL)
121+
{
122+
MPI_Finalize();
123+
return 0;
124+
}
125+
size = global_data_n;
126+
}
127+
last_process_id = size - 1;
128+
129+
/* distribute input data to different process */
130+
local_data_n = global_data_n / size;
131+
remain_data_n = global_data_n % size;
132+
float *recv = new float[local_data_n + 1]; // use to receive
133+
float *temp = new float[local_data_n + 1]; // use to merge
134+
if (rank < remain_data_n)
135+
{
136+
++local_data_n;
137+
local_data_start = rank * local_data_n;
138+
}
139+
else
140+
{
141+
local_data_start = rank * local_data_n + remain_data_n;
142+
}
143+
float *data = new float[local_data_n];
144+
145+
/* calculate how many data change in each phase */
146+
int div = 2;
147+
if (rank + 1 == remain_data_n)
148+
trans_next_data_n = (local_data_n - 1) / div;
149+
else
150+
trans_next_data_n = local_data_n / div;
151+
trans_before_data_n = local_data_n / div;
152+
if (!trans_next_data_n)
153+
trans_next_data_n = 1;
154+
if (!trans_before_data_n)
155+
trans_before_data_n = 1;
156+
float *phase_process_data_offset = data + local_data_n - trans_next_data_n;
157+
158+
/* read data from inputfile */
159+
MPI_File_open(USED_COMM, argv[2], MPI_MODE_RDONLY, MPI_INFO_NULL, &inputFile);
160+
MPI_File_read_at(inputFile, sizeof(float) * local_data_start, data, local_data_n, MPI_FLOAT, MPI_STATUS_IGNORE);
161+
MPI_File_close(&inputFile);
162+
163+
/* execute odd-even sort */
164+
boost::sort::spreadsort::float_sort(data, data + local_data_n);
165+
int even_check = 0, odd_check = 0, check = 0, terminate = 1;
166+
while (terminate)
167+
{
168+
/* even phase */
169+
// if rank is even and isn't last process, it needs to send and receive data with (rank + 1).
170+
if (!(rank & 1) && rank != last_process_id)
171+
{
172+
MPI_Sendrecv(phase_process_data_offset, trans_next_data_n, MPI_FLOAT, rank + 1, 0,
173+
recv, trans_next_data_n, MPI_FLOAT, rank + 1, 0, USED_COMM, MPI_STATUS_IGNORE);
174+
even_check = merge_front(data, local_data_n, recv, trans_next_data_n, temp);
175+
}
176+
// if rank is odd, it needs to send and receive data with (rank - 1).
177+
else if (rank & 1)
178+
{
179+
MPI_Sendrecv(data, trans_before_data_n, MPI_FLOAT, rank - 1, 0,
180+
recv, trans_before_data_n, MPI_FLOAT, rank - 1, 0, USED_COMM, MPI_STATUS_IGNORE);
181+
even_check = merge_rear(recv, trans_before_data_n, data, local_data_n, temp);
182+
}
183+
184+
/* odd phase */
185+
// if rank is odd and isn't last process, it needs to send and receive data with (rank + 1).
186+
if ((rank & 1) && rank != last_process_id)
187+
{
188+
MPI_Sendrecv(phase_process_data_offset, trans_next_data_n, MPI_FLOAT, rank + 1, 0,
189+
recv, trans_next_data_n, MPI_FLOAT, rank + 1, 0, USED_COMM, MPI_STATUS_IGNORE);
190+
odd_check = merge_front(data, local_data_n, recv, trans_next_data_n, temp);
191+
}
192+
// if rank is even and isn't first process, it needs to send and receive data with (rank - 1).
193+
else if (!(rank & 1) && rank != 0)
194+
{
195+
MPI_Sendrecv(data, trans_before_data_n, MPI_FLOAT, rank - 1, 0,
196+
recv, trans_before_data_n, MPI_FLOAT, rank - 1, 0, USED_COMM, MPI_STATUS_IGNORE);
197+
odd_check = merge_rear(recv, trans_before_data_n, data, local_data_n, temp);
198+
}
199+
check = odd_check | even_check;
200+
MPI_Allreduce(&check, &terminate, 1, MPI_INT, MPI_SUM, USED_COMM);
201+
}
202+
203+
/* write data to outputfile */
204+
MPI_File_open(USED_COMM, argv[3], MPI_MODE_CREATE | MPI_MODE_WRONLY, MPI_INFO_NULL, &outputFile);
205+
MPI_File_write_at(outputFile, sizeof(float) * local_data_start, data, local_data_n, MPI_FLOAT, MPI_STATUS_IGNORE);
206+
MPI_File_close(&outputFile);
207+
208+
delete data, recv;
209+
MPI_Finalize();
210+
return 0;
211+
}

0 commit comments

Comments
 (0)