Smoking fast Haskell code using GHC's new LLVM codegen
donsbot.wordpress.com
donsbot.wordpress.com
It took me years to realize what a killer project LLVM actually is. I bet this won't be the last success story for LLVM, either.
This provides a lot of encouragement to start some of my rainy-day projects -- my goal is to have a Haskell library with a proof of correctness that can outperform equivalent C. That day draws ever closer.
Isn't that a bit like saying that it "can outperform equivalent assembly"?
And why can you not prove the equivalent C correct? After all, you're doing that proof by hand either way. A Haskell compiler will only help you prove that your program is well-typed. If you're mutating buffers then you're in a monad like IO or ST and the the compiler will throw it's hands up and tell you that correctness is entirely your problem.
In practice, the overhead of supporting Haskell's other features means it's still generally slower than most popular compiled languages, though not by much. I have much higher expectations, however, for improvement in Haskell optimizers than I do for nontrivial static analysis for impure languages becoming viable.
Well, LLVM can do this, actually. If you treat C like a programming language instead of portable assembly, you can do interesting things with it.
This is why I am always confused when people say "functional programming is slow" -- current C implementations are very close to being as fast as theoretically possible, where as current FP implementations are nowhere near that (there are many optimization opportunities that are currently unexplored or unimplemented). And even with only a few optimizations, many FP implementations (GHC, OCaml, SBCL) are almost as fast as C already!
Not quite. To quote the master:
<pengvado> gcc fails to optimize it because gcc has always sucked at arrays
<pengvado> that's *the* benefit of fortran
The benefit of FORTRAN is due to array and aliasing issues in C, not really whole-program optimization. Isn't that a bit like saying that it "can outperform equivalent assembly"?
No; as shown in the link, this work allows idiomatic Haskell to outperform idiomatic C. Obviously it's possible to write C which is a direct translation of the generated assembly, but such code would be nearly unmaintainable, and certainly very difficult to reason about. And why can you not prove the equivalent C correct?
Proving the correctness of C code is possible, but (in my experience) significantly more difficult than for Haskell. After all, you're doing that proof by hand either way. A Haskell compiler will only help you prove that your program is well-typed. If you're mutating buffers then you're in a monad like IO or ST and the the compiler will throw it's hands up and tell you that correctness is entirely your problem.
I don't mean that the compiler will automatically generate a proof for me, but that authoring a proof will be possible in practice -- as opposed to C, where it's possible in theory but nobody actually can.I'm a bit confused about why you think operating within a monad causes problems for proving correctness; to my knowledge, verifying code which uses monads is no more difficult than code using any other data types.
Interesting that you mention this. I know when I am writing C, I usually "malloc" dynamic data structures, whereas in Haskell, I usually "alloca" dynamic data structures (when talking to C libraries, obviously). Same end result, but alloca is actually faster, which makes allocation-heavy libraries faster when used from Haskell. (I guess I should use alloca in C, too. But I've never seen this anywhere.)
I noticed that this was especially helpful in a library I recently used that never allocated any of its own memory; it was always the responsibility of the caller. Haskell idioms worked much better than C idioms here.
I'm a bit confused about why you think operating within a monad causes problems for proving correctness; to my knowledge, verifying code which uses monads is no more difficult than code using any other data types.
Wait, are you saying that calling a function called "(>>=)" is no different than calling any other function? Shocking. :)
Personally, I have found C libraries a lot easier to use from Haskell. A few "newtype" and Storabe instances later, you get a library that is impossible to make crash. You write the rest of your program in terms of that (in pure Haskell), and you are pretty much guaranteed enough safety to not segfault.
(I've specifically worked with a third-party financial analytics library that is quite crashy if you call certain functions in certain order. I used the type system to prevent myself from doing that, and now I can write complex problems that don't crash. Great success.)
Go - http://golang.org/ - doesn't use LLVM because they claim it is "large and slow". Search for llvm on http://golang.org/doc/go_faq.html
Wondering if they have done the test where the llvm flag has recompiled ghc.