gpt4 book ai didi

objective-c - 如何加快 Mac 应用程序处理 5000 个独立任务的速度?

转载 作者:太空狗 更新时间:2023-10-30 04:02:05 25 4
gpt4 key购买 nike

我有一个长时间运行(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 个项目)。 p>

一方面,也许 GCD 真的非常聪明,它已经给了我最大的吞吐量。但我担心的是,由于大部分工作都发生在该应用生成的脚本中,GCD 可能是根据不完整的信息进行推理,并没有做出最佳决策。

有什么提高性能的想法吗?正确后,第一个需要的属性是缩短该应用程序运行所需的时间。我不关心功耗、占用 Mac Pro 或其他任何东西。

更新:事实上,这在 docs 中看起来令人担忧:“并发队列在任何给定时刻执行的实际任务数是可变的,并且会随着应用程序中条件的变化而动态变化。许多因素会影响并发队列执行的任务数,包括可用内核数,< strong>其他进程正在完成的工作量,以及其他串行调度队列中任务的数量和优先级。” (强调)看起来让其他进程工作会对应用程序中的调度产生不利影响。

能够只说“同时运行这些 block ,每个内核一个,不要尝试做任何更聪明的事情”会很好。

最佳答案

如果您下定决心,可以使用 NSThread API 显式生成 24 个线程,并让每个线程从同步的工作项队列中拉取。我敢打赌性能会明显变差。

当提交给它的工作项从不阻塞时,GCD 的工作效率最高。也就是说,您所描述的工作负载相当复杂,并且充满了线程阻塞的机会。对于初学者来说,您正在生成一堆其他进程。就在这里,这意味着您已经依赖操作系统在您的主任务和这些从属任务之间分配时间/资源。除了设置每个子进程的操作系统优先级之外,操作系统调度程序无法知道哪些进程比其他进程更重要,默认情况下,您的子进程将与其父进程具有相同的优先级。也就是说,听起来您通过调整流程优先级没有任何好处。我假设您正在阻塞等待从任务完成的主任务线程。这实际上是停放该线程——它不能做任何有用的工作。但正如我所说,我认为调整从属任务的操作系统优先级不会有太多好处,因为这听起来确实像是一个 I/O 绑定(bind)工作流...

您继续描述三个 I/O 密集型操作(“将其序列化为一组 XML 文件、一个 SQLite 数据库和一个 CoreData 数据库。”)所以现在所有这些不同的线程和进程都在争夺什么大概是一个共享的大容量存储设备。 (即,除非您要写入 24 个不同的数据库,在 24 个独立的硬盘驱动器上,每个内核一个,否则您的过程最终将在磁盘访问时被序列化。)即使您有 24 个不同的硬盘驱动器,写入一个硬盘驱动器(甚至是 SSD)相对较慢。对于几乎任何阻塞的磁盘写入,您的线程将从它们正在运行的 CPU 中取出(以便另一个正在等待的线程可以运行)。

如果你想最大化你从 GCD 中获得的性能,你可能想要重写你在 C/C++/Objective-C 中的子任务中所做的所有事情,将它们引入进程中,然后使用 dispatch_io 原语进行所有相关的 I/O。对于您不控制低级读写的 API,您需要仔细管理和调整您的工作负载,以针对您拥有的硬件对其进行优化。例如,如果你有一堆东西要写入一个单一的、共享的 SQLite 数据库,那么让多个线程同时尝试写入该数据库是没有意义的。你最好让一个线程(或串行 GCD 队列)写入 SQLite 并在预处理完成后向其提交任务。

我可以在这里继续讲很长一段时间,但归根结底,这里的工作流程很复杂,看似受 I/O 限制。在最高级别,CPU 利用率或“正在运行的线程数”将成为此类任务的性能特别差的衡量标准。通过使用子进程(即脚本),您将大量控制权交给了操作系统,它实际上对您的工作负载一无所知,因此除了使用其通用调度程序分配资源外什么也做不了。 GCD 不透明的线程池管理实际上是您最不关心的问题。

在实际层面上,如果您想加快速度,请购买多个更快(即 SSD)的硬盘驱动器,然后重新设计您的任务/工作流程以单独和并行地使用它们。我怀疑这会为您带来最大的 yield (对于 time == money == hardware 的一些等价关系。)

关于objective-c - 如何加快 Mac 应用程序处理 5000 个独立任务的速度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18245478/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com