Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maximum number of threads with async-await task groups

My intent is to understand the “cooperative thread pool” used by Swift 5.5’s async-await, and how task groups automatically constrain the degree of concurrency: Consider the following task group code, doing 32 calculations in parallel:

func launchTasks() async {
    await withTaskGroup(of: Void.self) { group in
        for i in 0 ..< 32 {
            group.addTask { [self] in
                let value = await doSomething(with: i)
                // do something with `value`
            }
        }
    }
}

While I hoped it would constrain the degree of concurrency, as advertised, I'm only getting two (!) concurrent tasks at a time. That is far more constrained than I would have expected:

enter image description here

If I use the old GCD concurrentPerform ...

func launchTasks2() {
    DispatchQueue.global().async {
        DispatchQueue.concurrentPerform(iterations: 32) { [self] i in
            let value = doSomething(with: i)
            // do something with `value`
        }
    }
}

... I get twelve at a time, taking full advantage of the device (iOS 15 simulator on my 6-core i9 MacBook Pro) while avoiding thread-explosion:

enter image description here

(FWIW, both of these were profiled in Xcode 13.0 beta 1 (13A5154h) running on Big Sur. And please disregard the minor differences in the individual “jobs” in these two runs, as the function in question is just spinning for a random duration; the key observation is the degree of concurrency is what we would have expected.)

It is excellent that this new async-await (and task groups) automatically limits the degree of parallelism, but the cooperative thread pool of async-await is far more constrained than I would have expected. And I see of no way to adjust these parameters of that pool. How can we better take advantage of our hardware while still avoiding thread explosion (without resorting to old techniques like non-zero semaphores or operation queues)?

like image 719
Rob Avatar asked Jun 14 '21 22:06

Rob


People also ask

Is async await single threaded?

The async and await keywords don't cause additional threads to be created. Async methods don't require multithreading because an async method doesn't run on its own thread. The method runs on the current synchronization context and uses time on the thread only when the method is active. You can use Task.

Does async await use thread pool?

Await Keyword Basically, it returns to caller thread with reference to ongoing task and stop execution of code below that line and release the current thread to thread pool to process another request. Async and await are always used together, if not, then there will be something wrong.

Does await spawn a thread?

Using Async/Await doesn't necessarily cause a new thread to be created. But the use of Async/Await can lead to a new thread to be created because the awaitable function may internally spawn a new thread. And it often does, making the statement 'No, it doesn't spawn threads' almost useless in practice.

Is async await concurrent?

It is concurrent, in the sense that many outstanding asychronous operations may be in progress at any time. It may or may not be multithreaded. By default, await will schedule the continuation back to the "current execution context".


Video Answer


1 Answers

It looks like this curious behavior is a limitation of the simulator. If I run it on my physical iPhone 12 Pro Max, the async-await task group approach results in 6 concurrent tasks ...

enter image description here

... which is essentially the same as the concurrentPerform behavior:

enter image description here

The behavior, including the degree of concurrency, is essentially the same on the physical device.

One is left to infer that the simulator appears to be configured to constrain async-await more than what is achievable with direct GCD calls. But on actual physical devices, the async-await task group behavior is as one would expect.

like image 144
Rob Avatar answered Oct 24 '22 22:10

Rob