Parallel ghc --make
I know this has been talked about before and also a bit in the recent GSoC discussion. I would like to know what prevents ghc --make from working in parallel, who worked at that in the past, what their findings were and a general estimation of the difficulty of the problem. Afterwards, I would update http://hackage.haskell.org/trac/ghc/ticket/910 with a short summary of what the current situation is. Thanks to those who know more!
I wrote a ghc-server that starts a persistent process for each cpu. Then a 'ghc' frontend wrapper sticks each job in a queue. It seemed to be working, but timing tests didn't reveal any speed-up. Then I got a faster computer and lost motivation. I didn't investigate very deeply why it didn't speed up as I hoped. It's possible the approach is still valid, but I made some mistake in the implementation. So I can stop writing this little blurb I put it on github: https://github.com/elaforge/ghc-server On Mon, May 13, 2013 at 8:40 PM, Niklas Hambüchen <mail@nh2.me> wrote:
I know this has been talked about before and also a bit in the recent GSoC discussion.
I would like to know what prevents ghc --make from working in parallel, who worked at that in the past, what their findings were and a general estimation of the difficulty of the problem.
Afterwards, I would update http://hackage.haskell.org/trac/ghc/ticket/910 with a short summary of what the current situation is.
Thanks to those who know more!
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
To have a single-process ghc --make -j you first of all need internal thread-safety: GHC internally keeps a number of global caches that need to be made thread-safe: - table of interned strings (this is actually written in C and accessed via FFI) - cache of interface files loaded, these are actually loaded lazily using unsafeInterleaveIO magic (yuck) - cache of packages descriptions (I think) - the NameCache: a cache of string -> magic number. This is used to implement fast comparisons between symbols. The magic numbers are generated non-deterministically (more unsafeInterleaveIO) so you need to keep this cache around. - HomeModules: These are the modules that have been compiled in this --make run. The NameCache is used when loading interface files and also by the Parser. Making these things thread-safe basically involves updating these caches via atomicModifyIORef instead of just modifyIORef. I made those changes a few years ago, but at least one of them was rolled-back. I forgot the details, but I think it was one use of unsafePerformIO that caused the issues. unsafePerformIO needs to traverse the stack to look for thunks that are potentially evaluated by multiple threads. If you have a deep stack that can be expensive. SimonM since added stack chunks which should reduce the overhead of this. Could be worthwhile re-evaluating the patch. To have a multi-process ghc --make you don't need thread-safety. However, without sharing the caches -- in particular the interface file caches -- the time to read data from the disk may outweigh any advantages from parallel execution. Evan's approach of using a long-running worker process avoids issues with reloading the most of the caches for each module, but it probably couldn't take advantage of the HomeModule cache. It would be interesting to see if that was the issues. Then, it would be interesting if the disk access or the serialisation overhead is the issue; if it's the former, some clever use of mmap could help. HTH, / Thomas On 13 May 2013 17:35, Evan Laforge <qdunkan@gmail.com> wrote:
I wrote a ghc-server that starts a persistent process for each cpu. Then a 'ghc' frontend wrapper sticks each job in a queue. It seemed to be working, but timing tests didn't reveal any speed-up. Then I got a faster computer and lost motivation. I didn't investigate very deeply why it didn't speed up as I hoped. It's possible the approach is still valid, but I made some mistake in the implementation.
So I can stop writing this little blurb I put it on github:
https://github.com/elaforge/ghc-server
On Mon, May 13, 2013 at 8:40 PM, Niklas Hambüchen <mail@nh2.me> wrote:
I know this has been talked about before and also a bit in the recent GSoC discussion.
I would like to know what prevents ghc --make from working in parallel, who worked at that in the past, what their findings were and a general estimation of the difficulty of the problem.
Afterwards, I would update http://hackage.haskell.org/trac/ghc/ticket/910 with a short summary of what the current situation is.
Thanks to those who know more!
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Hello Thomas, thanks for your detailed answer.
Could be worthwhile re-evaluating the patch.
Does your patch still apply somewhat cleanly? And does it address all the caches in your list already or only some subset of them?
To have a multi-process ghc --make you don't need thread-safety. However, without sharing the caches -- in particular the interface file caches -- the time to read data from the disk may outweigh any advantages from parallel execution.
That might be a big step already - I've never seen a project where I'd care about parallel compilation that is not totally CPU-bound.
It's also useful to note that the disk cache might do a surprisingly good job at caching those .hi files for you. That, and a lot of people (like me!) use SSDs, where the parallel compilation takes the vast majority of time. I'd be really excited to see parallel ghc --make. By the way, totally unrelated, but why does cabal support -j when cabal-dev doesn't? - Clark On Wednesday, May 15, 2013, Niklas Hambüchen wrote:
Hello Thomas,
thanks for your detailed answer.
Could be worthwhile re-evaluating the patch.
Does your patch still apply somewhat cleanly? And does it address all the caches in your list already or only some subset of them?
To have a multi-process ghc --make you don't need thread-safety. However, without sharing the caches -- in particular the interface file caches -- the time to read data from the disk may outweigh any advantages from parallel execution.
That might be a big step already - I've never seen a project where I'd care about parallel compilation that is not totally CPU-bound.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org <javascript:;> http://www.haskell.org/mailman/listinfo/haskell-cafe
On Wed, May 15, 2013 at 6:36 PM, Clark Gaebel <cgaebel@uwaterloo.ca> wrote:
It's also useful to note that the disk cache might do a surprisingly good job at caching those .hi files for you. That, and a lot of people (like me!) use SSDs, where the parallel compilation takes the vast majority of time.
I'd be really excited to see parallel ghc --make.
By the way, totally unrelated, but why does cabal support -j when cabal-dev doesn't?
It helps to understand that they are made by different people and cabal-dev is "just" a wrapper around cabal. Out of curiosity I just tried 'cabal-dev install -j' and as far as I can tell right now it does support -j. Perhaps you need to install newer versions of cabal or cabal-dev? $ cabal-dev --version cabal-dev 0.9.1 built with Cabal 1.16.0 Jason
Oh! That works quite nicely. It's not supported for install-deps. I assumed that it just wasn't implemented. I should open a ticket. Thanks! - Clark On Wednesday, May 15, 2013, Clark Gaebel wrote:
It's also useful to note that the disk cache might do a surprisingly good job at caching those .hi files for you. That, and a lot of people (like me!) use SSDs, where the parallel compilation takes the vast majority of time.
I'd be really excited to see parallel ghc --make.
By the way, totally unrelated, but why does cabal support -j when cabal-dev doesn't?
- Clark
On Wednesday, May 15, 2013, Niklas Hambüchen wrote:
Hello Thomas,
thanks for your detailed answer.
Could be worthwhile re-evaluating the patch.
Does your patch still apply somewhat cleanly? And does it address all the caches in your list already or only some subset of them?
To have a multi-process ghc --make you don't need thread-safety. However, without sharing the caches -- in particular the interface file caches -- the time to read data from the disk may outweigh any advantages from parallel execution.
That might be a big step already - I've never seen a project where I'd care about parallel compilation that is not totally CPU-bound.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (5)
-
Clark Gaebel -
Evan Laforge -
Jason Dagit -
Niklas Hambüchen -
Thomas Schilling