Comment made by: jim.blomo
Spinning up more threads than CPU cores is not a good idea when the work is CPU bound. Currently (1.4) pmap uses an unbounded thread pool, so chunked sequences will create more threads than intended. The least invasive change is to use a fixed sized thread pool (ForkJoinPool being one example). pmap is differentiated from core.reducers by the fact that it is lazy. This implies a one-at-a-time ThreadPool.submit model, instead of the recursive fork/join model. Tradeoffs include:
Enforce look-ahead even on chunked sequences:
- + no threadPool changes
- - working against chunking, which is presumably being used for a reason
Move to a fixed size thread pool:
- + reduce contention for cpu-bound functions on chunked sequences
- - increase total realization time for io-bound functions
Use ForkJoinPool for fixed thread pool (instead of newFixedThreadPool):
- + automatic and dynamic parallelism
- - more complex setup (picking Java 6 vs 7 implementation, sharing pool with core.reducers)
I think using a traditional fixed size thread pool is the right option. Most of the time all of pmap's results will be realized, so I don't think it's worth saving work by being strict about the look-ahead size. This is also the decision map has made. Since we're not using ForkJoin's main strength (recursive work queuing), I don't think it is worth setting it up in clojure.core.
I'll use Agent/pooledExecutor as the fixed size thread.
Let me know if I forgot or misunderstood anything.