我的目的是了解 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 = doSomething(with: i)
// do something with `value`
}
}
}
}
虽然我希望它会限制并发程度,但正如所宣传的那样,我一次只能获得两个(!)并发任务。这比我预期的要受限得多:
如果我使用旧的GCDconcurrentPerform
...
func launchTasks2() {
DispatchQueue.global().async {
DispatchQueue.concurrentPerform(iterations: 32) { [self] i in
let value = doSomething(with: i)
// do something with `value`
}
}
}
...我一次获得十二个,充分利用设备(我的 6 核 i9 MacBook Pro 上的 iOS 15 模拟器),同时避免线程爆炸:
(FWIW,这两个都在 Big Sur 上运行的 Xcode 13.0 beta 1 (13A5154h) 中进行了分析。请忽略这两次运行中各个“作业”的细微差别,因为相关函数只是在随机持续时间内旋转;关键的观察是并发程度是我们所期望的。)
非常好的是这个新async
-await
(和任务组)自动限制并行度,但是协作线程池async
-await
比我预想的要受限得多。我认为没有办法调整该池的这些参数。我们如何才能更好地利用我们的硬件,同时仍然避免线程爆炸(不诉诸非零信号量或操作队列等旧技术)?
模拟器上协作线程池的这种限制已在 Xcode 14.3 中删除(在发行说明 https://developer.apple.com/documentation/xcode-release-notes/xcode-14_3-release-notes).
看起来这种奇怪的行为是 Xcode 14.2 及更早版本中模拟器的限制。如果我在物理 iPhone 12 Pro Max 上运行它,异步等待任务组方法会产生 6 个并发任务......
...本质上与concurrentPerform
行为:
行为(包括并发程度)在物理设备上本质上是相同的。
我们可以推断,模拟器似乎被配置为比直接 GCD 调用可实现的更多限制 async-await。但在实际的物理设备上,异步等待任务组的行为正如人们所期望的那样。
无论如何,以上内容是由 MacBook Pro 上的 Xcode 13 生成的。我在 Xcode 14.2 中重复了这两台不同的 Mac,并得到了不同的结果。具体来说,在我的 Intel 2018 MacBook Pro 上,模拟器的协作线程池有两个线程。不过,在我的 2022 Mac Studio 模拟器上,它被限制为 3 个线程:
看来模拟器的协作线程池的大小受到您使用的 Mac 硬件的影响。但重点仍然是,协作线程池是人为地限制在模拟器上的。
为了进行比较,下面是在 Xcode 14.2 中在物理 iPhone 12 Pro Max 上运行的类似“兴趣点”:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)