python - 对于多处理星图来说,这种加速正常吗?
问题描述
代码:
from multiprocessing import Pool
from itertools import repeat
import timeit
import multiprocessing
def add_one(number, flag):
new_number = None
if flag=="a":
new_number = number+1
return (number, new_number)
numbers = list(range(10000000))
pool = Pool(multiprocessing.cpu_count())
for i in range(3):
print(i)
start_time = timeit.default_timer()
flag = "a"
new_numbers = pool.starmap(add_one, zip(numbers, repeat(flag)))
print('time taken: ', timeit.default_timer() - start_time)
池计数配置分别为 3、1 和 multiprocessing.cpu_count()。他们花费的时间如下:
(base) ins-MacBook-Pro-2 graph_test % python test.py
0
time taken: 7.543301321
1
time taken: 7.8004514
2
time taken: 7.892797112
ins-MacBook-Pro-2 graph_test % python test.py
0
time taken: 11.030308790000001
1
time taken: 11.616422934
2
time taken: 11.846459496999998
ins-MacBook-Pro-2 graph_test % python test.py
0
time taken: 6.376773281
1
time taken: 6.876658618999999
2
time taken: 6.518348029
我的 Mac 有 8 个内核。好像没有加速很多。我使用星图的方式正确吗?
解决方案
multiprocessing
对于细粒度的并行性不会产生显着的加速 - 你需要做“大(ger)工作”,因为它在挂钟时间得到回报。
与使用多处理的开销add_one()
相比,调用函数完成的工作简直是微不足道。在幕后,主程序必须挑选参数,通过进程间通信机制发送这些字符串;然后工人必须解开论点;然后该函数会做少量工作来比较一个字符串,并可能将 1 加到一个整数上,然后构建一个 2 元组的结果;然后多处理机器必须再次在幕后腌制那个 2 元组;通过进程间通信机制将pickle发送回主程序;然后主程序必须解开结果字符串,并将生成的 2 元组附加到列表中。"a"
您“看到”支持所有这一切的工作很少,但总的来说,支持工作的成本远远超过调用的成本add_one()
。
要查看与使用的内核数量更一致的加速,add_one()
需要单独花费更多时间,因此并行工作的潜力更大。例如,更改:
if flag=="a":
至
if (flag * 100000)[0] =="a":
不,这不是一个明智的改变。这只是一种add_one()
消耗更多时间的方法,因此您可以看到添加内核确实有帮助。它根本不会改变开销,它只会增加在多处理实现之外需要完成的工作量。制作所有这些无用的“大字符串”可以并且将会并行完成。
注意:不要将“核心”误认为“物理 CPU”。.cpu_count()
通常返回“逻辑”(非物理)核心的数量。对于多处理,物理内核的数量通常更为重要。
推荐阅读
- reactjs - 没有 JSX 的 ReactJS onClick
- php - 具有活动类的 PHP 菜单功能
- mysql - 消息:“方法 Illuminate\Validation\Validator::validateTazker 不存在。”
- ssl - 客户证书公用名?主题替代名称?
- javascript - Django / JQuery - 根据数据库数据更改 JQuery 日历
- reactjs - 如何在专注于一行antd-table时模糊表格的其余部分
- transactions - 发送以太币时如何检查合约调用的返回值?
- android - Android TableLayout - 在屏幕中心动态添加按钮
- r - 满足条件时跟踪最后一次观察的组特定变量
- reactjs - react SPA中的Magic Link身份验证