4 ms·
Hey, since this is likely to attract Haskell programmers: how fast is Haskell these days for a programmer intent on writing optimized code? I am particularly i
by ykonstant 2y ago
Hey, since this is likely to attract Haskell programmers: how fast is Haskell these days for a programmer intent on writing optimized code? I am particularly interested in its performance for numerical crunching like matrix operations and other stuff that benefit from SIMD.
- epgui 2y agoI’m not the best person to answer this question, but AFAIK it’s very very fast (in the rough vicinity of C). But also memory-hungry.
- freilanzer 2y agoI'm pretty sure highly optimised code won't be elegant Haskell code though.
- rebeccaskinner 2y agoHighly optimized code tends to be inelegant in any language. That said, you can get really good performance from very elegant looking “normal” Haskell too. The big challenge with performance in Haskell is that the differences between optimized and unoptimized code can be pretty subtle if you’re not used to thinking about Haskell performance.
- epgui 2y agoLet me clarify: naive/beautiful/effortless Haskell code tends to be highly performant, although that is not always true. I believe it is much easier to write fast Haskell code than to write fast C/C++ code.
- Iceland_jack 2y agoI met Sam Derbyshire at ZuriHac who told me all the difficult architectural work had been done for SIMD support. + https://gitlab.haskell.org/ghc/ghc/-/issues/7741 https://gitlab.haskell.org/ghc/ghc/-/issues/7741 It might make it for GHC 9.12 (for 128 bit vectors only, and mostly floating-point operations unless other people come in and contribute). The patch is at: + https://gitlab.haskell.org/ghc/ghc/-/merge_requests/12860 https://gitlab.haskell.org/ghc/ghc/-/merge_requests/12860
- ykonstant 2y agoThanks for the info!
- mrkeen 2y agoI like Haskell performance for every-day backend/web and CLI stuff. But I drop down into Rust when I'm writing something performance-focused. That said, Haskell's no slouch. Here's a small program to count the 1-bits in a file. main :: IO () main = do content <- getArgs >>= \[a] -> unsafeMMapVector a Nothing print (vectorPopCount content) vectorPopCount :: V.Vector Word64 -> Int vectorPopCount = V.foldl' (+) 0 . V.map popCount When you compile with -msse4.2, it will correctly use the hardware popcount instruction, and crunches through a 1GB input file in 0m0,090s. Rounding to the nearest MB, it uses 0 heap. (For the curious, if I compile without -msse4.2 it runs in 0m0,293s). I haven't tried crunching matrices, but I would start by checking out repa, accelerate, or massiv. https://hackage.haskell.org/package/repa https://hackage.haskell.org/package/accelerate https://hackage.haskell.org/package/massiv
- ykonstant 2y agoThe lack of heap allocations is great! Thanks for the pointers.
- lazamar 2y agoHaskell's speed can be competitive with systems languages but keep in mind that its killer feature is ease of abstraction. The idea is that it is simple to assemble multiple parts into a coherent, well organised program. Which is important for the entirety of the program, no just the tight loop. So, with the nice FFI Haskell has, you can always drop down to languages without a GC for inherently imperative optimisations. Then you wrap that into a library with nice types and you can now leverage that raw power anywhere in your Haskell code where the types will match. I worked at Meta in a high performance Haskell application and that's what we did. Wrote beautiful, large, fast Haskell programs which in some specialised parts had C++ building blocks. 99% of the time was spent on Haskell land composing things into more and more useful applications.
- wyager 2y agoThe reality is that for any language, including C, compiler optimized code will never be as fast as hand optimized code in libraries like BLAS. So at some level, the choice of host language doesn't matter very much, because you're going to be outsourcing all of the computation anyway if you're really serious about speed. This is the same reason all the AI stuff, possibly the single largest consumer of compute in the world, gets away with being written in python except for the low level compute libraries. To answer your question directly, The GHC compiler is very good. High level code will perform very well, and for most realistic applications, performance bottlenecks are architectural, not e.g. the use of single width versus SIMD, and the "architectural asymptotics" of haskell are very favorable. I think GHC has/is getting SIMD support but that's not what I would focus on when evaluating perf. I wouldn't write a matrix multiplication algorithm in Haskell, but I also wouldn't write one in rust or C if I was serious about speed. Many focus on number crunching as a performance metric, but almost no one is ever actually bottlenecked on that, and if they are it doesn't really matter what high level language they're using.
- GrantMoyer 2y ago> The reality is that for any language, including C, compiler optimized code will never be as fast as hand optimized code That's not strictly true; sometimes a C compiler can optimize away my whole program: https://godbolt.org/z/oG5nfGE6z https://godbolt.org/z/oG5nfGE6z
- wyager 2y agoYou're doing extremely simple constant arithmetic here. GHC can optimize this type of thing away to nothing as well. Are we talking about contrived examples or real numerical bottlenecks?
- Twisol 2y agoI think it was a joke about compilers removing code by reasoning about undefined behavior.
- ReleaseCandidat 2y agoIt's doable but harder than in imperative languages and the resulting code is _really_ ugly. See the thread of the 1BRC https://discourse.haskell.org/t/one-billion-row-challenge-in-hs/8946 https://discourse.haskell.org/t/one-billion-row-challenge-in... with example code at (I hope that's the right Gist) https://gist.github.com/AndrasKovacs/e156ae66b8c28b1b84abe6b483ea20ec https://gist.github.com/AndrasKovacs/e156ae66b8c28b1b84abe6b...
- CyberDildonics 2y agoIf you want to write fast stuff that takes advantage of SIMD, you want to use ISPC, which is made for high performance SIMD. Using haskell for this would be like doing surgery with a dull rock, you will never get what you want.
- tkz1312 2y agoHaskell really shines when you want to write high level, declarative code. Performance when using this style is generally fine for CLI / web backend style stuff. It has the tools to write pretty fast low level code, but they’re fairly clunky and if that’s all you want to write it’s probably not going to be the best tool for the job. They’re pretty nice if you have a few focused hotspots you need to optimize. It has pretty nice CPU profiling tools, so finding and optimizing CPU hotspots is fairly pleasant. Tracking down rouge memory leaks (which lazy evaluation makes more likely) on the other hand can be extremely frustrating. If you look at the benchmarks game results [1], the fastest haskell implementations are generally between 2 and 5 times slower than the fastest c versions, and will be written in a highly imperative style. [1]: https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/clang-ghc.html https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
- wredue 2y agoIf you’re writing idiomatic Haskell. Its performance is terrible. If you’re choosing to fight with Haskell, why? Just use something else. To understand why people claim Haskell is “fast”, you need to understand what they mean. What they mean is “if you opted to write C in such a way as you were performing similar amounts of copious and useless data copying, pointer following and stack blowing madness, Haskell will perform that fast”. They are not saying “Haskell is as fast as the fastest idiomatic C implementation”. Another thing you’re going to see a lot of is extremely simple anecdotes, such as counting in a loop, or favourable measure points (they will measure the whole c program, but just the point in Haskell after they’ve flattened data, for example, stating “we just want to compare those parts”).
- epgui 2y agoI think if your runtime performance is terrible with Haskell, either the explanation is that you might be doing something a bit crazy, or that your application is memory-constrained.
- wredue 2y agoUh no. The explanation is that Haskell has terrible performance idioms like “copying shit for no reason all the time”. There’s a reason that the prevailing opinion on language performance within the Haskell community is “thinking about performance of a language is a premature optimization” This, of course, ignores that Haskells poor performance characteristics are actually technical debt, for which all people should be considering off the bat for their project. You cannot simultaneously say “premature” and not also add this to the techdebt column. There comes a time in *all* scaling applications that Haskell will be such a burden, that it’ll be forced to be rewritten.
- epgui 2y agoIt seems we’re in complete polar disagreement. None of the observations you make match mine.
- 2y ago