Difference between revisions of "Iced Cakes Pipeline"
Line 65: | Line 65: | ||
{{CodeToImplement|CakePipeline|mixBakeAndIceCakes|pipeline.cake.studio}} | {{CodeToImplement|CakePipeline|mixBakeAndIceCakes|pipeline.cake.studio}} | ||
− | {{Parallel|public static IcedCake[] mixBakeAndIceCakes(Mixer mixer, | + | {{Parallel|public static IcedCake[] mixBakeAndIceCakes(Mixer mixer, Oven oven, Icer icer, int cakeCount)}} |
Design a simple pipeline using Phasers. In order to have a finished cake, you need to first mix the ingredients, then bake the cake, and finally ice it with frosting. Although you only have one tool for each step (one whisk, one oven, and one icing spatula), there's no problem with icing one cake while another is baking in the oven. That's where the parallelism comes in. Answering the above questions should give you all the information you need to set up this method. Remember that this needs to be able work for any number of cakes passed through! | Design a simple pipeline using Phasers. In order to have a finished cake, you need to first mix the ingredients, then bake the cake, and finally ice it with frosting. Although you only have one tool for each step (one whisk, one oven, and one icing spatula), there's no problem with icing one cake while another is baking in the oven. That's where the parallelism comes in. Answering the above questions should give you all the information you need to set up this method. Remember that this needs to be able work for any number of cakes passed through! |
Revision as of 22:24, 17 April 2019
Contents
Motivation
Pipelines can increase throughput when processing a stream of data. We will gain additional experience with Phasers by building a software pipeline.
Backgroud
Code To Use
Cakes
class Mixer
- mix(int cakeIndex)
class Baker
- bake(int cakeIndex, MixedIngredients mixedIngredients)
- inUse()
- numberAlreadyBaked()
class Icer
- ice(int cakeIndex, BakedCake bakedCake)
Looping
Our reference page's parallel loop section
Phasers
Our reference page's phasers section
class Phaser (Guide to the Java Phaser)
- register
- arrive
- awaitAdvance use via PhaserUtils.awaitAdvanceForPhase(phaser, phase)
If you are on or past the phase you want to await, then calling phaser.awaitAdvance()
directly is fine. If you might be on a prior phase, then invoke PhaserUtils.awaitAdvanceForPhase(phaser, phase)
. If in doubt, invoking awaitAdvanceForPhase is safer.
public static int awaitAdvanceForPhase(Phaser phaser, int phase) { return awaitAdvanceForPhase(phaser, phase, () -> Thread.yield()); } public static int awaitAdvanceForPhase(Phaser phaser, int phase, Runnable runnable) { while (true) { int currentPhase = phaser.awaitAdvance(phase); if (currentPhase < 0 || currentPhase > phase) { return currentPhase; } else { if (runnable != null) { runnable.run(); } } } }
The Core Questions
- What are the tasks?
- What is the data?
- Is the data mutable?
- If so, how is it shared?
Here are some other questions that will help lead you down the right road.
- What work does each task need to do?
- What, if anything, does each task depend upon? That is: what does each task have to wait for before it may proceed?
Code To Implement
Required Code
class: | CakePipeline.java | |
methods: | mixBakeAndIceCakes | |
package: | pipeline.cake.studio | |
source folder: | student/src/main/java |
method: public static IcedCake[] mixBakeAndIceCakes(Mixer mixer, Oven oven, Icer icer, int cakeCount)
(parallel implementation required)
Design a simple pipeline using Phasers. In order to have a finished cake, you need to first mix the ingredients, then bake the cake, and finally ice it with frosting. Although you only have one tool for each step (one whisk, one oven, and one icing spatula), there's no problem with icing one cake while another is baking in the oven. That's where the parallelism comes in. Answering the above questions should give you all the information you need to set up this method. Remember that this needs to be able work for any number of cakes passed through!
Note that icer.ice() returns an object of IcedCake. Collect all the 'IcedCake's you make, and return them in an array.
Optional Challenge
class: | MultiOvenCakePipeline.java | |
methods: | mixBakeAndIceCakes | |
package: | pipeline.cake.challenge | |
source folder: | student/src/main/java |
method: public static IcedCake[] mixBakeAndIceCakes(Mixer mixer, List<Oven> ovens, Icer icer, int cakeCount)
(parallel implementation required)
As we've discussed in class, not all steps of the pipeline always take the same amount of time to complete. In this example, baking a cake in the oven usually takes much longer than simply mixing the ingredients or icing the cake. The Baker is the bottleneck on the performance of this pipeline. One way to further improve the process then is to simply add another oven. This time, build a similar pipeline to what you made earlier, but use both of the Bakers passed to you in order to speed things up. Here's a couple things to take note of:
- How have the tasks changed? How does this additional oven affect the number of threads your program will use?
- Assume that the only way to get a second oven is to buy an old, used one. It can't get as hot, so it will need more time to bake a cake. Because of this, it is better to set up your solution such that when a set of ingredients has been mixed, it sends them to any open oven, rather than just alternating between the two ovens.
- Make sure that only one of the two ovens bakes any given cake. Use baker.inUse() and baker.numberAlreadyBaked() to help keep track of which oven has done which cakes.
Testing Your Solution
Visualization
class: | CakePipelineVizApp.java | VIZ |
package: | pipeline.cake.viz | |
source folder: | student/src//java |
The viz below is for the challenge assignment.
Correctness
class: | CakePipelineTestSuite.java | |
package: | pipeline.cake.studio | |
source folder: | testing/src/test/java |
When you are passing the tests and your visualization looks good, demo it to an instructor.