运行多个python程序时的高内核CPU

我开发了一个庞大的数值计算python程序。 我运行在32位Xeon CPU,64GB内存和Ubuntu 14.04 64位的Linux机器上。 我并行启动多个具有不同模型参数的python实例,以使用多个进程而不必担心全局解释器锁(GIL)。 当我使用htop监视CPU利用率时,我发现所有内核都被使用,但大部分时间是由内核使用的。 一般来说,内核时间是用户时间的两倍多。 我担心系统级别会有很多开销,但我无法find原因。

如何减less高内核CPU使用率?

这是我做的一些观察:

  • 这种效果与我是运行10个作业还是50无关。如果作业less于核心,则不是使用所有核心,但使用的核心仍然具有较高的CPU使用率
  • 我使用numba实现了内部循环,但问题与此无关,因为删除numba部分不能解决问题
  • 我也认为这可能与使用python2类似于这个问题中提到的问题,但从python2切换到python3并没有太大的改变
  • 我测量了由OS执行的上下文切换总数,每秒大约10000次。 我不确定这是否是一个很大的数字
  • 我试图通过设置sys.setcheckinterval(10000) (python2)和sys.setswitchinterval(10) (python3)来增加python时间片,但没有一个帮助
  • 我试图通过运行schedtool -B PID影响任务调度器,但是这没有帮助

编辑:这是htop的截图: 在这里输入图像说明

我也运行perf record -a -g ,这是由perf report -g graph

 Samples: 1M of event 'cycles', Event count (approx.): 1114297095227 - 95.25% python3 [kernel.kallsyms] [k] _raw_spin_lock_irqsave ◆ - _raw_spin_lock_irqsave ▒ - 95.01% extract_buf ▒ extract_entropy_user ▒ urandom_read ▒ vfs_read ▒ sys_read ▒ system_call_fastpath ▒ __GI___libc_read ▒ - 2.06% python3 [kernel.kallsyms] [k] sha_transform ▒ - sha_transform ▒ - 2.06% extract_buf ▒ extract_entropy_user ▒ urandom_read ▒ vfs_read ▒ sys_read ▒ system_call_fastpath ▒ __GI___libc_read ▒ - 0.74% python3 [kernel.kallsyms] [k] _mix_pool_bytes ▒ - _mix_pool_bytes ▒ - 0.74% __mix_pool_bytes ▒ extract_buf ▒ extract_entropy_user ▒ urandom_read ▒ vfs_read ▒ sys_read ▒ system_call_fastpath ▒ __GI___libc_read ▒ 0.44% python3 [kernel.kallsyms] [k] extract_buf ▒ 0.15% python3 python3.4 [.] 0x000000000004b055 ▒ 0.10% python3 [kernel.kallsyms] [k] memset ▒ 0.09% python3 [kernel.kallsyms] [k] copy_user_generic_string ▒ 0.07% python3 multiarray.cpython-34m-x86_64-linux-gnu.so [.] 0x00000000000b4134 ▒ 0.06% python3 [kernel.kallsyms] [k] _raw_spin_unlock_irqresto▒ 0.06% python3 python3.4 [.] PyEval_EvalFrameEx 

似乎大部分时间都花在调用_raw_spin_lock_irqsave 。 不过,我不知道这意味着什么。

如果内核中存在问题,则应使用诸如OProfile或perf等分析器来缩小问题的范围。

即运行perf record -a -g并使用perf report将读取的分析数据保存到perf data 。 另请参阅: linux perf:如何解释和查找热点 。


在你的情况下,高CPU使用率是由于竞争/dev/urandom引起的 – 它只允许一个线程从中读取,但是多个Python进程正在这样做。

Python模块random只用于初始化。 即:

 $ strace python -c 'import random; while True: random.random()' open("/dev/urandom", O_RDONLY) = 4 read(4, "\16\36\366\36}"..., 2500) = 2500 close(4) <--- /dev/urandom is closed 

你也可以通过使用os.urandom或者os.urandom类来显式的请求/dev/urandom 。 所以检查你的代码是处理随机数字。