我正在测试ipython的一些功能,我认为我做错了。
我测试了3种不同的方法来执行一些数学运算。
@parallel.parallel(view=dview, block=True)
和函数map
我有这段代码:
from IPython import parallel
import numpy as np
import multiprocessing as mp
import time
rc = parallel.Client(block=True)
dview = rc[:]
lbview = rc.load_balanced_view()
@parallel.require(np)
def suma_pll(a, b):
return a + b
@parallel.require(np)
def producto_pll(a, b):
return a * b
def suma(a, b):
return a + b
def producto(a, b):
return a * b
@parallel.parallel(view=dview, block=True)
@parallel.require(np)
@parallel.require(suma_pll)
@parallel.require(producto_pll)
def a_calc_pll(a, b):
result = []
for i, v in enumerate(a):
result.append(
producto_pll(suma_pll(a[i], a[i]), suma_pll(b[i], b[i]))//100
)
return result
@parallel.require(suma)
@parallel.require(producto)
def a_calc_remote(a, b):
result = []
for i, v in enumerate(a):
result.append(
producto(suma(a[i], a[i]), suma(b[i], b[i]))//100
)
return result
def a_calc(a, b):
return producto(suma(a, a), suma(b, b))//100
def main_pll(a, b):
return a_calc_pll.map(a, b)
def main_lb(a, b):
c = lbview.map(a_calc_remote, a, b, block=True)
return c
def main(a, b):
c = []
for i in range(len(a)):
c += [a_calc(a[i], b[i]).tolist()]
return c
if __name__ == '__main__':
a, b = [], []
for i in range(1, 1000):
a.append(np.array(range(i+00, i+10)))
b.append(np.array(range(i+10, i+20)))
t = time.time()
c1 = main_pll(a, b)
t1 = time.time()-t
t = time.time()
c2 = main(a, b)
t2 = time.time()-t
t = time.time()
c3 = main_lb(a, b)
t3 = time.time()-t
print(str(c1) == str(c2))
print(str(c3) == str(c2))
print('%f secs (multicore)' % t1)
print('%f secs (singlecore)' % t2)
print('%f secs (multicore_load_balance)' % t3)
我的结果是:
True
True
0.040741 secs (multicore)
0.004004 secs (singlecore)
1.286592 secs (multicore_load_balance)
为什么我的多核例程比我的单核例程慢?这种方法有什么问题?我该怎么做才能解决它?
一些信息:python3.4.1,ipython 2.2.0,numpy 1.9.0,ipcluster start 8引擎与LocalEngineSetLauncher
答案 0 :(得分:1)
在我看来,您正在尝试并行处理在单个核心上执行时间太短的事情。在Python中,任何形式的" true" parallelism是多进程的,这意味着你必须产生多个Python解释器,通过pickle / unpickling传输数据等。
这将导致小型工作负载的显着开销。在我的系统上,只需启动然后立即停止Python解释器需要大约1/100秒:
# time python -c "pass"
real 0m0.018s
user 0m0.012s
sys 0m0.005s
我不确定你正在使用的装饰器在幕后做什么,但正如你所看到的那样,为并行工作设置基础设施可能需要相当长的时间。
修改强>
进一步检查时,您似乎已经在运行代码之前设置了工作人员,因此上面提到的开销可能不在图片之内。
您正在将数据移动到工作进程,这两个列表包含1000个NumPy数组。对我的系统中的字符串进行腌制a
和b
,pickle
需要约0.13秒,cPickle
需要约0.046秒。通过将数组存储在NumPy数组中而不是列表中,可以减少酸洗时间:
a = np.array(a)
b = np.array(b)
这会将cPickle
时间减少到约0.029秒。