-
Notifications
You must be signed in to change notification settings - Fork 1
/
parallel.c
188 lines (166 loc) · 5.97 KB
/
parallel.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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#include "assistFunctions.h"
#include "conflict.h"
#include "mutate.h"
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <time.h>
#include "mpi.h"
void slave(int N, int *board1, int *board2, int** newBoards)
{
// Mutation algorithms
crossoverRandomSplit(N, board1, board2, 0.15, newBoards);
newBoards[2] = board1;
newBoards[3] = board2;
mutateMaxConflict(N, newBoards[2]);
mutateMaxConflict(N, newBoards[3]);
}
int main(int argc, char **argv)
{
// Initialize MPI and MPI variables
int rank, numranks;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &numranks);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
int startTime, endTime, totalTime;
startTime = MPI_Wtime();
// Sets the seed of the random function
srand(time(NULL));
// Number of boards to solve for
int numBoards = 4;
// Size of each board
int N = 64;
// Factor for genetic diversity
double genDivFactor = 0.3;
// Arrays allocated on the master (rank 0)
int** boards = (int **)malloc(numBoards * N * sizeof(int));
int *conflictScores = (int *)malloc(numBoards * sizeof(int));
int *bestBoard = (int *)malloc(N * sizeof(int));
// Arrays allocated on the slaves (all other ranks)
int *board1 = (int *)malloc(N * sizeof(int));
int *board2 = (int *)malloc(N * sizeof(int));
int **newBoards = (int **)malloc(4 * N * sizeof(int));
int conflictScoreSum = 0;
int bestConflictScore = INT_MAX;
// Allocate the remaining space for the double pointer arrays
for (int i = 0; i < numBoards; i++) {
boards[i] = (int *)malloc(N * sizeof(int));
}
for (int i = 0; i < 4; i++) {
newBoards[i] = (int *)malloc(N * sizeof(int));
}
// Master block
if (rank == 0)
{
// Populates the boards and calculates the conflict scores
for (int i = 0; i < numBoards; i++)
{
fillRandom(N, boards[i]);
conflictScores[i] = computeConflictScore(N, boards[i]);
conflictScoreSum += conflictScores[i];
printf("Board %d | Conflict Score: %d\n", i, conflictScores[i]);
// printBoard(N, boards[i]);
}
}
// Send the sum of conflict score to every rank
MPI_Bcast(&conflictScoreSum, 1, MPI_INT, 0, MPI_COMM_WORLD);
int iter = 0;
// Loops while our boards are still in conflict
while (conflictScoreSum != 0)
{
// Master block
if (rank == 0)
{
// Random index variables
int i1, i2;
// Board send block
for (int i = 1; i < numranks; i++)
{
i1 = rand() % numBoards;
do
{
i2 = rand() % numBoards;
} while (i2 == i1);
// Picks 2 of the boards randomly to send to the slaves
MPI_Send(boards[i1], N, MPI_INT, i, 0, MPI_COMM_WORLD);
MPI_Send(boards[i2], N, MPI_INT, i, 1, MPI_COMM_WORLD);
}
// Board receive block
for (int i = 1; i < numranks; i++)
{
MPI_Recv(bestBoard, N, MPI_INT, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
MPI_Recv(&bestConflictScore, 1, MPI_INT, i, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
// Attempts to replace the current boards with better boards
for (int j = 0; j < numBoards; j++)
{
if (bestConflictScore < conflictScores[j])
{
boards[j] = bestBoard;
conflictScoreSum -= conflictScores[j];
conflictScoreSum += bestConflictScore;
conflictScores[j] = bestConflictScore;
}
}
}
// Mutate one of the boards randomly depending on out genetic diversity factor
if (randDouble() < genDivFactor)
{
mutateTrulyRandom(N, boards[rand() % numBoards]);
}
// Prints out update every 1,000 runs
if (iter % 1000 == 0)
{
printf("Conflict Scores: ");
for (int i = 0; i < numBoards; i++)
{
printf("%d ", conflictScores[i]);
}
printf("\n");
}
}
// Slave block
else
{
// Receive the 2 boards from master
MPI_Recv(board1, N, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
MPI_Recv(board2, N, MPI_INT, 0, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
// Apply the mutations
slave(N, board1, board2, newBoards);
int c;
// Loop over the new boards we get
for (int i = 0; i < 4; i++)
{
c = computeConflictScore(N, newBoards[i]);
// Finds the board with the lowest conflict score
if (c < bestConflictScore)
{
bestConflictScore = c;
bestBoard = newBoards[i];
}
}
// Return the best board with it's conflict score
MPI_Send(bestBoard, N, MPI_INT, 0, 0, MPI_COMM_WORLD);
MPI_Send(&bestConflictScore, 1, MPI_INT, 0, 1, MPI_COMM_WORLD);
}
// Update the conflict score value every rank has
MPI_Bcast(&conflictScoreSum, 1, MPI_INT, 0, MPI_COMM_WORLD);
iter++;
}
// printf("Rank %d roger roger\n", rank);
// Synchronizes all the ranks
MPI_Barrier(MPI_COMM_WORLD);
endTime = MPI_Wtime();
totalTime = endTime - startTime;
// Prints out the solution
if (rank == 0) {
for (int i = 0; i < numBoards; i++)
{
printf("Board %d | Conflict Score: %d\n", i, conflictScores[i]);
// printBoard(N, boards[i]);
}
printf("Solved in %d iterations in %d seconds\n", iter, totalTime);
}
// End the program
MPI_Finalize();
exit(0);
}