【发布时间】:2018-09-19 13:05:23
【问题描述】:
所以一位朋友注意到了对numpy 的一些好奇。这是一个最小的示例,它首先串行运行相同的脚本,而不是两个实例在各自的进程中并行运行:
#!/bin/bash
# This is runner.sh
fl=/tmp/$(mktemp test_XXXXX.py)
trap "rm -fv '$fl'" EXIT
cat - > "$fl" <<-'EndOfHereDoc'
#!/usr/bin/env python
import numpy as np
import sys
if __name__ == '__main__':
if len(sys.argv)>1: print(sys.argv[1] +' start: '+ str(datetime.datetime.now()))
cube_size=100
cube=np.zeros((cube_size,cube_size,cube_size))
cube_ones=np.ones((cube_size,cube_size,cube_size))
for x in range(10000):
np.add(cube_ones,cube,out=cube)
if len(sys.argv)>1: print(sys.argv[1] +' start: '+ str(datetime.datetime.now()))
EndOfHereDoc
echo "Serial"
time python "$fl" 0
echo
echo "Parallel"
time python "$fl" 1&
time python3 "$fl" 2&
wait
rm -fv "$fl"
trap '' EXIT
其输出为:
$ runner.sh
Serial
0 start: 2018-09-19 15:46:52.540881
0 end: 2018-09-19 15:47:04.592280
real 0m12,105s
user 0m12,084s
sys 0m0,020s
Parallel
1 start: 2018-09-19 15:47:04.665260
2 start: 2018-09-19 15:47:04.780635
2 end: 2018-09-19 15:47:27.053261
real 0m22,480s
user 0m22,448s
sys 0m0,128s
1 end: 2018-09-19 15:47:27.097312
real 0m22,505s
user 0m22,409s
sys 0m0,040s
removed '/tmp/test_zWN0V.py'
没有加速。就好像进程一个接一个地运行。我假设 numpy 只使用一个资源,而另一个进程等待该资源被释放。 但是这里到底发生了什么? GIL 应该只是多线程的问题,而不是多进程的问题,对吧?我觉得特别奇怪,p2 不只是在等待 p1 完成。相反,这两个过程都需要大约 22 秒才能完成。我希望一个人获得资源并在一半的时间内完成。而另一个等到第一个释放它并需要额外的约 12 秒。
请注意,在 Pool 中使用 python 自己的 multiprocessing 模块运行 python 代码时也会发生这种情况。但是,如果您执行不涉及某些特定 numpy 函数的操作,例如:
cube_size=25
cube=[0 for i in range(cube_size**3)]
for x in range(10000):
cube = [ value + 1 for value in cube]
编辑:
我有一个真正的 4 核 CPU。我一直牢记超线程,这不是这里的问题。在单进程部分,一个 CPU 处于 100%,其余的空闲。在两个进程部分中,两个处于 100%,其余处于空闲状态(根据 htop)。我知道 numpy 在后台运行 ATLAS、LAPACK 和 BLAS 库,它们不是 Python(实际上是纯 C 或 Fortran)。这些可能会利用并行技术。我的问题是,为什么 CPU 利用率没有显示出来?
【问题讨论】:
-
也许你只有一个单核 CPU?或 RAM 不足 - 尝试使用
/usr/bin/time -l python ...运行并查看最大工作集。 -
@MarkSetchell 看时序输出。并行进程肯定是并行运行的。这里的问题是 numpy is 已经是多线程的(或者可以是)并且擅长多线程,尽管有 GIL(因为 numpy 所做的大部分事情都不使用解释器)。跨度>
-
@Dunes - 是的,你是对的,谢谢。
-
仅作记录,我有一个四核 CPU。顺便提一句。为了防止其他人自欺欺人,超线程将显示为比您实际拥有的更多 CPU 内核,并且可以在 100% 的利用率下高效地使用。我的后续问题是,如果 numpy 已经并行运行,为什么在单进程示例中只有一个 100% 的核心,而其余的则空闲?
标签: python performance numpy multiprocessing