处理多个std::异步调用

Handling multiple std::async calls

本文关键字:异步 调用 std 处理      更新时间:2023-10-16

我有一个需求,需要高效地删除数千个文件。目前,文件是按顺序删除的。

我想通过使用std::async()以异步方式调用delete来加快删除速度。

电流:

  1. 获取文件列表
  2. 对于每个文件,调用delete()

所需流量:

  1. 获取文件列表
  2. 对于每个文件:
    1. 使用std::async()调用AsyncDelete()
    2. 将未来对象存储在矢量中
  3. 等待每个删除操作完成,然后返回

我将使用std::launch::async启动每个异步任务,以便它在单独的线程上运行。

我有以下问题:

  1. async()是否适用于涉及多个任务的工作负载?还是将线程用于此类任务更好?我读了Scott Myer的书《高效的现代C++》中的一章(第35项:更喜欢基于任务的编程而不是基于线程的编程),他在书中建议使用基于任务的程序设计而不是基于螺纹的程序设计。

  2. 每个"async()"调用的成本有多高?它是否有类似于线程创建开销的开销?我计划控制每个周期调用的异步任务的数量。例如,如果要删除10000个文件,我将在每个周期只调用100个删除,而不是一次性生成10000个异步()任务。我希望标准库实现能够有效地处理多个异步调用(例如使用线程池)。

  3. async()返回的future()对象公开了get()和wait()方法。我读到过,get()在内部调用wait()。对存储在向量中的每个期货调用get()就足够了吗?

  4. 如果一个get()永远不会返回怎么办?建议在超时的情况下使用wait_forr()吗?

您可能会发现这实际上并没有您想要的那么多帮助。文件系统可能有内核级别的锁(以确保一致性),如果有许多线程碰到这些锁,可能会造成麻烦。

我建议

  1. 获取文件列表
  2. 将列表分成(比如)十个相等的块(由迭代器对表示)
  3. 启动十个线程,每个线程删除列表中自己的块
  4. 等待十根线完成。

  5. 用10的不同值进行实验。

作为一种完全不同的方法,您是否考虑过将所有内容移动到数据库中?快速删除数千个持久的东西正是数据库擅长的。

瓶颈是I/O操作和操作系统级别的文件系统操作,委派数千个线程来做这件事不太可能缓解瓶颈——事实上,你可能会发现这种方法实际上会减慢速度。

正如其他人所提到的,根据文件的大小,最好将数据存储在内部数据库中,而不是滥用文件系统。

否则,我可能建议使用一个线程来删除文件,然后您可以等待(或不等待)线程完成。


要回答您关于async的成本有多高的一个问题:std::async的实现是编译器和操作系统特定的,与您机器上的本机线程实现的开销相当。实际上,最好的做法是自己进行基准测试。