我正在使用xargs
调用Python脚本来处理大约3000万个小文件。我希望使用xargs
并行化过程。我正在使用的命令是:
find ./data -name "*.json" -print0 |
xargs -0 -I{} -P 40 python Convert.py {} > log.txt
基本上,Convert.py
会读小json文件(4kb),进行一些处理并写入另一个4kb文件。我正在一台具有 40 个 CPU 核心的服务器上运行。并且该服务器上没有运行其他 CPU 密集型进程。
通过监控htop(顺便说一句,有没有其他好的方法来监控CPU性能?),我发现它-P 40
没有预期的那么快。有时所有核心都会冻结并在 3-4 秒内几乎降至零,然后恢复到 60-70%。然后我尝试将并行进程的数量减少到-P 20-30
,但仍然不是很快。理想的行为应该是线性加速。对于并行使用 xargs 有什么建议吗?
答案1
我愿意打赌你的问题是Python。您没有说对每个文件进行什么样的处理,但假设您只是在内存中处理数据,则运行时间将主要由启动 3000 万个 python 虚拟机(解释器)决定。
如果您可以重构您的 python 程序以获取文件列表,而不是仅一个文件,那么您将获得性能上的巨大提升。然后您仍然可以使用 xargs 来进一步提高性能。例如40个进程,每个进程处理1000个文件:
find ./data -name "*.json" -print0 |
xargs -0 -L1000 -P 40 python Convert.py
这并不是说 python 是一种糟糕/缓慢的语言;而是说它是一种糟糕的/缓慢的语言。它只是没有针对启动时间进行优化。您将在任何基于虚拟机的语言或解释语言中看到这一点。例如,Java 的情况会更糟。如果你的程序是用 C 语言编写的,启动一个单独的操作系统进程来处理每个文件仍然会产生成本,但会少得多。
从那里您可以尝试-P
看看是否可以提高一点速度,也许可以通过增加进程数量来在读取/写入数据时利用空闲处理器。
答案2
因此,首先,考虑约束:
每项工作的限制是什么?如果是 I/O 则可以大概每个 CPU 核心可以执行多个作业,直到达到 I/O 限制,但如果是 CPU 密集型,则比毫无意义地同时运行多于 CPU 核心的作业还要糟糕。
我对这些事情的理解是GNU 并行可以让您更好地控制作业队列等。
看GNU 并行 vs & (我的意思是背景) vs xargs -P了解两者有何不同的更详细解释。
答案3
正如其他人所说,检查您是否受 I/O 限制。另外, xargs 的手册页建议使用-n
with ,您没有提及您看到的并行运行的进程-P
数。Convert.py
作为建议,如果您受 I/O 限制,您可以尝试使用 SSD 块设备,或者尝试在 tmpfs 中进行处理(当然,在这种情况下您应该检查是否有足够的内存,避免由于 tmpfs 导致的交换)压力(我认为),以及首先将数据复制到其中的开销)。