[HN Gopher] PR to Merge Multicore OCaml
___________________________________________________________________
PR to Merge Multicore OCaml
Author : c-cube
Score : 334 points
Date : 2021-12-21 15:17 UTC (7 hours ago)
(HTM) web link (github.com)
(TXT) w3m dump (github.com)
| sadiq wrote:
| As usual, happy to answer any questions.
| Zababa wrote:
| I've searched a bit for this and haven't been able to find a
| good answer. Let's say that I have m tasks that I want to run
| concurrently on n cores, for example handling HTTP requests or
| searching for something in files. I'd also like to not have to
| manage manually how the tasks are going to be distributed.
| Basically, have the same experience as when writing Go code. Is
| there a way to do this in multicore OCaml? I've found the task
| pool in domainslib [1] but I'm not sure if it's what I'm
| looking for.
|
| [1]: https://github.com/ocaml-
| multicore/domainslib/blob/master/li...
| sadiq wrote:
| You could use eio with an event loop per domain and the
| domain manager to distribute work to other domains. The
| restriction at the moment is that the tasks you spin off to
| other domains can't do asynchronous io.
|
| There is work on-going at the moment to bridge or even unify
| eio (concurrency via effects) and domainslib (nested
| parallelism via domains and effects) but it's a few months
| out.
| talex5 wrote:
| To clarify that, there are two systems here:
|
| - domainslib schedules all tasks across all cores (like
| Go).
|
| - eio keeps tasks on the same core (and you can use a
| shared job queue to distribute work between cores if you
| want).
|
| Eio can certainly do async IO on multiple cores.
|
| Moving tasks freely between cores has some major downsides
| - for example every time a Go program wants to access a
| shared value, it needs to take a mutex (and be careful to
| avoid deadlocks). Such races can be very hard to debug.
|
| I suspect that the extra reliability is often worth the
| cost of sometimes having unbalanced workloads between
| cores. We're still investigating how big this effect is.
| When I worked at Docker, we spent a lot of time dealing
| with races in the Go code, even though almost nothing in
| Docker is CPU intensive!
|
| For a group of tasks on a single core, you can be sure that
| e.g. incrementing a counter or scanning an array is an
| atomic operation. Only blocking operations (such as reading
| from a file or socket) can allow something else to run. And
| eio schedules tasks deterministically, so if you test with
| (deterministic) mocks then the trace of your tests is
| deterministic too. Eio's own unit-tests are mostly expect-
| based tests where the test just checks that the trace
| output matches the recorded trace, for example.
|
| The Eio README has more information, plus a getting-started
| guide: https://github.com/ocaml-
| multicore/eio/blob/main/README.md
| Zababa wrote:
| Thank you for the clear explanation!
| vphantom wrote:
| I think libraries like Lwt will be the ones to offer the
| level of abstraction which you're describing. I too would
| like to see the simplicity of goroutines make it into OCaml 5
| ASAP.
| jpf0 wrote:
| A bunch of questions: Is multi-threading happening at the level
| of user-defined functions? How are threads scheduled? What's
| the underlying method or library for enabling multi-threading
| (Cilk, openMP, some LWT library...)? To what extent has this
| level of granularity been tested against other levels of nested
| parallelism (e.g. SIMD or otherwise parallel operators)? Have
| you tested performance by OS, and if so, have you noted any
| necessary OS-level modifications related to thread management?
| Is this part of a broader roadmap for accelerator integration?
| sadiq wrote:
| 1. Domains are the unit of parallelism. A domain is
| essentially an OS thread with a bunch of extra runtime book-
| keeping data. You can use Domain.spawn
| (https://github.com/ocaml-multicore/ocaml-
| multicore/blob/5.00...) to spawn off a new domain which will
| run the supplied function and terminate when it finishes.
| This is heavyweight though, domains are expected to be long-
| running.
|
| 2. Domainslib is the library developed alongside multicore to
| aid users in exploiting parallelism. It supports nested
| parallelism and is pretty highly optimised
| (https://github.com/ocaml-multicore/domainslib/pull/29 for
| some graphs/numbers). The domainslib repo has some good
| examples: https://github.com/ocaml-
| multicore/domainslib/tree/master/te...
|
| 3. We've not tested against other forms of parallelism. There
| isn't anything stopping you exploiting SIMD in addition to
| parallelism from domains.
|
| 4. No, we've not compared performance by OS.
|
| 5. No plans for the multicore team to look at accelerator
| integration at the moment.
| pdimitar wrote:
| Is the previous plan for adding effects in OCaml 5.1 still in
| place?
|
| I am very excited not only for the native parallelism that's
| coming in 5.0 but also about the effect handlers! I am sure
| many others are looking to start creating very interesting
| things with them, e.g. Rust-alike async capabilities or
| Erlang's preemptive green threads / actors runtime.
| sadiq wrote:
| 5.00 (the first release with multicore) will include effects!
|
| More info: https://discuss.ocaml.org/t/multicore-ocaml-
| september-2021-e...
| jasone wrote:
| Yes, but note the absence of syntactic support. Effects
| will be usable for writing libraries and experimentation,
| but routine use won't be very ergonomic until a later
| release.
| simplify wrote:
| Considering the hard part of effects is implementing them
| at the language level, deferring on syntax is a good
| problem to have.
| pdimitar wrote:
| Oh. I haven't followed lately. Thanks a lot for the updated
| info!
|
| Really looking forward to what the community will build
| with OCaml 5.00! IMO it will shoot the language straight
| into the mainstream and I can't wait. OCaml is applicable
| for like 90% what's out there, including as a Python
| replacement. And its syntax is often much terser than Rust
| (although the higher-level typing constructs can be
| confusing to read).
|
| After that, all that's left is a tool like Elixir's mix or
| Rust's cargo and the language is basically not only in the
| 21st century but much farther than _many_ others! Looking
| forward to it.
| rwmj wrote:
| I'm slightly concerned if this means changing C extensions (of
| which we have rather a lot).
|
| We only have a few places that use "naked" pointers, which are
| in any case deprecated, and we should be able to fix those
| easily enough.
|
| Mostly the rest are fairly ordinary extensions that just call C
| functions and use the usual CAMLparam stuff.
|
| We do have a few places that register global roots. And several
| packages that do callbacks from C back to OCaml. We also use
| @@noalloc a lot.
|
| Is there anything else? Since there's so much code, what should
| I be grepping for to find code that might be of concern?
|
| Edit: Some examples of simple stuff:
|
| https://github.com/libguestfs/libguestfs-common/blob/master/...
| https://github.com/libguestfs/libguestfs-common/blob/master/...
| https://github.com/libguestfs/libguestfs-common/blob/master/...
|
| More complex stuff:
|
| https://gitlab.com/nbdkit/nbdkit/-/tree/master/plugins/ocaml
| http://oirase.annexia.org/tmp/ocaml/
| sadiq wrote:
| To echo what avsm said, our intention is to preserve the C
| API. With the exception of naked pointers, if you follow the
| rules around the existing C API then your extensions should
| continue to work in sequential code running on 5.0.
|
| We have a scheduled build and test of every package in opam
| with multicore: http://check.ocamllabs.io:8082/ to try to
| shake out C API incompatibilities and that's proved fruitful.
|
| If you do find things that don't work on 5.0, please let us
| know (and if you can, get it in to opam so we test it
| automatically!).
| avsm wrote:
| You may find the "nnpchecker" configure option in 4.13.0
| useful. This will print a detected use of naked pointers to
| stderr, which can hopefully be triggered by test suites.
|
| Noalloc and registering roots should all be the same, as are
| callbacks (for sequential code, which all existing code will
| be)
| 2wrist wrote:
| Great stuff!!
| VitalyAnkh wrote:
| Oh the PR is so huge. Would this be difficult to review?
| brabel wrote:
| It's probably a final PR from multiple smaller, reviewed ones,
| I would guess.
| sideeffffect wrote:
| I don't know much about OCaml, only Scala and Cats
| Effect/ZIO/Monix, but would appreciate if I could get a gist of
| what Multicore OCaml brings to the table.
|
| Is there somebody who's familiar with both worlds and could
| compare them and explain how Multicore OCaml (and possibly the
| new effect system) work?
|
| Thanks in advance!
| michaelmcmillan wrote:
| Finally a PR worthy of Hacktoberfest.
| gmfawcett wrote:
| The multicore team has done an excellent job of communicating
| their plans and progress over the past few years. Innovative
| research, solid engineering, and a top-notch communications game.
| Whether or not you care about Ocaml, many other SE projects could
| learn a lot from studying this team.
| eatYourFood wrote:
| > could learn a lot from studying this team.
|
| How? Where?
| gmfawcett wrote:
| Fair question! Here's a good place to start, they've been
| doing monthly progress reports here since January 2020:
|
| https://discuss.ocaml.org/tag/multicore-monthly
|
| There have also been presentations, videos, academic papers,
| etc., which should all be documented in the monthly reports.
| dang wrote:
| Past related threads:
|
| _Multicore OCaml: October 2021_ -
| https://news.ycombinator.com/item?id=29238972 - Nov 2021 (12
| comments)
|
| _Effective Concurrency with Algebraic Effects in Multicore
| OCaml_ - https://news.ycombinator.com/item?id=28838099 - Oct 2021
| (59 comments)
|
| _Multicore OCaml: September 2021, effect handlers will be in
| OCaml 5.0_ - https://news.ycombinator.com/item?id=28742033 - Oct
| 2021 (3 comments)
|
| _Multicore OCaml: September 2021 - Effect handlers will be in
| OCaml 5.0_ - https://news.ycombinator.com/item?id=28719088 - Oct
| 2021 (3 comments)
|
| _Adapting the OCaml Ecosystem for Multicore OCaml_ -
| https://news.ycombinator.com/item?id=28440385 - Sept 2021 (1
| comment)
|
| _Adapting the OCaml Ecosystem for Multicore OCaml_ -
| https://news.ycombinator.com/item?id=28373155 - Aug 2021 (21
| comments)
|
| _Multicore OCaml: July 2021_ -
| https://news.ycombinator.com/item?id=28039219 - Aug 2021 (14
| comments)
|
| _Multicore OCaml: May 2021_ -
| https://news.ycombinator.com/item?id=27480678 - June 2021 (27
| comments)
|
| _Multicore OCaml: April 2021_ -
| https://news.ycombinator.com/item?id=27140522 - May 2021 (89
| comments)
|
| _Multicore OCaml: Feb 2021 with new preprint on Effect Handlers_
| - https://news.ycombinator.com/item?id=26424785 - March 2021 (29
| comments)
|
| _Multicore OCaml: October 2020_ -
| https://news.ycombinator.com/item?id=25034538 - Nov 2020 (9
| comments)
|
| _Multicore OCaml: September 2020_ -
| https://news.ycombinator.com/item?id=24719124 - Oct 2020 (43
| comments)
|
| _Parallel Programming in Multicore OCaml_ -
| https://news.ycombinator.com/item?id=23740869 - July 2020 (15
| comments)
|
| _Multicore OCaml: May 2020 update_ -
| https://news.ycombinator.com/item?id=23380370 - June 2020 (17
| comments)
|
| _Multicore OCaml: March 2020 update_ -
| https://news.ycombinator.com/item?id=22727975 - March 2020 (37
| comments)
|
| _Multicore OCaml: Feb 2020 update_ -
| https://news.ycombinator.com/item?id=22443428 - Feb 2020 (80
| comments)
|
| _State of Multicore OCaml [pdf]_ -
| https://news.ycombinator.com/item?id=17416797 - June 2018 (103
| comments)
|
| _OCaml-multicore now at 4.04.2_ -
| https://news.ycombinator.com/item?id=16646181 - March 2018 (4
| comments)
|
| _A deep dive into Multicore OCaml garbage collector_ -
| https://news.ycombinator.com/item?id=14780159 - July 2017 (89
| comments)
|
| _Lock-free programming for the masses_ -
| https://news.ycombinator.com/item?id=11907584 - June 2016 (29
| comments)
|
| _Lock-free programming for the masses_ -
| https://news.ycombinator.com/item?id=11893911 - June 2016 (4
| comments)
|
| _OCaml 4.03 will, "if all goes well", support multicore_ -
| https://news.ycombinator.com/item?id=9582980 - May 2015 (113
| comments)
|
| _Multicore OCaml_ - https://news.ycombinator.com/item?id=8003699
| - July 2014 (1 comment)
| laylomo2 wrote:
| dang
| noncoml wrote:
| I really didn't think I'd see the day.
| [deleted]
| eatonphil wrote:
| Congrats!
| sharmin123 wrote:
| nicolashahn wrote:
| If OCaml gets good tooling and ecosystem I'm totally in. I've
| heard it's close to Rust but GCed and that sounds extremely
| enticing.
| jasone wrote:
| I started using OCaml in 2017, and had a rough start. But since
| then Dune (https://dune.build/) and the now-excellent LSP
| implementation have resolved the biggest issues I had. I
| haven't had such a pleasant development environment since Turbo
| Pascal! (To be fair, IntelliJ was also pretty good other than
| the shortcomings of Java.)
| sideeffffect wrote:
| Since you mentioned using IntelliJ, I can't resist asking the
| question: Have you played with Scala too? If yes, how would
| you compare OCaml to it?
| nestorD wrote:
| Tooling got me from Ocaml to F#, I would recommend it if that
| is a criteria for you.
| devmunchies wrote:
| I definitely will use it as my primary server language on side
| projects after it has a standardized async lib (effect handlers
| and eio). I was also hoping that rust would be my primary lang
| but its a little too verbose with all the "<>" for it to be my
| guilty pleasure. Been dabbling in OCaml since 2018.
| wk_end wrote:
| It's similar to Rust in certain respects, but it feels very
| different in several others.
|
| * There's no ownership tracking. This might be obvious - it
| doesn't need it, it has GC - but is actually kind of
| unfortunate; even in GC'd languages, linearity can be used to
| safely model state machines/typestate or for optimization.
|
| * There's no traits/ad-hoc polymorphism at all.
|
| * There's no impls, though a common pattern with a similar feel
| is to define types inside modules with the actual
| implementation of the type hidden, and provide an interface via
| functions to create or interact with instances of the type.
|
| * It uses exceptions for error handling (when it doesn't use an
| option type) and even as a lightweight control flow mechanism.
| And now there's algebraic effects as well.
|
| * It has an extraordinarily powerful module system, with
| functors (pass modules into other modules to produce new
| modules) and first-class modules (modules that exist as values
| at run-time that can be passed around to functions).
|
| * It has some more advanced type machinery - GADTs, polymorphic
| variants, and a very interesting, powerful, almost completely
| unused object system.
|
| * This bleeds a little into "ecosystem" and a little into "no
| ad-hoc polymorphism" and a little into the oddness of the
| syntax and a little into subjectivity, but in general doing
| really bog-standard imperative stuff in OCaml, while possible,
| tends to feel more awkward than it does in Rust.
| c54 wrote:
| I like OCaml a lot but I agree that it suffers from this
| tooling/ecosystem problem. Even un-fancy languages with good
| tooling are just going to win, at the end of the day. Go is the
| main example of this. Rust also has great tooling that's gotten
| better over time.
|
| I think over time Jane Street will (continue to) open source
| more of its libraries, and hopefully soon will also migrate
| onto Dune (internally they use jenga[0]). This should mean that
| the ecosystem within Jane Street more closely matches the
| external environment and tooling should get better as they push
| patches upstream.
|
| Hopefully.
|
| [0] https://discuss.ocaml.org/t/does-jenga-have-more-features-
| th...
| wk_end wrote:
| I mean, maybe. But Core and Async have been open source for a
| long time, and there's still plenty of people out there using
| Batteries/Containers/Iter/BOS/Lwt.
| jabl wrote:
| Is there an ELI5 writeup somewhere about what's so nice about
| algebraic effects?
|
| I skimmed through some preprint on arxiv, and I got the
| impression that one could implement async/await as well as
| something like green threads if you select a suitable runtime.
| But beyond implementing other concurrency abstractions, why
| should I care?
| classified wrote:
| https://speakerdeck.com/kayceesrk/effect-handlers-in-multico...
| simplify wrote:
| The short answer is, algebraic effects allow you to build your
| own abstractions _like_ async /await. That's extremely
| powerful.
| rackjack wrote:
| Whoa, earlier than I expected (didn't think we'd see the PR
| within the year). Exciting!!
| ijustboughtit wrote:
| Last time (ca. 1 year ago) I tried learning OCaml, I ended up
| reading the beta version of Real World OCaml 2nd Ed. IIRC and for
| some reason all I remember now is that I didn't feel confident
| regarding the learning material.
|
| The RWO-website https://dev.realworldocaml.org claims that the
| 2nd. Ed. has been published in Q4 2021, but I can't find it
| anywhere. Can somebody with experience tell me if RWO 2nd Ed. is
| the way to go?
| avsm wrote:
| (Coauthor of RWO here)
|
| We are just finishing edits of a few chapters (the tooling,
| testing and GADT ones), and then it'll be off to the publishers
| early in the new year. The online one is therefore pretty up to
| date.
|
| There's also a thread on the OCaml forums on this topic with
| more suggestions: https://discuss.ocaml.org/t/how-do-you-stay-
| productive-in-oc...
| keewee7 wrote:
| F# is a ML/OCaml with solid concurrent and parallel programming
| features and has been multiplatform since Microsoft released .Net
| Core 1.0 in 2016.
| klibertp wrote:
| > F# is a ML/OCaml
|
| No. F# is an ML dialect, like OCaml. But, you should be aware
| that the "O" in "OCaml" actually means something. OCaml comes
| with beautiful object system that's prototypal in nature and
| structurally typed integrated into the language. F# on the
| other hand has the object system inherited from .NET, and it's
| simplistic in comparison.
|
| Also, modules and functors.
|
| So, no, F# is not OCaml. If you absolutely need to use .NET,
| and know some ML, you can reach for F#, but its limitations
| will drive you nuts quickly. F# is for C# programmers - they
| have "full power of .NET" still accessible, plus a few nice
| things like HM type inference, immutability by default, and
| maybe computational expressions.
| bmitc wrote:
| I completely disagree that F# is for C# developers. For one,
| C# developers are usually fine sticking with C# and its
| massive ecosystem. F# and .NET more seamlessly run everywhere
| than Ocaml, which last time I tried is a lot of trouble on
| Windows. F# has had multicore support from the beginning and
| hasn't needed a multi-year development process to get there.
|
| I'd like to learn Ocaml (more than just the parts I've
| learned from F# and SML), but F# is by no means a simplistic
| language in terms of what you can accomplish. It's easily one
| of the best designed and most pragmatic languages out there.
| From the syntax I have seen, F# is cleaner than Ocaml.
|
| > F# is an ML dialect, like OCaml
|
| That's kind of splitting hairs. The object system is
| different for obvious reasons. F# clearly started as a port
| of a subset of Ocaml to .NET and was even valid Ocaml code
| for some time in the early days. That's exactly a dialect.
| pbiggar wrote:
| But basically no one uses the object part of OCaml
| pjmlp wrote:
| For various levels of no one.
| rackjack wrote:
| GTK comes to mind
| pjmlp wrote:
| F# is not really for C# programmers, C# programmers just get
| by the F# features that keep being copied into C#.
|
| F# is an ML that is kind of allowed to play on .NET because
| in a given moment management accepted to integrate it into
| Visual Studio, and keeps looking for the golden spot that it
| will take it beyond the VB/C# shadow, always a second thought
| when the .NET team designs new architecture features only
| taking VB and C# into consideration.
|
| F# twittersphere is its own bubble, not always with nice
| opinions about Microsoft and the .NET platform it depends on.
| gmfawcett wrote:
| F# is a great language, and definitely an ML. But it falls a
| bit short of being an OCaml. :) The type-system features are
| quite different -- e.g. F# has no functors and no GADTs, at
| least not the last time I checked. I think that F# has a
| different feel and perhaps a different target audience.
| [deleted]
| [deleted]
| Kototama wrote:
| I'm excited. Haskell gets a lot of attention but I have the
| feeling that OCaml may be better for _engineers_.
| ghostwriter wrote:
| How can parallel untracked mutations of untracked state be
| better for engineers?
| grumpyprole wrote:
| It may not remain untracked, hopefully types for algebraic
| effects will land in the future.
| ernst_klim wrote:
| > How can parallel untracked mutations of untracked state be
| better for engineers?
|
| What is untracked? Is unsafePerformIO
| (printLn ...)
|
| tracked? What is tracked? Is foo :: IO ()
|
| thread-safe? Maybe, maybe not. What meaningful information
| does this signature says to me? That it does some IO? That's
| an extremely useless information, especially if most of your
| code is IO something.
|
| What granularity does IO have? Does foo ::
| IO ()
|
| throws any exceptions? Maybe, maybe not.
|
| The need for effect tracking for writing correct programs is
| way overstated by some Haskell programmers. It's usually much
| more prudent to write DSLs which hide effects like variable
| mutations and logging, than expose them.
|
| For example you can start your program with a pure correct-
| by-construction core DSL, and then add logging, mutable
| variables where needed underneath the DSL's terms without
| breaking the semantics of the DSL. With effect tracking you
| are doomed to either reinvent custom effects to be able to
| switch interpreters painlessly, or you'll need to break the
| DSL by the addition of effects.
|
| Neither is prudent in real world, neither gives more value
| than takes. What is really funny is that some Haskell
| programmed believe that logging should be tracked, but
| allocation apparently should not (yes, it's a side effect).
|
| Where in fact all the "effects" are need to be tracked only
| when they are meaningful, i.e. when they are part of our
| DSL's semantics, and not some hidden part of the interpreter
| I don't need to know about.
|
| Imagine a theorem prover function which creates a conjunction
| of two terms: val conj : term -> term ->
| term
|
| It doesn't matter if it allocates or logs, at the precision
| that is interesting to us, it's just a function creating a
| conjunction of two terms.
| ghostwriter wrote:
| > unsafePerformIO (printLn ...)
|
| This repetitive talking point is getting boring. Go figure
| whether it's tracked now: {-# LANGUAGE
| Safe #-} -distrust-all-packages
|
| > What meaningful information does this signature says to
| me? That it does some IO? That's an extremely useless
| information, especially if most of your code is IO
| something.
|
| That's an extremely narrow view which you wouldn't have if
| you ever tried to implement a safe sandboxed environment.
|
| > What granularity does IO have? Does [...] throws any
| exceptions? Maybe, maybe not.
|
| what does it have to do with tracked parallel mutations?
|
| > Neither is prudent in real world, neither gives more
| value than takes
|
| define prudent and define real-world.
|
| > It doesn't matter if it allocates or logs
|
| have you heard about referential transparency? It's the
| thing your "theorem prover" example does not have.
| naasking wrote:
| > How can parallel untracked mutations of untracked state be
| better for engineers?
|
| It basically requires eager evaluation which, believe it or
| not, is a huge ergonomic win for people wanting to work on
| practical problems.
|
| OCaml also preserves the concise syntax and great type
| inference you get in Haskell.
|
| All in all, a more pragmatic set of tradeoffs I'd say,
| although it certainly has its own problems.
| sidkshatriya wrote:
| There are many paradigms in programming. Each have their
| strengths. A purely functional approach ala Haskell is not
| the only way. Based on your comment, it would seem no one
| should use C/C++. Yet many do. It depends on what you want to
| achieve, what is your abstraction budget, your performance
| requirement, legacy code...
|
| OCaml offers a pragmatic functional approach to programming.
| And now you are going to be able to have your OCaml code run
| in a truly parallel fashion on your multicore CPU.
|
| In the future there are plans to add typing to effects
| though. (There is support for effects currently but its
| untyped and experimental). When that happens you can track
| changes to state (which is a kind of "effect") if you want
| to...
| ghostwriter wrote:
| > A purely functional approach ala Haskell is not the only
| way.
|
| that wasn't the OP's argument though, the argument was that
| OCaml is somehow generally better for engineers.
|
| > OCaml offers a pragmatic functional approach to
| programming.
|
| an evaluation of something as pragmatic depends purely on
| what one whishes to practice. There's no universally
| objective notion of pragmatism.
|
| > And now you are going to be able to have your OCaml code
| run in a truly parallel fashion on your multicore CPU.
|
| no, it won't be able to do that automatically. Your code
| will have to respect certain invariants to function
| properly, and you as a developer will have to enforce these
| invariants with the available tooling at hand. Haskell has
| purity, guaranteed STM, and `par` labels for that. OCaml
| doesn't have those and the existing codebases will have to
| eliminate their thread-unsafe public interfaces first.
|
| > When that happens you can track changes to state
|
| how are you planning to track state changes without purity?
| sidkshatriya wrote:
| > > And now you are going to be able to have your OCaml
| code run in a truly parallel fashion on your multicore
| CPU.
|
| > no, it won't be able to do that automatically. [...]
|
| I was comparing it to the old situation in OCaml is that
| it was _impossible_ to have threads that were executing
| pure OCaml code and were _not_ IO bound to execute truly
| parallely. That limitation is removed.
|
| To me it is pretty obvious that you will need to use
| things like atomics, thread safe data-structures, mutexes
| etc. to ensure your code runs properly in multicore
| OCaml. It was implicit in my response. But I should have
| been more explicit.
|
| > that wasn't the OP's argument though, the argument was
| that the OCaml is somehow generally better for engineers.
|
| Engineers tend to be pragmatic. OCaml is pragmatic. So in
| quick short form, OCaml may be better to solve a certain
| kind of problem than something that is more pure and
| abstract like Haskell. It was intended as an informal
| argument and not an argument in a court of law :-).
| youerbt wrote:
| > pure and abstract
|
| Like math? Engineers would rather not use math?
|
| > It was intended as an informal argument
|
| Maybe. But at this point it just looks like a mean dig at
| Haskell. A better word would be opinionated. Haskell is
| opinionated, and that is fine.
|
| The biggest bait in this thread is using the term
| "engineers". It should rather be: people trained in
| imperative programming in mainstream imperative
| languages. Then it makes sense.
| ModernMech wrote:
| > Based on your comment, it would seem no one should use
| C/C++
|
| Maybe, there are better options out there these days for
| parallel and concurrent programs. Parallel programming in C
| and C++ is extremely fraught for the very reasons the
| parent brings up. There are so many footguns, starting from
| the fact that the favorite debugging method of C
| programmers, printf(), is not even thread safe.
|
| It's so bad that Rust markets as a feature "fearless
| concurrency", capitalizing on the recognition that the
| prevailing emotional state of a C or C++ dev writing
| concurrent or parallel programs is one of _fear_.
|
| And the very thing that makes Rust concurrency fearless
| over C and C++ is that borrowing and mutability are
| explicitly tracked. As we enter a world where over a dozen
| CPU cores are the norm, we are learning what works and what
| doesn't in writing programs for these machines, and
| integrating those learnings into new languages.
| pjmlp wrote:
| One detail that usually is left out of the fearless
| concurrency story is that it only works in-process across
| threads, it does very little to help in distributed
| concurrency across multiple processes accessing shared
| data, eventually written in various languages.
|
| Which in the age of micro-services is quite relevant as
| well.
|
| Definitely better than other languages, still doesn't
| prevent one to actually think about end-to-end overall
| system design.
| nomel wrote:
| > starting from the fact that the favorite debugging
| method of C programmers, printf()
|
| Most everyone I know uses a debugger. Maybe you're mostly
| exposed to beginner programmers?
| pjmlp wrote:
| There are couple of them that share this kind of
| opinions, https://lkml.org/lkml/2000/9/6/65
| nomel wrote:
| I sympathize with what he's saying, and I imagine he's
| correct, for his context, but some of us don't work on
| never-ending code and just want to write the best code we
| can, as quickly as possible, so we can move on to the
| next challenge. For those that are more pragmatic, and
| enjoy working on the hard problems the code is trying to
| solve rather than the hard problems of the code, using a
| debugger can be beneficial.
| slaymaker1907 wrote:
| I prefer printf because it works pretty much anywhere,
| handles concurrency by default (as in you can see the
| interleavings, though the log call itself is locked), and
| allows me to have a custom tailored view of the state I
| want to see.
|
| The last point may not be obvious, but debuggers have
| tons of noise for complex programs. In practice I just
| want to see how my program state changes over time while
| a debugger shows the entire program state or a large
| subset of it.
|
| I think the future of debugging is going to be structured
| program state logging. Ideally we should be able to take
| our logs and partially reconstruct program state over
| time. For example, in addition to source location, we
| should save the lexical information for each variable
| logged so you can have interactivity with your logs and
| source code.
| hedora wrote:
| I assume they were referring to the strong OCaml ecosystem
| (and collection of C/C++ bindings), not the relative merits
| of the threading systems.
| wk_end wrote:
| The OCaml ecosystem is not particularly strong compared to
| Haskell (or most other languages).
| [deleted]
| jamespwilliams wrote:
| Agreed. Being able to drop seamlessly into an imperative style
| is very useful.
|
| I'm someone who isn't an experienced functional programmer, or
| that deeply knowledgeable about type systems and category
| theory etc, but OCaml is still approachable to me, I feel I can
| get stuff done in it. I didn't feel that way with Haskell - I
| tried, but found the number of ways to do things overwhelming,
| and a lot of it felt very theoretical. Of course, Haskell's
| pureness is an impressive and interesting feature; but it isn't
| for me.
|
| OCaml also has much better systems programming abilities
| compared with Haskell, IMO. It feels like OCaml is the Rust of
| the functional programming world (and this is no accident, the
| Rust compiler was first implemented in OCaml in fact).
|
| This is all completely subjective of course.
| DonaldPShimoda wrote:
| Totally agree. OCaml is, in general, a better choice for
| engineering and real-world application. I think Haskell gets a
| lot of attention because it's _interesting_ (for lack of a
| better word). I don 't mean "OCaml is a boring language", but
| rather "Haskell was specifically designed as a playground for
| advanced ideas in type theory, so lots of weird things happen
| in that ecosystem." For doing personal projects for fun, I'd
| rather work with Haskell, but for getting things done probably
| not.
| gmfawcett wrote:
| Please let's just all be friends. :) It's fair game to discuss
| and differentiate the two languages on features, but "better
| for engineers" is going to take us right into the valley of
| flame-wars, by way of No-True-Scotsman town. :)
|
| Haskell and OCaml are both brilliant languages, with excellent
| feature sets and amazing dev teams... and lots of "engineers"
| who like them.
| yawaramin wrote:
| Note the difference:
|
| Kototama: ...I have the feeling that OCaml may be better for
| _engineers._
|
| You: let's not say that OCaml is better for engineers.
|
| People are allowed to feel things.
|
| But I'll give you a concrete reason why OCaml actually can be
| better for engineers: named and optional arguments. This
| single feature does wonders for code readability and
| maintainability.
|
| Actually I'll throw in a bonus reason: no laziness by default
| i.e. small and simple, predictable runtime that behaves
| almost exactly like a C executable.
| light_hue_1 wrote:
| Named arguments exist, https://hackage.haskell.org/package/
| named-0.3.0.1/docs/Named... That's just one example.
|
| But yes. Optional arguments are a big problem at scale. And
| laziness is the worst antifeature I could imagine.
|
| But. You can disable laziness and get great performance.
| You just need to be careful when using libraries and pick
| ones that have the right strictness.
|
| A strict Haskell would be a killer language.
| pharmakom wrote:
| > You just need to be careful when using libraries and
| pick ones that have the right strictness.
|
| Honestly a deal breaker
|
| > A strict Haskell would be a killer language.
|
| PureScript may be this language!
| rackjack wrote:
| Also, OCaml has records. Haskell has """records""".
| dleslie wrote:
| OCaml benefits from not looking like operator stew.
| sidkshatriya wrote:
| Actually OCaml has more operator stew than Haskell. Haskell's
| use of typeclasses/HKT avoids a lot of operator/function-name
| noise in the code.
|
| Where OCaml wins is that it does not hate mutation. This
| makes the code more impure but simpler. Sometimes just
| incrementing a mutable variable makes more sense than
| introducing a state monad!
| yawaramin wrote:
| I'd even argue that OCaml has way less operator stew than
| Haskell if we include Haskell's strictness annotations,
| type class instance selectors, and the large number of
| operators they have in the standard library. By comparison
| OCaml has a very modest number of operators.
| bitwize wrote:
| Yes, but is incrementing a mutable variable properly
| constrained and typed?
| [deleted]
| DonaldPShimoda wrote:
| What does this even mean?
|
| OCaml's variables are immutable. To use mutation, you
| have to do so explicitly with the `ref` type, e.g.:
| let box = ref 0 in print_endline ("box value: "
| ++ int_of_string !box); box := !box + 1;
| print_endline ("box value: " ++ int_of_string !box)
|
| will print first `0` and then `1`. You cannot put a non-
| integer into the box because the box has type `int ref`,
| meaning only values of type `int` can be put into it with
| the `:=` operator.
| kccqzy wrote:
| GP is (rhetorically, I assume) asking about whether or
| not the action of incrementing the mutable variable is
| typed, not that the variable itself is typed.
|
| For example in normal Haskell the code that uses mutation
| and code that does not use mutation have different types.
| A function may have the type f :: Int
| -> Int
|
| but with mutation it can become f ::
| Int -> ST s Int
|
| or f :: Int -> IO Int
|
| or f :: Int -> STM Int
|
| depending on the circumstances. That's not the case in
| OCaml. The kind of mutation in OCaml references is the
| most similar to Haskell's ST monad (not to be confused
| with State or StateT), but in Haskell the type tells us a
| mutation is happening inside the function call.
| ghostwriter wrote:
| You don't have to introduce a state monad to increment a
| mutable variable in Haskell, you can do that with IORefs
| pretty much the same way you do it in OCaml. But in a
| multi-core environment you will eventually want a
| guaranteed STM.
| sidkshatriya wrote:
| You are correct. However, IORefs are not idiomatic in
| "normal" Haskell. However, mutable variables are very
| much accepted in OCaml.
|
| Adding mutability to the mix via IORefs + Haskell's
| laziness by default means you don't _really_ know when a
| particular IORef mutation may really be executed.
|
| In OCaml, evaluation is eager and you know when it will
| happen. Even when you introduce bangs and special Haskell
| language extensions, fully removing laziness from your
| code in Haskell is difficult.
|
| TL;DR: Because of Haskell's laziness you are in some ways
| forced to be purely functional. OCaml allows you to
| embrace mutation in ways Haskell does not, in my view.
|
| > But in a multi-core environment you will eventually
| want a guaranteed STM.
|
| You actually may not always always want STMs. STMs are
| awesome but something more basic like locks may do the
| job. It can be more performant to use, say, a mutex. If
| STMs were superior on every parameter they would have
| taken over the world. They have not -- they are good in
| some scenarios and not so good in others...
| ghostwriter wrote:
| > Even when you introduce bangs and special Haskell
| language extensions, fully removing laziness from your
| code in Haskell is difficult.
|
| Why would one prefer to fully remove laziness?
|
| > TL;DR: Because of Haskell's laziness you are in some
| ways forced to be purely functional. OCaml allows you to
| embrace mutation in ways Haskell does not, in my view.
|
| unless there's a strive to be more on the side of the
| Safe[1] language subset, Haskell can be told to embrace
| the same mutation property with a combination of
| `unsafePerformIO` and `seq`. People tend to avoid it
| because the language offers a tooling to achieve better
| mutation properties. Overall, my argument here is that
| OCaml's idiomatic approach to permissible mutations
| doesn't seem to be a competitive advantage when it comes
| to software development in general, but rather a flavour
| that imperative programmers prefer due to their
| familiarity with the concept.
|
| > You actually may not always always want STMs.
|
| Whenever there's a non-trivial retry policy, one should
| prefer to choose STM + queues over debugging adventures
| with Locks and Mutexes. Almost all of multithreaded
| software I can immediately think of have non-trivial
| retrying logic.
|
| [1] https://ghc.gitlab.haskell.org/ghc/doc/users_guide/ex
| ts/safe...
| emmelaich wrote:
| > Why would one prefer to fully remove laziness?
|
| Far from an Ocaml/Haskell expert, but is it that laziness
| makes resource use less predictable?
| ghostwriter wrote:
| Laziness on itself does not prevent one from properly
| evaluating resource utilisation. In fact, laziness helps
| in resource preservation. But what makes it less
| predictable is various optimisation techniques that come
| to aid the lazy environment: strictness analysis, rewrite
| rules, and stream fusion[1][2]. They may change
| significantly between compiler releases and affect the
| previously optimised codebase.
|
| [1] https://wiki.haskell.org/GHC_optimisations
|
| [2] https://markkarpov.com/tutorial/ghc-optimization-and-
| fusion....
| yodsanklai wrote:
| I'd say OCaml wins in term of operators and maybe as a
| language until you start using monads. My entirely
| subjective feeling is that modern OCaml codebases use more
| and more monads, the language is becoming less elegant and
| tedious as a result.
| WastingMyTime89 wrote:
| The introduction of let+ and let* made using monads
| fairly elegant in my opinion but this is a recent
| addition so you might have never seen it used. Outside of
| concurrent code monads are not that common in my
| experience.
| rackjack wrote:
| Module hell?
| throwaway894345 wrote:
| When I tried to dabble in OCaml, it definitely looked like
| operator stew to me, but I'm coming to it from the C, Python,
| JS, etc world so maybe Haskell is even worse in this regard?
| yodsanklai wrote:
| I'd say that the learning curve in Haskell is much steeper.
| saghm wrote:
| OCaml definitely has a lot of built-in operators, but
| Haskell makes it absurdly easy to define your own operators
| as well, with built-in syntax for using binary operators as
| prefix functions and vice-versa. I'm not sure there's a
| definitive answer, but that's probably in large part
| because the idea of "operator stew" is pretty subjective.
| mcintyre1994 wrote:
| Ocaml makes it super easy to define your own operators as
| well. I was debugging a performance issue in an Ocaml
| codebase when I was very junior and new to the language,
| and proudly reported my finding that we shouldn't be
| using the (**) power operator in some algorithm but just
| multiplying and surely this was the cause of the problem.
| Turned out somebody had defined (**) as 64-bit multiply
| :)
|
| That said I don't know Haskell to compare!
| jimbokun wrote:
| > Turned out somebody had defined (*) as 64-bit multiply
| :)
|
| Well I don't think you should have been the one
| embarrassed in that scenario.
| _old_dude_ wrote:
| You can try reason first, it's a frontend for OCaml with a
| C-like syntax
|
| https://medium.com/@asankhaya/reason-with-
| ocaml-b75697a6c00b
| throwaway894345 wrote:
| Yeah, I played around with Reason but at the time the
| tooling kind of sucked and it only seemed to be used to
| generate JavaScript via BuckleScript. Not sure if things
| are better these days or not.
| baby wrote:
| I see Rust as an imperative language with functional support,
| and OCaml as a functional language with imperative support
| sidkshatriya wrote:
| Some questions:
|
| - Is merging this PR going to be more or less a formality now?
| I'm assuming subsequent PRs will make further improvements/fix
| any further bugs discovered. When is the merge to trunk likely to
| happen?
|
| - (Not that it really matters, but I'm curious). Will this PR be
| merged as-is with nearly 4000 commits or will it be squashed? The
| history exists in the multicore repo but will the history be
| brought into the ocaml repo?
| sadiq wrote:
| 1. Before multicore got to this PR stage it went through two
| phases of detailed review by the core team. A summary of this
| is on November's Multicore Monthly:
| https://discuss.ocaml.org/t/multicore-ocaml-november-2021-wi...
| . The tasks coming out of that which are marked post-MVP will
| be follow-up PRs before the 5.00 release.
|
| 2. That is unclear at the moment. There's a lot of useful
| history in those commits (which link out to issues and PRs on
| ocaml-multicore's repo) but at the same time, it also includes
| a lot of experiments that were ultimately backed out.
| pjmlp wrote:
| Great news! Congratulations to everyone involved.
| lgrialn wrote:
| Hurray!
|
| My wish for Ocaml is that it could somehow be popular enough to
| have more... casual users, let's say. I enjoy playing with it
| more than any other language I've run into, but everyone else
| falls so deeply into it that I don't generally follow their
| discussions very well. (Maybe I'll fall in deep myself in time,
| but it remains to be seen.)
| ModernMech wrote:
| I don't know if you've seen this language yet and I haven't
| used it, but Grain seems to take a lot of inspiration from
| Reason. Seems like they are trying to target a more casual
| audience.
|
| https://grain-lang.org
| Ericson2314 wrote:
| Someone needs to get OCaml running on the Go runtime, so it can
| be an F# for that ecosystem.
| ernst_klim wrote:
| This is a very bad idea considering Go runtime is optimized
| for way less allocations due to 1) how good Go in stack
| allocation is and 2) how mutable everything is.
|
| OCaml on the other hand has an extremely well optimized
| runtime for lots of small heap allocations (typical in FP),
| and produces good asm code for functional patterns.
| whimsicalism wrote:
| What's the motivation? OCaml is roughly as performant as Go.
| Ericson2314 wrote:
| Pure naked grab at more users. I don't mean to imply there
| any anything better about Go's runtime at all.
| yawaramin wrote:
| With all the problems arising from leaky abstractions and
| trying to adapt to a foreign runtime? Imho there's no point.
| Especially now that OCaml Multicore is on the way. A much
| better effort, for anyone interested, would be to vastly
| simplify the OCaml build and package management story to be
| more Go-like.
| Ericson2314 wrote:
| > With all the problems arising from leaky abstractions and
| trying to adapt to a foreign runtime?
|
| Huh? The point is Go might be a lousy language, but I can't
| think of anything OCaml _needs_ to do that the Go runtime
| cannot do. This wouldn 't be leaky and the FFI could be
| quite good.
|
| > Especially now that OCaml Multicore is on the way.
|
| As I wrote in the other reply, this would be a naked ploy
| for new users, and flexing the language isn't wedded to a
| single run time.
|
| Multicore OCaml isn't just a runtime change, but also
| demonstration of the new effects indicating that the
| language can do parallelism without bad concurrency
| problems. All that language-side work carries over to the
| other runtime: you get to show off Goroutines done more
| safely!
| c-cube wrote:
| Does Go's runtime do generational collection? No. Does it
| support tailcalls? I have no idea but I doubt so. Without
| these there cannot be any chance for OCaml-on-go; more
| blockers would probably come to mind quite quickly.
___________________________________________________________________
(page generated 2021-12-21 23:01 UTC)