Including multi-threading functionality in a package

Hi, first post here. Long time python user, so still learning Julia but enjoying so far.

What is the general approach to adding multi-threading support into a Julia package? Specifically, I’ve ported a geo-processing library from rust (which was also available in python via the rust binary/FFI), and wanted to embed multi-threading support to allow better performance. The package can be found here: https://github.com/joshuanunn/ConvertBNG.jl

I could either enforce it (but presumably limit users to Julia >= 1.3), or somehow decide at runtime what to do - i.e. check version or try catch type behavior, or could simply leave it to end users to implement themselves (i.e. write something in readme), as it would be very trivial anyway (I have left the relevant lines commented out in the source). I guess the last option might be best as the user must set the relevant environment variable first?

I would appreciate any thoughts - I’m more trying to get a feel for the general approach with package functionality with regards to performance.

Thanks,
Josh

2 Likes

Hey and welcome! :wave:
Here are some alternatives I know are used in practice

  • Provide both a threaded and an unthreaded function. The selection can be done statically using @static if VERSION >= v1.3
  • Many popular packages supporting threading simply just support v1.3, one example is FFTW.
  • Maintain two branches, one with support for v1.0 and one with v1.3. This is of course laborious.
  • Implement threading by means of @threads for i in ... This construct is available also in v1.0, but does currently not compose well with outer threading, i.e., if the user also attempts to thread their code making use of your threaded code.
4 Likes

IMO this is the only viable option for most open source projects with limited resources. Your users just have to switch to 1.3, which is the reasonable thing to do anyway (and soon, 1.4).

Generally, unless a package has users with very low risk tolerance, its maintainers should never hesitate requiring a released version. And conversely, users who claim they have very low risk tolerance and want to use your package on earlier versions should be ready to back this up with contributions in the form for PRs or money.

8 Likes

Hi both, thank you for the informative replies - a few potential options there and just what I was hoping for.

I’ll implement one of these this week - given that it’s a new package (also somewhat niche) and that I suspect most users are likely to move to Julia 1.3 onwards within the next year, I’ll probably lean towards requiring it as a minimum.

1 Like

If anyone is interested in the follow-up to this, I added multi-threading using Threads.@threads for… This can be used with the long term 1.0.5 release up until the latest it seems, so just set this as the minimum requirement.

When benchmarking, I found performance in 1.3.1 and the latest 1.4 RC to be slightly better and much more consistent between runs than 1.0.5, so recommend use later versions anyway.

If anyone is interested, I’ve put the benchmark results up in tables on the GitHub repo readme (linked above in my first post) in context of the same tests run with the equivalent rust binaries for two different CPUs and OS’s and varying the number of threads.

1 Like