Python多处理即使在单线程中也减慢了速度

时间:2018-08-17 15:06:33

标签: python multithreading numpy multiprocessing

我想使用多进程并行运行相同的代码。

我的过程代码仅在8分钟内运行。在10分钟内使用“强制单线程”的东西。但是,当我并行运行24个实例时,每个实例大约需要1个小时。

之前,当每个进程像疯子一样疯狂地跨线程时,我有1.6M的上下文切换。 然后,我使用了以下环境。强制Numpy每个进程仅使用一个线程的变量:

os.environ["NUMEXPR_NUM_THREADS"] = '1'
os.environ["OMP_NUM_THREADS"] = '1'
os.environ["MKL_THREADING_LAYER"] = "sequential"  # Better than setting MKL_NUM_THREADS=1 (source: https://software.intel.com/en-us/node/528380)

即使在那之后,我的问题仍然存在。我每个进程大约需要1个小时的运行时间。 使用一览表,除了CPU使用率在95-100%(一览表为红色)之外,其余部分都是绿色,内存,带宽,甚至上下文切换都在5K左右恢复正常。

您是否知道为什么会这样?我不明白为什么当没有明显的指示器一眼就弹出时并行速度要慢6倍

以下是扫视的屏幕截图glances output

2 个答案:

答案 0 :(得分:0)

对于我的特定问题,我找到了答案。看来这是由于我的硬件而不是代码。

该代码可以在其他16个CPU的服务器上正常运行。当使用其中的15个时,我得到了8分钟的时间,这正是我想要的。

我认为旧服务器中的某些东西使多进程处理变慢。

旧服务器不起作用:

processor   : 23
vendor_id   : AuthenticAMD
cpu family  : 16
model       : 8
model name  : Six-Core AMD Opteron(tm) Processor 8439 SE
stepping    : 0
cpu MHz     : 2800.000
cache size  : 512 KB
physical id : 3
siblings    : 6
core id     : 5
cpu cores   : 6
apicid      : 29
initial apicid  : 29
fpu     : yes
fpu_exception   : yes
cpuid level : 5
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm 3dnowext 3dnow constant_tsc rep_good nopl nonstop_tsc extd_apicid pni monitor cx16 popcnt lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs skinit wdt hw_pstate vmmcall npt lbrv svm_lock nrip_save pausefilter
bugs        : tlb_mmatch fxsave_leak sysret_ss_attrs null_seg amd_e400 spectre_v1 spectre_v2
bogomips    : 5600.33
TLB size    : 1024 4K pages
clflush size    : 64
cache_alignment : 64
address sizes   : 48 bits physical, 48 bits virtual
power management: ts ttp tm stc 100mhzsteps hwpstate

新服务器在其上运行:

processor   : 15
vendor_id   : GenuineIntel
cpu family  : 6
model       : 42
model name  : Intel Xeon E312xx (Sandy Bridge)
stepping    : 1
microcode   : 0x1
cpu MHz     : 2599.998
cache size  : 16384 KB
physical id : 1
siblings    : 8
core id     : 7
cpu cores   : 8
apicid      : 15
initial apicid  : 15
fpu     : yes
fpu_exception   : yes
cpuid level : 13
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good nopl xtopology eagerfpu pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx hypervisor lahf_lm arat xsaveopt
bogomips    : 5199.99
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management:

答案 1 :(得分:0)

没有“最小代码示例”,确实很难回答,因此,我将提供一些代码,而不是直接回答。我已经尝试过:

import os
os.environ['OMP_NUM_THREADS'] = '1'
import numpy as np
import time
def tns(): return time.time_ns() / 1e9

def nps(vec, its=100): 
    return min(np.linalg.norm(vec - np.random.randn(len(vec))) for _ in range(its))

start = tns()
s = nps(np.random.randn(100_000))
end = tns()
print("{} took {}".format(s, end - start))

在我的机器上,设置OMP_NUM_THREADS=1可以使速度提高约2.5倍。我从freenode上的#numpy收到的解释是我的代码受内存限制,因此多线程将无济于事。