There are two due dates for this assignment. First, you need to set up your assignment git repository on or before March 31th so your instructor can test and make sure everything is working as expected. Second, you then need to complete the assignment instructions and then add/commit/push your files to your git repository on or before 11:59pm on Thursday April 8. Your instructor highly recommends committing early and often.
In a genetic algorithm, a population of candidate solutions (called individuals, creatures, or phenotypes) to an optimization problem is evolved toward better solutions. Each candidate solution has a set of properties (its chromosomes or genotype) which can be mutated and altered; traditionally, solutions are represented in binary as strings of 0s and 1s, but other encodings are also possible.
The evolution usually starts from a population of randomly generated individuals, and is an iterative process, with the population in each iteration called a generation. In each generation, the fitness of every individual in the population is evaluated; the fitness is usually the value of the objective function in the optimization problem being solved. The more fit individuals are stochastically selected from the current population, and each individual's genome is modified (recombined and possibly randomly mutated) to form a new generation. The new generation of candidate solutions is then used in the next iteration of the algorithm. Commonly, the algorithm terminates when either a maximum number of generations has been produced, or a satisfactory fitness level has been reached for the population.
A typical genetic algorithm requires:
- genetic representation of the solution domain,
- fitness function to evaluate the solution domain.
A standard representation of each candidate solution is as an array of bits. The main property that makes these genetic representations convenient is that their parts are easily aligned due to their fixed size, which facilitates simple crossover operations. Variable length representations may also be used, but crossover implementation is more complex in this case.
Once the genetic representation and the fitness function are defined, a GA proceeds to initialize a population of solutions and then to improve it through repetitive application of the mutation, crossover and selection operators.
In this assignment, you are going to modify and improve the processing speed of a "REVERSE Conway's Game of Life" program using MPI.
The Reverse Conway's Game of life is when we have a target state which we want to reach using the forward Conway game of life rules (see HW3). The reverse problem is much harder because the math itself is not reversable. to solve this problem we will "guess" a state, forward propigate the game to the end state and then compare the target end state to our guess end state.
Consider a $50 \times 50$ Conway's GOL target. All possible states are $2^{(50 \times 50)}$ or
2**(50*50)
375828023454801203683362418972386504867736551759258677056523839782231681498337708535732725752658844333702457749526057760309227891351617765651907310968780236464694043316236562146724416478591131832593729111221580180531749232777515579969899075142213969117994877343802049421624954402214529390781647563339535024772584901607666862982567918622849636160208877365834950163790188523026247440507390382032188892386109905869706753143243921198482212075444022433366554786856559389689585638126582377224037721702239991441466026185752651502936472280911018500320375496336749951569521541850441747925844066295279671872605285792552660130702047998218334749356321677469529682551765858267502715894007887727250070780350262952377214028842297486263597879792176338220932619489509376
This is a big number and it is impossible to find a solution in a reasonable amount of time using brute force. We are going to try to solve this problem using Genetic algorithms.
✅ DO THIS: On or before March 31th Fork the instructor's repository, set the permissions, clone your fork to your HPCC account and make sure you can compile and run the software.
make clean
make
make test
Note: if for any reason you can not figure out git, please review the git tutorial and go to your instructors office hours. If you would like, you may "tar zip" (tgz) a backup of your repository to your instructor on the by 11:59pm on Thursday April 8.
By the end of this assignment, you should be able to:
For this assignment you will do the following parts:
✅ DO THIS: Benchmark the code provided using the "random" setting by using the following command:
SEED=1
time ./revROC cmse2.txt $SEED
✅ DO THIS: Write a script (called timecheck.sh
to run the code 10 times with 10 different input seeds. Note the average time and the best result Fitness in your report. Save the best solution as serial_best.txt
.
NOTE: this will take a while. Feel free to make the script a SLURM submission script and run it on the HPCC. Just make sure you give it plenty of time (4 hours?) to finish.
✅ DO THIS: Commit the timecheck.sh
and serial_best.txt
files to your repository.
We should be able to run this code on different cores using different random seeds. Basically create lots of workers that are each searching for the best answer at the same time (and not talking to each other). When they all are done we can see which of the workers "wins".
✅ DO THIS: Write a job script (called job_array.sb
) to run the program on 50 CPUs using a simple job array (see quiz1). Give each job the following:
✅ DO THIS: Review the output for all 50 jobs and note the best result Fitness in your report. Save the best solution as pp_best.txt
.
✅ DO THIS: Commit the job_array.sb
and pp_best.txt
file to your repository.
To make things a little simpler, I would like to split up the MPI problem into two steps. This first step we are just going to use MPI to "Consolidate" all of the answers. Generally speaking the results will not be any different from the Pleasantly parallel runs but this is the "easier" step so I think it should go first.
✅ DO THIS: Make a copy of reverseGOL.c
called reverseGOL-mpi.c
. Modify the makefile to compile this program using mpicc (keep the compile for the baseline reverseGOL.c
).
✅ DO THIS: Modify the end of reverseGOL-mpi.c
to have workers share their best result with the lead worker (rank ==0) and then have the lead worker print out the overall best result to the screen. This will involve the following steps:
MPI_Send
commands.MPI_RECV
commands. If the worker's fitness is better than the current best, replace the current best with the worker's solution otherwise discard that worker's solution. After the loop print out the final result. ✅ DO THIS: Write a job script (called mpi_job.sb
) to run the program on 50 CPUs using MPI (mpirun). Give the job similar runtime to step 2, 100gb of memory (2gb per core). Run this on the cmse2.txt input target.
✅ DO THIS: Review the output and note the best result Fitness in your report. Save the best solution as mpi_basic_best.txt
.
✅ DO THIS: Commit the mpi_job.sb
, reverseGOL-mpi.c
and mpi_basic_best.txt
files to your repository. Also commit any changes to your makefile.
Both step 2 and 3 are basically pleasantly parallel (although step 3 saves us a lot of time reviewing files). The problem with these Pleasantly parallel codes is that there is no cross-communication between the search workers. one of the strengths of genetic search is that it can chase down good solutions by modifying okay ones.
In this step we are going to modify the code using MPI so that each search program can "talk" to each other and share their best results so far. This way the workers can all chase down solutions together.
There are a lot of correct ways to do this. We are going to try something simple as a starting point. After each generation and before the mutation we will have each worker share its best result so far with it's neighbor (using round robin). If the neighbor's fitness is better than our own current best, we will replace our current best with our neighbors and set our second best sbest
to what was our current best.
✅ DO THIS: Modify revConway_MPI
to do the following:
✅ DO THIS: Rerun our updated mpi program using the mpi-job.sh
script. Review the output and note the best result Fitness in your report. Save the best solution as mpi_best.txt
.
✅ DO THIS: Commit the mpi__best.txt
file to your repository. Also commit any changes to your makefile.
✅ DO THIS: Write a report describing what you learned (There is a template in the instructor's git repository). The report should be written in either Markdown or Jupyter notebooks.
Make a graph of the final fitness values to see what method "won" explain the graphs in your report text with a focus on any odd results you may see. Conclude with a general lessons learned.
✅ DO THIS: Prepare your files for the instructor. I recommend having two versions of the code; original serial version, MPI version. You can also have a third version for the intermediate MPI code if you did not get the file code to work. Update the provided Makefile
to build all executables.
When you are done, add/commit and push all of your changes to your forked git repository. Your instructor will use the following command to compile and test your code on the HPCC:
make clean
make
make test
sbatch job_array.sh
sbatch mpi_job.sh
Submit your tgz file to the course Desire2Learn page in the HW1 assignment.
Written by Dr. Dirk Colbry, Michigan State University
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.