在 Python3 中混合使用并行和子进程,导致 CPU 效率随着时间的推移而降低?
Mixed use of Parallel and subprocess in Python3, causing lower CPU efficiency over time?
我正在 运行ning 一个包含 3 个主要功能的 Python3 脚本。 somefunction()
使用子进程从另一个程序获取结果 "eval"; foo()
在 somefunction()
上应用并行; bar()
包含重复调用 foo()
的 for 循环。
from joblib import Parallel, delayed
import subprocess
class Foobar:
def somefunction(self, i):
cmdline = '~/path/eval ' + 'i' # eval is an executable
output = subprocess.check_output(cmdline, shell=True)
return output
def foo(self):
# Parallel
num_cores = multiprocessing.cpu_count()
list = Parallel(n_jobs=num_cores)(delayed(self.somefunction)(i) for i in somerange)
def bar(self):
for i in range(1000):
self.foo()
result = Foobar()
result.bar()
我运行在具有 10vCPU 的 Google 计算 VM 实例上执行此操作。一开始10个CPU都是运行ning,到运行foo()
用了1分钟。然而,随着时间的推移,运行ning CPU 的数量越来越少,因此需要 5+ 分钟才能达到 运行 foo()
。
我认为问题是由 subprocess
和 Parallel
的混合使用引起的,我试图通过如下更改 somefunction()
来排除 subprocess
和问题消失了。
def somefunction(self, i):
for k in range(100000):
k += 1
return k
原始代码中发生了什么?重构它的优雅方法是什么?
我终于通过将多处理更改为多线程来解决了这个问题:
Parallel(n_jobs=num_cores)(delayed(self.somefunction)(i) for i in somerange)
至
Parallel(n_jobs=num_cores, prefer="threads")(delayed(self.somefunction)(i) for i in somerange)
我正在 运行ning 一个包含 3 个主要功能的 Python3 脚本。 somefunction()
使用子进程从另一个程序获取结果 "eval"; foo()
在 somefunction()
上应用并行; bar()
包含重复调用 foo()
的 for 循环。
from joblib import Parallel, delayed
import subprocess
class Foobar:
def somefunction(self, i):
cmdline = '~/path/eval ' + 'i' # eval is an executable
output = subprocess.check_output(cmdline, shell=True)
return output
def foo(self):
# Parallel
num_cores = multiprocessing.cpu_count()
list = Parallel(n_jobs=num_cores)(delayed(self.somefunction)(i) for i in somerange)
def bar(self):
for i in range(1000):
self.foo()
result = Foobar()
result.bar()
我运行在具有 10vCPU 的 Google 计算 VM 实例上执行此操作。一开始10个CPU都是运行ning,到运行foo()
用了1分钟。然而,随着时间的推移,运行ning CPU 的数量越来越少,因此需要 5+ 分钟才能达到 运行 foo()
。
我认为问题是由 subprocess
和 Parallel
的混合使用引起的,我试图通过如下更改 somefunction()
来排除 subprocess
和问题消失了。
def somefunction(self, i):
for k in range(100000):
k += 1
return k
原始代码中发生了什么?重构它的优雅方法是什么?
我终于通过将多处理更改为多线程来解决了这个问题:
Parallel(n_jobs=num_cores)(delayed(self.somefunction)(i) for i in somerange)
至
Parallel(n_jobs=num_cores, prefer="threads")(delayed(self.somefunction)(i) for i in somerange)