具有异步等待任务组的最大线程数

我的目的是了解 Swift 5.5 的 async-await 使用的“协作线程池”,以及任务组如何自动约束并发度:考虑以下任务组代码,并行执行 32 个计算:

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`
            }
        }
    }
}

虽然我希望它会限制并发程度,但正如宣传的那样,我一次只能处理两个 (!) 并发任务。这比我预期的要严格得多:

如果我使用旧的 GCD concurrentPerform...

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

...我一次得到 12 个,充分利用设备(我的 6 核 i9 MacBook Pro 上的 iOS 15 模拟器),同时避免线程爆炸:

(FWIW,这两个都在运行在 Big Sur 上的 Xcode 13.0 beta 1 (13A5154h) 中进行了分析。请忽略这两次运行中各个“作业”的细微差别,因为有问题的函数只是随机旋转一段时间;关键观察是并发程度是我们所期望的。)

这个新的 async-await(和任务组)自动限制并行度非常好,但是 async-await 的协作线程池比我预期的要严格得多。而且我看不到调整该池的这些参数的方法。我们如何才能更好地利用我们的硬件,同时避免线程爆炸(不使用非零信号量或操作队列等旧技术)?

回答

看起来这种奇怪的行为是模拟器的限制。如果我在我的物理 iPhone 12 Pro Max 上运行它,异步等待任务组方法会导致 6 个并发任务......

...本质上与concurrentPerform行为相同:

行为,包括并发程度,在物理设备上基本相同。

一种是推断模拟器似乎被配置为对 async-await 的约束比直接 GCD 调用所能达到的要多。但是在实际的物理设备上,async-await 任务组的行为正如人们所期望的那样。


以上是具有异步等待任务组的最大线程数的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>