Async limit

Hi,

When using @async is there a way to limit the number of processes/queries being run at the same time?

Thank you
Kind regards

It is reasonable to use a semaphore for this, as described here for threads:

I have also seen a Channel used as a adhoc semaphore.
Which is marginally faster since it is not having to take out locks etc.
but probably not worth the loss of clarity for code.
Plus using a semaphore frees you to change from tasks to threads later.
(threads are just tasks without the sticky bit set)

1 Like

I recommend using “worker pool” pattern I described in a quick tutorial Concurrency patterns for controlled parallelisms (discussion) which is just a simple wrapper around a channel and tasks.

Semaphore may be useful for simple things sometimes but lock and lock-like constructs often yield non-composable and hard-to-read code. “Don’t communicate by sharing memory, share memory by communicating.” is one of very practical Go Proverbs. Since a lot of good practical ideas in concurrency are developed in Go, I think it’d be useful to steal some patterns from Go. Some of them are discussed in my tutorial I linked above.

It is also a waste of resource to allocate tasks and then limit how many of them can run. It is usually much cleaner to match the bound and the number of tasks in the first place, in terms of performance and code structure.

Channel uses lock internally.

A nitpick: There’s no way in Julia to “change tasks to threads.” There is no language-level API to create an OS thread. The only thing you can do is to create a task which comes with two flavors:

  • A task scheduled with Threads.@spawn can be executed by arbitrary worker threads.
  • A task scheduled with @async uses the same worker thread as the parent task.

(I’m sure you already know this since you are mentioning the “sticky bit.” This is rather for avoiding confusion of other readers.)

6 Likes

So they do.
This was not the case in 1.2, it was changed in 1.3.
Makes sense, we started taking multithreading seriously in 1.3,
but I thought that the Base.Channel didn’t have a lock, and only the Base.Threads.Channel had a lock; but no: Base.Threads.Channel === Base.Channel

1 Like