schrum2 / MM-NEAT

Modular Multiobjective (Hyper) Neuro-Evolution of Augmenting Topologies + MAP-Elites: Java code for evolving intelligent agents in Ms. Pac-Man, Tetris, and more, as well as code for Procedural Content Generation in Mario, Zelda, Minecraft, and more!
http://people.southwestern.edu/~schrum2/re/mm-neat.php
Other
50 stars 20 forks source link

Parallelism in MAP Elites #777

Closed schrum2 closed 2 years ago

schrum2 commented 2 years ago

Perhaps before trying #774 there are some other parts of the code that need to support parallelism first. The parameter "parallelMAPElitesInitialize" is false by default and we just made sure that it cannot be used in conjunction with Minecraft, since it would result in multiple shapes being generated at the same location at the same time. In order for "parallelMAPElitesInitialize" being true to be possible without errors, we need to make sure that every shape that is generated gets to reserve a spot in which to generate.

In MinecraftLonerShapeTask we can set up a reservation system. In the constructor for MinecraftLonerShapeTask call MinecraftShapeTask.getShapeCorners with a certain size indicating the number of simultaneous evaluations allowed (this can be a new command line parameter "parallelMinecraftSlots"). Save these corners in a global instance variable in MinecraftLonerShapeTask. Then, whenever oneEval gets called, the code has to first request an available corner, reserve it so nothing else can generate there, generate and evaluate the shape, and then return the corner to the pool of available corners before finishing.

To handle the reservations, I think we want to use a queue. Specifically, use a BlockingQueue: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html . Fill it with the corners in the constructor. Whenever oneEval executes, it requests a corner from the queue. If it gets one, it can evaluate the shape right away. If the queue is empty, then the thread blocks and waits for corners to be available. Make sure to put corners back in the queue once evaluation is complete.

schrum2 commented 2 years ago

@MuellMark and @alejmedinajr can work on this together AFTER @MuellMark finished issue #771

MuellMark commented 2 years ago

We added in a blocking queue, which was filled in the constructor, and holds all of the possible coordinates for shape generation. Then, before evaluating a shape, a coordinate is chosen from the queue and is used to generate and evaluate the shape. Once the shape has done both of those, the coordinate is returned to the queue. Because it has blocking, whenever the queue is empty, the code waits for another coordinate to be added back in. We also did testing with it, and it runs with parallelism, multiple shapes generate at a time.