-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmpi_image_processing_v1.0.c
140 lines (112 loc) · 3.17 KB
/
mpi_image_processing_v1.0.c
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
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include "pgmio/pgmio.h"
#define P 4
#define NUM_ITER 1000
int main(int argc, char *argv[]) {
// MPI variables
MPI_Comm comm;
MPI_Status status;
int size, rank, root = 0, next, prev;
// Other variables
char *file_name;
int M, N, MP, NP;
int i, j, iter;
file_name = "edge192x128.pgm";
pgmsize(file_name, &M, &N);
MP = M/P;
NP = N;
float master_buffer[M][N];
float buffer[MP][NP];
float old[MP+2][NP+2];
float new[MP+2][NP+2];
float edge[MP+2][NP+2];
// Initialise MPI and compute number of processes and local rank
comm = MPI_COMM_WORLD;
MPI_Init(&argc, &argv);
MPI_Comm_size(comm, &size);
MPI_Comm_rank(comm, &rank);
// Check if number of processes is correct
if (P != size) {
if (rank == root) {
printf("ERROR: P = %d, size = %d.\n", P, size);
}
MPI_Finalize();
exit(-1);
}
// Set neighbours' ranks
next = rank + 1;
prev = rank - 1;
if (next >= size) {
next = MPI_PROC_NULL;
}
if (prev < 0) {
prev = MPI_PROC_NULL;
}
// With master process, read the image data into master buffer
if (rank == root) {
printf("Processing %d x %d image on %d processes\n", M, N, P);
printf("Number of iterations = %d\n", NUM_ITER);
printf("Reading <%s>\n", file_name);
pgmread(file_name, master_buffer, M, N);
}
// Split the master buffer data up amongst processes
MPI_Scatter(master_buffer, MP*NP, MPI_FLOAT,
buffer, MP*NP, MPI_FLOAT,
root, comm);
// Copy buffer data into edge adding a 1 pixel padding
for (i=1; i<=MP; ++i) {
for (j=1; j<=NP; ++j) {
edge[i][j] = buffer[i-1][j-1];
}
}
// Initialize old values with 255.0 (white)
for (i=0; i<MP+2; ++i) {
for (j=0; j<NP+2; ++j) {
old[i][j] = 255.0;
}
}
// Main loop
for (iter=0; iter<NUM_ITER; ++iter) {
// Do halo swaps
MPI_Sendrecv(&old[MP][1], NP, MPI_FLOAT, next, 1,
&old[0][1], NP, MPI_FLOAT, prev, 1,
comm, &status);
MPI_Sendrecv(&old[1][1], NP, MPI_FLOAT, prev, 2,
&old[MP+1][1], NP, MPI_FLOAT, next, 2,
comm, &status);
// Calculate the new value
for (i=1; i<=MP; ++i) {
for (j=1; j<=NP; ++j) {
new[i][j] = 0.25 * (old[i-1][j] + old[i+1][j] +
old[i][j-1] + old[i][j+1] - edge[i][j]);
}
}
// Update the old value with the new value
for (i=1; i<=MP; ++i) {
for (j=1; j<=NP; ++j) {
old[i][j] = new[i][j];
}
}
}
// Copy data back to buffer
for (i=0; i<MP; ++i) {
for (j=0; j<NP; ++j) {
buffer[i][j] = old[i+1][j+1];
}
}
// Gather all the data from the buffers back to master buffer
MPI_Gather(buffer, MP*NP, MPI_FLOAT,
master_buffer, MP*NP, MPI_FLOAT,
root, comm);
// With master process, write the result image
if (rank == root) {
file_name="result192x128.pgm";
printf("Writing <%s>\n", file_name);
pgmwrite(file_name, master_buffer, M, N);
}
// Finalize the MPI environment
MPI_Finalize();
return 0;
}