我的目的是了解Swift 5.5的异步等待所使用的“协作线程池”,以及任务组如何自动限制并发程度:考虑以下任务组代码,并行执行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上的i9 15模拟器),同时避免了线程爆炸:

(FWIW,这两者都被描述在运行在大Sur上的Xcode 13.0beta 1(13A5154)中。请不要理会这两次运行中各个“作业”之间的细微差别,因为所讨论的函数只是在一个随机的时间内旋转;关键的观察是并发的程度是我们所期望的。)
这个新的异步等待(和任务组)自动限制并行性的程度是很好的,但是异步等待的协作线程池比我预期的要约束得多。我看不出有什么办法来调整这个池的参数。我们如何更好地利用我们的硬件,同时仍然避免线程爆炸(而不求助于非零信号量或操作队列之类的老技术)?
发布于 2021-06-14 22:50:04
看起来,这种奇怪的行为是模拟器的一个限制。如果我在物理iPhone 12 Pro Max上运行它,异步等待任务组方法将产生6个并发任务.

..。它与concurrentPerform行为本质上是相同的:

这种行为,包括并发的程度,在物理设备上基本上是相同的。
可以推断,模拟器似乎被配置为约束异步-等待比直接GCD调用所能实现的更多。但是在实际的物理设备上,异步等待任务组的行为就像人们所期望的那样。
https://stackoverflow.com/questions/67978028
复制相似问题