Piping is bad because multiprocessing has a relatively large overhead. That is why I am a fan of Simon Tatham's (brain damaging) coroutines, that are evolved from Duff's Device (which I also use a lot). Of course, assembler language stack swaps are better than coroutines, but not portable.
The piping is handy for initial testing (small evolutionary changes to existing code). Once it works, it can be refactored into a monolithic loop (perhaps using a state-machine if it gets too complicated). For monolithic loops that contain subfunctions that need to be performed at different rates, I use a DDA (digital differential algorithm) to do rate conversion to decide when to fire various periodic events.
For really slow primitive processors with tiny RAM but big ROM, I do all my timing with a huge jump table, and interleave all my periodic events evenly through it (dithered to prevent too many events firing on the same clock interrupt). I also do deferred non-maskable interrupt processing after saving the critical measurement. You know -- how to squeeze jaw-dropping performance out of tiny resources.