Making my library thread-agnostic

I have a library that requires some thread-local state for correctness in the presence of threading, currently implemented as a Map from thread ids to the current value. This introduces a dependency on systhreads. However, the library does not itself depend on threading, and would work as well with a dummy implementation of Thread if it runs inside a single-threaded program. Is there a recommended way to make my library thread-agnostic and not depend on systhreads? I am especially looking for a solution at the level of dune.

I have two solutions in mind with their drawbacks:

  • Provide a functorial interface where the user supplies their desired implementation of the Thread module.
  • Choose between Thread and a dummy implementation at compilation using a preprocessor.

You could also rely on virtual libraries for that, and users of you library would have to choose whether they want the threaded or non-threaded backend when their executable depends on your library.

BTW, IIUC the multicore plan for OCaml, I believe that the threaded/non-threaded distinction will disappear in the future. i.e. there will be only one runtime and it will support multi-threading.

Thank you. This looks like the keyword that I was missing. Here is a link as a reference: https://dune.readthedocs.io/en/stable/variants.html.

I do not know what the plans are for “no-systhread”, but multicore will introduce a separate runtime that for a long time will stay alongside the monocore GC (even if as much as possible will be shared in the implementation). So I expect a similar question will arise once multicore is there, to avoid fragmentation inside the library ecosystem. Work will likely be done at the level of the compiler distribution to provide compatibility layers. But the same could have been done for providing already a thread-agnostic version of Thread.id, so maybe the idea of compatibility layer is not well-enough defined to solve the issue entirely.

I’m not sure where you got this information from, but it’s certainly not the current plan of record with the core OCaml development team. We have a series of features to land over the next few releases that clear the path for the domains-only multicore PRs, and we’ll take a decision on how to integrate it to the upstream distribution based on the results of the experimental science and maintainability considerations.

Dune always selects the threads predicate in META files when it’s linking an executable, so it’s difficult to build a completely unthreaded program using it at present.

However, you should be able to expose an unthreaded variant using META files. I need to implement this for ctypes dune port but haven’t added the META templates yet. You can see the variants in action there though.

Hi Anil, I am happy with this reply–dune pushes people towards systhreads anyway so there is not urgency to support nosysthreads. I will look further into it if there are some requests (if people ever care about my lib!).

The June 2018 multicore meeting, but is there really a contradiction with what you wrote? The experimental results have not improved much since then, and the language design is largely unfinished (we do not know yet how we are going to write concurrent programs safely according to ML standards). The parallel minor GC solves one issue of compatibility but not all, and at a cursory glance the paper raises more questions (I will let you know if I manage to formulate my thoughts about it). But it is good to see your enthusiasm about the multicore project.

The experimental results have not improved much since then,

It would be incorrect to say that experimental results have not improved since then. None of the parallel benchmarks sandmark existed in 2018; first benchmarks were added in Q3 2019. So unclear what the blanket statement “experimental results have not improved much since then” means since there was nothing to experiment with.

(we do not know yet how we are going to write concurrent programs safely according to ML standards).

Can you elaborate on this? For one, the memory model (PLDI 2018) preserves type safety for racy programs, which I think constitutes the difficult bits of “concurrent programs safely according to ML standards”.

and the language design is largely unfinished

Curious to know your thoughts behind your using the term “largely unfinished”. It would be useful if you can produce a list of the language features that are unfinished, so that all of us can work towards completing it.

2 Likes

I had in mind the figure of 10% slowdown that was announced at the time (which was just conjecture/preliminary results then).

I have noted this type safety claim in the latest paper, so this can be discussed as part of the paper. The example I gave is an important one, but I have further thoughts to contribute in time.

If you read the paper (specifically section 6.1.1), you will find that the average slowdown is 3.5% while using 61% less memory for the parallel minor GC. Since the throughput in a managed language is a tradeoff between space and time, you should read it as, if you were more relaxed with memory, the slowdown will be lower. Indeed, many programs that are 10+% slower than stock OCaml use much less memory than stock. See Fig 8. The slowest one is game_of_life (20% slower than stock) due to different way of handling exceptions. We have some fixes for this, but couldn’t get it in time for the paper.

2 Likes