Python:多重处理比顺序处理花费的时间更长,为什么?

问题描述 投票:0回答:1

我有这段代码,它生成 2,000,000 个均匀分布在边界框中的点,并根据某些标准进行一些计算来划分点。

import numpy as np

from draw import draw
import time

X = 0
Y = 1
N = 2000000

max_x = -100000
max_y = -100000
min_x = 100000
min_y = 100000

points = np.random.uniform(-10, 10, (N, 2))

start = time.time()
max_x_index = np.argmax(points[:, X])
max_y_index = np.argmax(points[:, Y])
min_x_index = np.argmin(points[:, X])
min_y_index = np.argmin(points[:, Y])

p_right = points[max_x_index]
p_top = points[max_y_index]
p_left = points[min_x_index]
p_bottom = points[min_y_index]

top_right = points[
points[:, X] > ((points[:, Y] - p_top[Y]) / (p_right[Y] - p_top[Y])) * (p_right[X] - p_top[X]) + p_top[X]]
top_left = points[
points[:, X] < ((points[:, Y] - p_top[Y]) / (p_left[Y] - p_top[Y])) * (p_left[X] - p_top[X]) + p_top[X]]
bottom_right = points[
points[:, X] > ((points[:, Y] - p_bottom[Y]) / (p_right[Y] - p_bottom[Y])) * (p_right[X] - p_bottom[X]) + p_bottom[
X]]
bottom_left = points[
points[:, X] < ((points[:, Y] - p_bottom[Y]) / (p_left[Y] - p_bottom[Y])) * (p_left[X] - p_bottom[X]) + p_bottom[X]]

end = time.time()
print(end - start)

输出通常为0.09,单位为秒。最耗时的部分是最后四次计算以获得top_right、top_left、bottom_right和bottom_left。我重写代码如下

import numpy as np
from draw import draw
import time
import multiprocessing

N = 2000000
X = 0
Y = 1
points = np.random.uniform(-10, 10, (N, 2))

max_x = -100000
max_y = -100000
min_x = 100000
min_y = 100000

manager = multiprocessing.Manager()
top_right = manager.list()
top_left = manager.list()
bottom_right = manager.list()
bottom_left = manager.list()


def set_top_right():
    global X, Y, points, p_top, p_right, top_right
    top_right.extend(points[
        points[:, X] > ((points[:, Y] - p_top[Y]) / (p_right[Y] - p_top[Y])) * (p_right[X] - p_top[X]) + p_top[X]])


def set_top_left():
    global X, Y, points, p_top, p_left, top_left
    top_left.extend(points[
        points[:, X] < ((points[:, Y] - p_top[Y]) / (p_left[Y] - p_top[Y])) * (p_left[X] - p_top[X]) + p_top[X]])


def set_bottom_right():
    global X, Y, points, p_bottom, p_right, bottom_right
    bottom_right.extend(points[
        points[:, X] > ((points[:, Y] - p_bottom[Y]) / (p_right[Y] - p_bottom[Y])) * (p_right[X] - p_bottom[X]) +
        p_bottom[X]])


def set_bottom_left():
    global X, Y, points, p_bottom, p_left, bottom_left
    bottom_left.extend(points[
        points[:, X] < ((points[:, Y] - p_bottom[Y]) / (p_left[Y] - p_bottom[Y])) * (p_left[X] - p_bottom[X]) +
        p_bottom[X]])


start = time.time()
max_x_index = np.argmax(points[:, X])
max_y_index = np.argmax(points[:, Y])
min_x_index = np.argmin(points[:, X])
min_y_index = np.argmin(points[:, Y])

p_right = points[max_x_index]
p_top = points[max_y_index]
p_left = points[min_x_index]
p_bottom = points[min_y_index]

p1 = multiprocessing.Process(target=set_top_right)
p2 = multiprocessing.Process(target=set_top_left)
p3 = multiprocessing.Process(target=set_bottom_right)
p4 = multiprocessing.Process(target=set_bottom_left)

p1.start()
p2.start()
p3.start()
p4.start()

p1.join()
p2.join()
p3.join()
p4.join()

end = time.time()

print(end - start)

令人惊讶的是,情况变得更糟,大约 0.15 秒。我对 Python 几乎是新手,但是,我想这两种方法都是单线程并且没有 I.O。运营。我的笔记本电脑 CPU 是

core i5
第 11 代,我希望每个核心都采用其中一个进程并使其速度更快。那为什么这么慢呢?

python multiprocessing
1个回答
0
投票

使用

multiprocessing.Manager.List
进行多处理不会更快,您将因复制状态而产生 IPC 开销。现在,您可能可以有效地将
multiprocessing.SharedMemory
与 numpy 数组一起使用,但是,我还建议使用
numexpr
,对于以下内容:

import numpy as np
import numexpr as ne

import time


X = 0
Y = 1
N = 2000000

max_x = -100000
max_y = -100000
min_x = 100000
min_y = 100000

points = np.random.uniform(-10, 10, (N, 2))

max_x_index = np.argmax(points[:, X])
max_y_index = np.argmax(points[:, Y])
min_x_index = np.argmin(points[:, X])
min_y_index = np.argmin(points[:, Y])

p_right = points[max_x_index]
p_top = points[max_y_index]
p_left = points[min_x_index]
p_bottom = points[min_y_index]

start = time.perf_counter()


top_right = points[
    points[:, X] > ((points[:, Y] - p_top[Y]) / (p_right[Y] - p_top[Y])) * (p_right[X] - p_top[X]) + p_top[X]
]
top_left = points[
    points[:, X] < ((points[:, Y] - p_top[Y]) / (p_left[Y] - p_top[Y])) * (p_left[X] - p_top[X]) + p_top[X]
]
bottom_right = points[
    points[:, X] > ((points[:, Y] - p_bottom[Y]) / (p_right[Y] - p_bottom[Y])) * (p_right[X] - p_bottom[X]) + p_bottom[X]
]
bottom_left = points[
    points[:, X] < ((points[:, Y] - p_bottom[Y]) / (p_left[Y] - p_bottom[Y])) * (p_left[X] - p_bottom[X]) + p_bottom[X]
]

print(time.perf_counter() - start)

start = time.perf_counter()

top_right = points[
    ne.evaluate(
        # points[:, X] > ((points[:, Y] - p_top[Y]) / (p_right[Y] - p_top[Y])) * (p_right[X] - p_top[X]) + p_top[X]
        "pointsX > ((pointsY - p_topY) / (p_rightY - p_topY)) * (p_rightX - p_topX) + p_topX",
        dict(pointsX=points[:, X], pointsY=points[:, Y], p_topY=p_top[Y], p_rightY=p_right[Y], p_rightX=p_right[X], p_topX=p_top[X])
    )
]
top_left = points[
    # points[:, X] < ((points[:, Y] - p_top[Y]) / (p_left[Y] - p_top[Y])) * (p_left[X] - p_top[X]) + p_top[X]
    ne.evaluate(
        "pointsX < ((pointsY - p_topY) / (p_leftY - p_topY)) * (p_leftX - p_topX) + p_topX",
        dict(pointsX=points[:, X], pointsY=points[:, Y], p_topY=p_top[Y], p_leftY=p_left[Y], p_leftX=p_left[X], p_topX=p_top[X])
    )
]
bottom_right = points[
    # points[:, X] > ((points[:, Y] - p_bottom[Y]) / (p_right[Y] - p_bottom[Y])) * (p_right[X] - p_bottom[X]) + p_bottom[X]
    ne.evaluate(
        "pointsX > ((pointsY - p_bottomY) / (p_rightY - p_bottomY)) * (p_rightX - p_bottomX) + p_bottomX",
        dict(pointsX=points[:, X], pointsY=points[:, Y], p_bottomY=p_bottom[Y], p_rightY=p_right[Y], p_rightX=p_right[X], p_bottomX=p_bottom[X])
    )
]
bottom_left = points[
    #points[:, X] < ((points[:, Y] - p_bottom[Y]) / (p_left[Y] - p_bottom[Y])) * (p_left[X] - p_bottom[X]) + p_bottom[X]
    ne.evaluate(
        "pointsX < ((pointsY - p_bottomY) / (p_leftY - p_bottomY)) * (p_leftX - p_bottomX) + p_bottomX",
        dict(pointsX=points[:, X], pointsY=points[:, Y], p_bottomY=p_bottom[Y], p_leftY=p_left[Y], p_leftX=p_left[X], p_bottomX=p_bottom[X])
        
    )
]
print(time.perf_counter() - start)

我得到的结果如下:

(py312) Juans-MBP:foo juan$ python testing.py
0.13140409300103784
0.0861169679556042
(py312) Juans-MBP:foo juan$ python testing.py
0.14112660207320005
0.10199439595453441
(py312) Juans-MBP:foo juan$ python testing.py
0.11003640200942755
0.10297299490775913
(py312) Juans-MBP:foo juan$ python testing.py
0.09756439505144954
0.08654426701832563
(py312) Juans-MBP:foo juan$ python testing.py
0.16173010191414505
0.09075463504996151
(py312) Juans-MBP:foo juan$ python testing.py
0.12655663397163153
0.08906243299134076
(py312) Juans-MBP:foo juan$ python testing.py
0.128101791953668
0.08784269192256033
(py312) Juans-MBP:foo juan$ python testing.py
0.13670661801006645
0.09372905897907913

始终更快。如果您多次对

np.evaluate("expression")
运行相同的调用,则不必每次都重新编译表达式(因此可能会更快)。

© www.soinside.com 2019 - 2024. All rights reserved.