加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-14 17:50:31 所属栏目:百科 来源:网络整理
导读:我有一个长期运行(5-10小时)的Mac应用程序,可以处理5000个项目.通过执行多个转换(使用Saxon),运行一堆脚本(在 Python和Racket中),收集数据,并将其序列化为一组XML文件,SQLite数据库和CoreData数据库来处理每个项目.每个项目完全独立于其他项目. 总之,它做了
我有一个长期运行(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或其他任何东西.

更新:事实上,这在docs中看起来很惊人:“在任何给定时刻并发队列执行的任务的实际数量是可变的,并且可以随着应用程序中的条件的变化而动态变化.许多因素会影响执行的任务数量.并发队列,包括可用内核的数量,其他进程正在完成的工作量,以及其他串行调度队列中任务的数量和优先级.“ (重点补充)看起来让其他进程正常工作会对应用程序中的调度产生负面影响.

能够只是说“同时运行这些块,每个核心一个,不要尝试做任何更聪明的事情”真是太好了.

解决方法

如果您受到约束并确定,则可以使用NSThread API显式生成24个线程,并使每个线程从同步的工作项队列中拉出.我敢打赌,性能会明显变差.

当提交给它的工作项永远不会阻止时,GCD的效率最高.也就是说,您所描述的工作量相当复杂,并且充斥着线程阻塞的机会.对于初学者来说,你正在产生一堆其他过程.就在这里,这意味着您已经依靠操作系统来分配主任务和这些从属任务之间的时间/资源.除了设置每个子进程的OS优先级之外,OS调度程序无法知道哪些进程比其他进程更重要,并且默认情况下,您的子进程将具有与其父进程相同的优先级.也就是说,通过调整流程优先级听起来并不是什么好事.我假设您正在阻止等待从任务完成的主任务线程.这有效地停止了这个线程 – 它没有任何有用的工作.但就像我说的那样,我不认为通过调整你的奴隶任务的操作系统优先级可以获得很多东西,因为这听起来像是一个I / O绑定的工作流程……

您将继续描述三个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)的硬盘,并重新设计任务/工作流程,以便单独和并行使用它们.我怀疑这会产生最大的收益(对于某些等价关系的时间==钱==硬件.)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读