This kind of parallelism is based on different functional blocks in your application. The idea is simple: The application is split into separate processing units, that communicate with a fixed number other units in such a way that the output of one part serves as the input of another part. Thus we can visualize such a system as a set of nodes that are connected by pipes in which data only flow in one direction.
A good example is a compiler. Such a compiler may consist of a scanner, a parser and a code-generator. The output of the scanner is the input of the parser. The output of the parser is the input of the code-generator. And the output of the codegenerator is written to the disk.
Each of these parts may be placed on a different processor.
Features:
Problems: