我有这段代码,它生成 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 代,我希望每个核心都采用其中一个进程并使其速度更快。那为什么这么慢呢?
使用
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")
运行相同的调用,则不必每次都重新编译表达式(因此可能会更快)。