我有一个长时间运行(5-10 小时)的 Mac 应用程序,可以处理 5000 个项目。每个项目都通过执行一些转换(使用 Saxon)、运行一堆脚本(在 Python 和 Racket 中)、收集数据并将其序列化为一组 XML 文件、一个 SQLite 数据库和一个 CoreData 数据库来处理。每个项目都完全独立于其他项目。
总之,它做了很多事情,需要很长时间,并且似乎是高度可并行化的。
加载所有需要处理的项目后,应用程序使用 GCD 并行化工作,使用dispatch_apply
:
dispatch_apply(numberOfItems, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(size_t i) {
@autoreleasepool {
...
}
});
我在具有 12 个内核(24 个虚拟)的 Mac Pro 上运行该应用程序。因此,我希望始终处理 24 个项目。但是,我通过记录发现正在处理的项目数量在 8 到 24 之间变化。这实际上增加了运行时间(假设它一次可以处理 24 个项目)。
一方面,也许 GCD 真的非常聪明,它已经给了我最大的吞吐量。但我担心,因为大部分工作都发生在这个应用程序生成的脚本中,也许 GCD 是根据不完整的信息进行推理,并没有做出最好的决定。
任何想法如何提高性能?正确之后,第一个期望属性是缩短此应用程序运行所需的时间。我不关心功耗、占用 Mac Pro 或其他任何事情。
更新:事实上,这在文档中看起来令人震惊:“在任何给定时刻,并发队列执行的实际任务数量是可变的,并且可以随着应用程序中条件的变化而动态变化。许多因素会影响执行的任务数量并发队列,包括可用内核的数量,其他进程正在完成的工作量,以及其他串行调度队列中任务的数量和优先级。” (强调)看起来让其他进程在工作会对应用程序中的调度产生不利影响。
能够说“同时运行这些块,每个内核一个,不要尝试做任何更聪明的事情”会很好。