Memory management is a standard problem for programs written in C and C++. It is important to free memory when it is no longer needed, because otherwise you will run out. Unfortunately, it is complex to keep track of which memory is no longer needed. The symptoms of memory management problems are typically either running out of memory, or obscure and difficult to debug memory corruption.
Any program can do memory management successfully with a disciplined approach. However, the problems are pervasive enough that there is a standard solution for them: garbage collection. Java, for example, always uses garbage collection, and therefore has no memory management problem. The same is true of Lisp, and of most interpreted languages. Garbage collection decreases performance and increases memory usage. Still, many people find it to be a valuable technique.
Is there any comparable approach which will work for parallel programming? The problem in parallel programming is race conditions. The standard solution is mutexes and condition variables, and variants thereof. These can work with a disciplined approach. However, in practice, the problems are pervasive. Is there something like garbage collection which can provide a complete solution?
There has been a lot of recent work on transactional memory. This is a technique which tracks all reads and writes in a locked section, and unrolls the writes if two different threads turn out to be in the section simultaneously. I don’t personally see the point. Transactional memory still requires the programmer to place locks correctly. The advantage it provides is that it can provide good performance even with coarse-grained locks. However, the good performance only comes if lock contention is low. When lock contention is high, the bookkeeping overhead of transactional memory is high. And the coarser the locks, the higher the lock contention. So it doesn’t seem like a significant change to the current systems.
What we need is some way for multiple threads of control to share access to data structures in memory without requiring locks. And we need some way to guarantee data structure invariants, so that while the structure is being updated by one thread other threads do not see an inconsistent state. It’s difficult to see how we can maintain invariants without annotations from the programmer.
The goal I am setting is a high one: to be able to write code in a relatively straightforward manner, and to permit that code to use multiple threads of control. I don’t see a solution.
A fallback position might be the one I discussed earlier: require the separate threads to operate in separate address spaces, and provide library calls to move data back and forth. This is a more difficult programming model, so it doesn’t seem like the perfect solution. But I don’t see a good one.
Leave a Reply
You must be logged in to post a comment.