-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.c
153 lines (120 loc) · 4.57 KB
/
main.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
141
142
143
144
145
146
147
148
149
150
151
152
153
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
void Usage(char*);
void readFile(FILE *fp, int *array);
void prefixSum(int *array);
void childSum(int *array, int startIndex, int chunkSize, int *prefixSums, int *flags, int steps, int identifier);
void calculatePrefixSum(int *input, int *output, int step, int startIndex, int endIndex);
uint16_t numElements;
uint16_t numCores;
int *array;
int main(int argc, char** argv) {
if(argc != 5) {
Usage(argv[0]);
}
FILE *inputp;
FILE *outputp;
numElements = atoi(argv[1]);
numCores = atoi(argv[2]);
if (numElements <= 0 || numCores <= 0) {
fprintf(stderr, "Number of elements or cores less than 0.");
exit(EXIT_FAILURE);
}
if (numCores > numElements) {
fprintf(stderr, "Error: Number of cores defined (%d) greater than number of elements (%d)\n", numCores, numElements);
exit(EXIT_FAILURE);
}
inputp = fopen(argv[3], "r");
outputp = fopen(argv[4], "w");
if (inputp == NULL || outputp == NULL) {
perror("open failed");
exit(EXIT_FAILURE);
}
array = mmap(NULL, numElements * sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
readFile(inputp, array);
fclose(inputp);
prefixSum(array);
for(int i = 0; i < numElements; i++) {
fprintf(outputp, "%d ", array[i]);
}
munmap(array, numElements * sizeof(int));
fclose(outputp);
return EXIT_SUCCESS;
}
void readFile(FILE *fp, int *array) {
int numRead = 0;
while (numRead < numElements && fscanf(fp, "%d", &array[numRead]) == 1) {
numRead++;
}
if (numRead != numElements) {
fprintf(stderr, "Error: Number of elements defined (%d) not equal to number of elements found (%d)\n", numElements, numRead);
numElements = numRead;
if (numCores > numElements) {
fprintf(stderr, "Error: Number of cores defined (%d) greater than number of elements (%d)\n", numCores, numElements);
exit(EXIT_FAILURE);
}
}
}
void calculatePrefixSum(int *input, int *output, int step, int startIndex, int endIndex) {
for (int j = startIndex; j < endIndex; j++) {
output[j] = input[j] + ((j >= step) ? output[j - step] : 0);
}
}
void prefixSum(int *array) {
int numSteps = (int)log2(numElements);
int chunkSize = numElements/numCores;
pid_t pid_array[numCores];
int* prefixSums = mmap(NULL, numElements * sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
int *flags = mmap(NULL, numCores * sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
memset(prefixSums, 0, numElements * sizeof(int));
memset(flags, 0, numCores * sizeof(int));
for(int i = 0; i < numCores; i++) {
pid_t pid = fork();
pid_array[i] = pid;
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
} else if(pid == 0) {
int startIndex = i * chunkSize;
childSum(array, startIndex, chunkSize, prefixSums, flags, numSteps, i);
exit(EXIT_SUCCESS);
}
}
int status;
for(int i = 0; i < numCores; i++) {
waitpid(pid_array[i], &status, 0);
}
munmap(prefixSums, numElements * sizeof(int));
munmap(flags, numCores * sizeof(int));
}
void childSum(int *array, int startIndex, int chunkSize, int *prefixSums, int *flags, int steps, int identifier) {
int endIndex = (identifier == numCores - 1) ? numElements : startIndex + chunkSize;
for(int step = 1, prefixSteps = 1; step < steps; step++, prefixSteps *= 2) {
calculatePrefixSum(array, prefixSums, prefixSteps, startIndex, endIndex);
// oldest child rewrites input array to be the output array.
if (identifier == 0) {
for (int i = 1; i < numCores; i++) {
while (flags[i] < step) {} // Wait for other children to complete current step.
}
for (int i = 0; i < numElements; i++) {
array[i] = prefixSums[i];
}
flags[identifier] = step; // oldest child is complete with everything.
}
else {
flags[identifier] = step; // update barrier to signal completion of step[step].
while (flags[0] < step); // wait for oldest to rewrite arrays.
} //proceed to next step.
}
}
void Usage(char* s) {
fprintf(stderr, "Usage: %s num_elements num_cores input_file output_file", s);
exit(EXIT_FAILURE);
}