多线程多处理?我如何使它更有效率?

Multiprocessing with Multithreading? How do I make this more efficient?

我手头有一个有趣的问题。我可以访问 128 CPU ec2 实例。我需要 运行 一个接受 1000 万行 csv 的程序,并针对该 csv 中的每一行向 DB 发送请求以扩充 csv 中的现有数据。为了加快速度,我使用:

executor = concurrent.futures.ProcessPoolExecutor(len(chunks))
futures = [executor.submit(<func_name>, chnk) for chnk in chunks]
successes = concurrent.futures.wait(futures)

我将 1000 万行 csv 分成 128 个部分,然后使用 futures 启动 128 个进程(主要进程 +1,因此总共 129 个)。每个进程获取一个块,并检索其块的记录并将输出吐到一个文件中。在此过程结束时,我将所有文件合并在一起,瞧。

我对此有一些疑问。

提前致谢!

Is this most efficient?

不进行分析很难判断。总会有瓶颈的地方。例如,如果您受到 cpu 的限制,并且无法提高算法的效率,那么这可能是一个硬性限制。如果您的存储带宽有限,并且您已经在使用高效的 read/write 缓存(通常由 OS 或低级驱动程序处理),那可能是一个硬性限制。

Are all cores of the machine actually used?

(假设 python 在一台物理机器上 运行ning,你指的是一个 cpu 的单个内核)是的,python 的 mp.Process 使用单个线程创建一个新的 OS 级进程,然后由 OS 的调度程序分配该线程在物理核心上执行给定的时间。调度算法通常非常好,所以如果您有与逻辑核心数量相同的繁忙线程,OS 将使所有核心保持忙碌。

Would threads be better?

不太可能。 Python 不是线程安全的,因此它必须一次只允许每个进程一个线程 运行。在 cc++ 中编写函数并调用 python 宏时,有一些特定的例外情况:Py_BEGIN_ALLOW_THREADS 尽管这不是很常见。如果你的大部分时间花在这些功能上,线程实际上将被允许 运行 并发,并且与进程相比会有更少的开销。线程还共享内存,使完成后返回结果更容易(线程可以简单地修改一些全局状态,而不是通过队列或类似方式传递结果)。

multithreading on each CPU?

同样,我认为您可能拥有一个具有 128 个内核的 CPU。OS 调度程序决定在任何给定时间每个内核上应该 运行 哪些线程。除非线程正在释放 GIL,否则每个进程只能有一个线程一次 运行。例如 运行 128 个进程,每个进程有 8 个线程将导致 1024 个线程,但仍然只有 128 个可以一次 运行,所以额外的线程只会增加开销。

what to read up on?

当你想让代码更快时,你需要进行分析。并行处理的分析更具挑战性,远程/虚拟计算机的分析有时也具有挑战性。使一段特定代码变慢的原因并不总是很明显,唯一可以确定的方法是对其进行测试。还要查看您正在使用的工具。我特别考虑您正在使用的数据库,因为大多数数据库软件都进行了大量的优化工作,但您必须以正确的方式使用它才能获得最大的速度。想到批量请求而不是一次访问一行。