We have already reviewed some of these patterns earlier in this book. For example, in Chapter 4, Task Parallel Library in Depth, we studied Parallel.Invoke
and Parallel.Foreach,
which actually is an implementation of the
fork/join pattern. In Chapter 6, Using Concurrent Data Structures, we reviewed a Producer/Consumer pattern implementation. However, there is a very important scenario that we have not seen yet. It is called a
parallel pipeline.
Usually a complex parallel computation can be considered as several stages combined into some sort of a pipeline. The latter stage needs the results of the former, and this prevents these stages from running in parallel. However, the calculations inside each stage can be independent, which allows us to parallelize each stage itself. Besides this, we can simultaneously run all the stages, assuming that we can process stage results one by one, so we do not have to wait until each stage computes all the results...