Earlier quoted context omitted.
SIMD has been somewhat of a massive failure in this regard. Unlike threads, most languages seem to ignore its existence and abdicate its usage to the sufficiently complex compiler. I wish there was better author time feedback to the developer on where they're getting such a perf boost. As far as I'm aware there's no popular linting or blue squiggle to guide you in the right direction. In games it seems like the popul…
Agreed completely. Most auto-vectorization approaches are hit-miss and you still cannot have big-binaries, where instruction set is decided dynamically, trivially. ISPC comes close, but does come with a learning curve.
Concurrency in Haskell: Fast, Simple, Correct
121–129 of 129 posts
Re: Concurrency in Haskell: Fast, Simple, Correct
#122Earlier quoted context omitted.
>> or some comment like: Rust guarantees that you aren't mutating shared state. > The core type system guarantees that there is no [sharing] while mutating, and no mutation while [sharing]
Not sure what you are pointing out, so let me spell out what I said earlier. 1. You get single-writer multiple reader for free from the type system, without any runtime overhead. 2. For the same reason, the type system does not allow multiple writers. If you want multiple writers, then you are forced to use locks. Once you use locks, the runtime guarantees safety for this case. Either way, you get 100% safety.
> 1. You get single-writer multiple reader for free from the type system, without any runtime overhead.
Take the example from the article which is accepted by the Haskell type system:
writeTBCQueue :: TBCQueue a -> a -> STM ()
writeTBCQueue q v = do
stillOpen
Rust would reject this because of multiple writers.Also, thinking about it more, I'm now very skeptical of Rust even providing 'single-writer multiple-reader'. Is it in fact single-reader-writer xor multiple-reader? In other words, how does it handle a goblin constantly moving money between accounts while a gnome is constantly trying to count the total amount?
goblinBankerThread = forever $ do
seed (amount acctB)
then moveAmount $5 acctA acctB
else moveAmount $5 acctB acctA
gnomeAccountantThread = forever $
atomically $ do
accounts
Yes, Rust is 100% safe because it would reject this code, so it would never run. Not running code also has guaranteed no-overhead!2. For the same reason, the type system does not allow multiple writers. If you want multiple writers, then you are forced to use locks
* Locks are problematic, which is why I chose STM over locks in the first place.
* Locks are in all the languages. Does your comment about 100% safety really apply to all languages ?
Re: Concurrency in Haskell: Fast, Simple, Correct
#123Earlier quoted context omitted.
Not sure what you are pointing out, so let me spell out what I said earlier. 1. You get single-writer multiple reader for free from the type system, without any runtime overhead. 2. For the same reason, the type system does not allow multiple writers. If you want multiple writers, then you are forced to use locks. Once you use locks, the runtime guarantees safety for this case. Either way, you get 100% safety.
You're not adding any new information. I already understand you completely. > 1. You get single-writer multiple reader for free from the type system, without any runtime overhead. Take the example from the article which is accepted by the Haskell type system: writeTBCQueue :: TBCQueue a -> a -> STM () writeTBCQueue q v = do stillOpen Rust would reject this because of multiple writers. Also, thinking about it more, I'…
In your goblin example, I believe the gnomeAccountantThread would have to constantly retry, because the writer (if successful) would have produced a new version of two accounts, which would trip up the reader, forcing it to start again. In general, Haskell's STM is built for short-lived transactions; for longer running transactions or those that touch a lot of objects, you'd need something like multi-versioned objects seen in databases or epochs to get a consistent snapshot. Neither Rust nor Haskell is suited to this example out of the box.
For your second question, you assume axiomatically that locks are problematic. They aren't in Rust (except, see later about deadlocks). Unlike any other language with in-place mutation, Rust will force you to use a mutex in order to share something for read-write (in a multiple writer scenario), otherwise it won't compile. You have to use lock() in order to get access to the underlying object, and once you have that object, the type system makes sure only the owner can mutate it. In C/C++/Java/Go, you don't get this guarantee at all ... it is possible to mistakenly use the object without using a mutex. So, there is not guarantee of safety in the other languages. There is a 100% guarantee in Rust.
---
That said, the problematic part about locks (whether it is mutexes or MVars in Haskell) is deadlocks, which is solved by having a deterministic lock order. In your Haskell example, if acctA and acctB were MVars, you'd do
let (first, second) = if acctA
withMVar second $ \_ -> do
...Re: Concurrency in Haskell: Fast, Simple, Correct
#124Earlier quoted context omitted.
Web servers handling lots of small requests are actually pretty easy to garbage collect to: you just delete all the data at the end of the request. Either you have a specialised GC that works like this, or probably a good general generational GC can pick up on this pattern on its own.
Or you do as Erlang's BEAM VM: each thread has it's own memory area which is GC'ed individually. This means upon request termination, you just terminate the thread and the memory is reclaimed with no need for a GC.
Re: Concurrency in Haskell: Fast, Simple, Correct
#125Earlier quoted context omitted.
Clojure atoms use STM, though. I've been writing Clojure for almost a decade now, it's not that STM isn't great, it's just that immutable data will carry you a very long way - you just don't need coordinated mutation except in very narrow circumstances. In those circumstances STM is great! I have no complaints. But it just doesn't come up very often.
That’s incorrect. Only refs+dosync use stm. https://clojure.org/reference/refs Not atoms. From Hickey’s History of Clojure paper: “ Taking on the design and implementation of an STM was a lot to add atop designing a programming language. In practice, the STM is rarely needed or used. It is quite common for Clojure programs to use only atoms for state, and even then only one or a handful of atoms in an entire program.…
That said, I have never used a ref, nor seen one in use outside of a demo blogpost.
Re: Concurrency in Haskell: Fast, Simple, Correct
#126Earlier quoted context omitted.
There's no time like the present. Feel free to reach out if I can help you along your journey
Not the person you're replying to, but I'll bite: I've written low thousands of lines of Haskell. Similar to mikojan, I love Haskell in theory, but ended up not enjoying it as much in practice. 1. The multitude of string-y types. I end up converting between String, Text, Lazy Text, ByteString, Lazy ByteString, and I forget what else. Each library wants me to pass in a specific string type, and each other library retu…
Re: Concurrency in Haskell: Fast, Simple, Correct
#127Earlier quoted context omitted.
Not the person you're replying to, but I'll bite: I've written low thousands of lines of Haskell. Similar to mikojan, I love Haskell in theory, but ended up not enjoying it as much in practice. 1. The multitude of string-y types. I end up converting between String, Text, Lazy Text, ByteString, Lazy ByteString, and I forget what else. Each library wants me to pass in a specific string type, and each other library retu…
The manual string conversions are annoying. But with https://hackage.haskell.org/package/string-conversions-0.4.0... you just add a `cs` and don't think more about it.
Re: Concurrency in Haskell: Fast, Simple, Correct
#128Earlier quoted context omitted.
That’s incorrect. Only refs+dosync use stm. https://clojure.org/reference/refs Not atoms. From Hickey’s History of Clojure paper: “ Taking on the design and implementation of an STM was a lot to add atop designing a programming language. In practice, the STM is rarely needed or used. It is quite common for Clojure programs to use only atoms for state, and even then only one or a handful of atoms in an entire program.…
Haha, I read The Joy of Clojure way back in 2013 and conflated the different reference types with STM. So thanks for mentioning that, I always thought it weird that you'd need STM for vars and atoms too. That said, I have never used a ref, nor seen one in use outside of a demo blogpost.
Re: Concurrency in Haskell: Fast, Simple, Correct
#129Earlier quoted context omitted.
Coloured functions are a feature - not a bug, Haskell is full of them, and they are exactly what make STM safe in Haskell, but abandonware in other languages which have tried. 2. The way you call a function depends on its color. ` >=` vs `=` 3. You can only call a red function from within another red function. This should sound pretty familiar! You can only call an IO function from within another IO function. STM in…
It is a shame that the people you are answering is being downvoted, I also understand the importance of coloring functions, but look at the examples that person put, python and rust. In those, executing a colored function (at least the async related ones) propagates up to the top of the program, that is a cost that we have to interiorize, but I would be lying if I told you I wouldn't he happy with such behavior. I do…
I'm glad that the fight happens between the developer and the compiler so that it doesn't have to happen between developers on every single pull request.