【发布时间】:2018-11-21 21:44:11
【问题描述】:
基本上有一个脚本来梳理节点/点的数据集以删除那些重叠的。实际的脚本更复杂,但我将其缩减为基本上是一个简单的重叠检查,对演示没有任何作用。
我尝试了几种使用锁、队列、池的变体,一次添加一项作业而不是批量添加。一些最严重的违规者的速度要慢几个数量级。最终,我以最快的速度完成了它。
发送到各个进程的重叠检查算法:
def check_overlap(args):
tolerance = args['tolerance']
this_coords = args['this_coords']
that_coords = args['that_coords']
overlaps = False
distance_x = this_coords[0] - that_coords[0]
if distance_x <= tolerance:
distance_x = pow(distance_x, 2)
distance_y = this_coords[1] - that_coords[1]
if distance_y <= tolerance:
distance = pow(distance_x + pow(distance_y, 2), 0.5)
if distance <= tolerance:
overlaps = True
return overlaps
处理函数:
def process_coords(coords, num_processors=1, tolerance=1):
import multiprocessing as mp
import time
if num_processors > 1:
pool = mp.Pool(num_processors)
start = time.time()
print "Start script w/ multiprocessing"
else:
num_processors = 0
start = time.time()
print "Start script w/ standard processing"
total_overlap_count = 0
# outer loop through nodes
start_index = 0
last_index = len(coords) - 1
while start_index <= last_index:
# nature of the original problem means we can process all pairs of a single node at once, but not multiple, so batch jobs by outer loop
batch_jobs = []
# inner loop against all pairs for this node
start_index += 1
count_overlapping = 0
for i in range(start_index, last_index+1, 1):
if num_processors:
# add job
batch_jobs.append({
'tolerance': tolerance,
'this_coords': coords[start_index],
'that_coords': coords[i]
})
else:
# synchronous processing
this_coords = coords[start_index]
that_coords = coords[i]
distance_x = this_coords[0] - that_coords[0]
if distance_x <= tolerance:
distance_x = pow(distance_x, 2)
distance_y = this_coords[1] - that_coords[1]
if distance_y <= tolerance:
distance = pow(distance_x + pow(distance_y, 2), 0.5)
if distance <= tolerance:
count_overlapping += 1
if num_processors:
res = pool.map_async(check_overlap, batch_jobs)
results = res.get()
for r in results:
if r:
count_overlapping += 1
# stuff normally happens here to process nodes connected to this node
total_overlap_count += count_overlapping
print total_overlap_count
print " time: {0}".format(time.time() - start)
及测试功能:
from random import random
coords = []
num_coords = 1000
spread = 100.0
half_spread = 0.5*spread
for i in range(num_coords):
coords.append([
random()*spread-half_spread,
random()*spread-half_spread
])
process_coords(coords, 1)
process_coords(coords, 4)
尽管如此,非多处理始终在不到 0.4 秒的时间内运行,而多处理我可以得到略低于 3.0 秒的运行时间。我知道这里的算法可能太简单而无法真正获得收益,但考虑到上述情况有近 50 万次迭代,而实际情况有更多,多处理速度慢了一个数量级对我来说很奇怪。
我缺少什么/我可以做些什么来改进?
【问题讨论】:
-
那么您是否尝试过在实际数据上实际运行它并确定多处理是否值得?例如,不要使用 500 万,而是使用 500 万,看看会发生什么?过早的优化可能会花费您大量时间
-
@IanQuah,我尝试过一次,速度较慢,但我使用了一种被废弃的方法,结果证明效率低下,因此进行了隔离和试验。也就是说,在这一点上,这更像是个人的好奇心。如果我不能让这样一个看似简单的用例受益,我什么时候使用 python 多处理?
-
@Darkonaut 是的,我读到的更多信息似乎与我对它的其他熟悉程度(主要是在 Java 中)相比,Python 在多处理方面有很多开销。也就是说,这些链接中的 numpy 建议是基本数学运算的一个很好的解决方法。
标签: python multiprocessing python-multiprocessing