for循环中的多处理
Multiprocessing in for loop
假设我有一个字典,其中每个元素都是一个由 GPS 坐标元组定义的四边形,并且还有一个元组包含 GPS 坐标的起点和终点的一堆旅行:(((origin_latitude, origin_longitude), (dest_latitude,dest_longitude)),((...),(...)))。这是两个四边形和两次旅行的示例:
dictionary={0:((0,0),(0,1),(1,1),(1,0)),1:((3,3),(3,4),(4,4),(4,3))}
trips=(((0.5,0.5),(3.5,3.5)),((-1,-1),(-2,-2)))
我想把每趟行程分类为出发地四边形编号、目的地四边形编号、出发地和目的地之间的组合编号(行程参考号)。我是这样做的:
import matplotlib.path as mplPath
def is_in_zone(quadri,point):
bbPath = mplPath.Path(quadri)
return bbPath.contains_point(point)
def get_zone_nbr(dictio,trip):
start_zone=-1
end_zone=-1
trip_ref=-1
for key,coordinates in dictio.iteritems():
if is_in_zone(coordinates,trip[0]):
start_zone=key
if is_in_zone(coordinates,trip[1]):
end_zone=key
if start_zone>-1 and end_zone>-1:
trip_ref=len(dictio)*start_zone+end_zone
break
return (start_zone,end_zone,trip_ref)
if __name__=='__main__':
dictionary={0:((0,0),(0,1),(1,1),(1,0)),1:((3,3),(3,4),(4,4),(4,3))}
trips=(((0.5,0.5),(3.5,3.5)),((-1,-1),(-2,-2)))
for t in trips:
get_zone_nbr(dictionary,t)
我的字典长度大约为 30,所以函数 get_zone_nbr 会很慢。我有数百万次旅行要处理。您是否看到任何明显的优化 get_zone_nbr() 的方法?或任何可以使此代码 运行 更快的东西(例如多处理,但我不确定如何将其与循环一起使用)。
第一个简单的并行性是并行处理您的行程。
>>> import matplotlib.path as mplPath
>>> def is_in_zone(quadri,point):
... bbPath = mplPath.Path(quadri)
... return bbPath.contains_point(point)
...
>>> def get_zone_nbr(dictio,trip):
... start_zone=-1
... end_zone=-1
... trip_ref=-1
... for key,coordinates in dictio.iteritems():
... if is_in_zone(coordinates,trip[0]):
... start_zone=key
... if is_in_zone(coordinates,trip[1]):
... end_zone=key
... if start_zone>-1 and end_zone>-1:
... trip_ref=len(dictio)*start_zone+end_zone
... break
... return (start_zone,end_zone,trip_ref)
...
>>> dictionary={0:((0,0),(0,1),(1,1),(1,0)),1:((3,3),(3,4),(4,4),(4,3))}
>>> trips=(((0.5,0.5),(3.5,3.5)),((-1,-1),(-2,-2)))
>>>
>>> from pathos.pools import ThreadPool
>>> pool = ThreadPool()
>>>
>>> results = pool.map(lambda x: get_zone_nbr(dictionary, x), trips)
>>> results
[(0, 1, 1), (-1, -1, -1)]
我正在使用 pathos
,这是一个 multiprocessing
分支,可提供更好的序列化、灵活性和交互性。 (我也是作者。)
然后您还可以应用相同的方法将函数内的 for 循环 get_zone_nbr
转换为 map 函数调用。 pathos
允许您使用带有多个参数的 map
调用。由于您正在处理字典项目,并且项目自然是无序的,因此您可以使用 "unordered iterated map"(在 pathos
中是 uimap
,但在 multiprocessing
中是 imap_unordered
).
我还建议您为代码计时,看看哪个 map
调用会更快。 map
调用有几种不同的变体,以及几种不同的并行后端。我在上面使用了一个线程池,但也有跨进程和套接字的并行(后者对你的情况来说太慢了)。 pathos
为所有选择提供统一的 API,因此您只需编写一次代码,然后放入任何其他 pools/maps,直到找到适合您情况的最快的.
在此处获取 pathos
:https://github.com/uqfoundation
假设我有一个字典,其中每个元素都是一个由 GPS 坐标元组定义的四边形,并且还有一个元组包含 GPS 坐标的起点和终点的一堆旅行:(((origin_latitude, origin_longitude), (dest_latitude,dest_longitude)),((...),(...)))。这是两个四边形和两次旅行的示例:
dictionary={0:((0,0),(0,1),(1,1),(1,0)),1:((3,3),(3,4),(4,4),(4,3))}
trips=(((0.5,0.5),(3.5,3.5)),((-1,-1),(-2,-2)))
我想把每趟行程分类为出发地四边形编号、目的地四边形编号、出发地和目的地之间的组合编号(行程参考号)。我是这样做的:
import matplotlib.path as mplPath
def is_in_zone(quadri,point):
bbPath = mplPath.Path(quadri)
return bbPath.contains_point(point)
def get_zone_nbr(dictio,trip):
start_zone=-1
end_zone=-1
trip_ref=-1
for key,coordinates in dictio.iteritems():
if is_in_zone(coordinates,trip[0]):
start_zone=key
if is_in_zone(coordinates,trip[1]):
end_zone=key
if start_zone>-1 and end_zone>-1:
trip_ref=len(dictio)*start_zone+end_zone
break
return (start_zone,end_zone,trip_ref)
if __name__=='__main__':
dictionary={0:((0,0),(0,1),(1,1),(1,0)),1:((3,3),(3,4),(4,4),(4,3))}
trips=(((0.5,0.5),(3.5,3.5)),((-1,-1),(-2,-2)))
for t in trips:
get_zone_nbr(dictionary,t)
我的字典长度大约为 30,所以函数 get_zone_nbr 会很慢。我有数百万次旅行要处理。您是否看到任何明显的优化 get_zone_nbr() 的方法?或任何可以使此代码 运行 更快的东西(例如多处理,但我不确定如何将其与循环一起使用)。
第一个简单的并行性是并行处理您的行程。
>>> import matplotlib.path as mplPath
>>> def is_in_zone(quadri,point):
... bbPath = mplPath.Path(quadri)
... return bbPath.contains_point(point)
...
>>> def get_zone_nbr(dictio,trip):
... start_zone=-1
... end_zone=-1
... trip_ref=-1
... for key,coordinates in dictio.iteritems():
... if is_in_zone(coordinates,trip[0]):
... start_zone=key
... if is_in_zone(coordinates,trip[1]):
... end_zone=key
... if start_zone>-1 and end_zone>-1:
... trip_ref=len(dictio)*start_zone+end_zone
... break
... return (start_zone,end_zone,trip_ref)
...
>>> dictionary={0:((0,0),(0,1),(1,1),(1,0)),1:((3,3),(3,4),(4,4),(4,3))}
>>> trips=(((0.5,0.5),(3.5,3.5)),((-1,-1),(-2,-2)))
>>>
>>> from pathos.pools import ThreadPool
>>> pool = ThreadPool()
>>>
>>> results = pool.map(lambda x: get_zone_nbr(dictionary, x), trips)
>>> results
[(0, 1, 1), (-1, -1, -1)]
我正在使用 pathos
,这是一个 multiprocessing
分支,可提供更好的序列化、灵活性和交互性。 (我也是作者。)
然后您还可以应用相同的方法将函数内的 for 循环 get_zone_nbr
转换为 map 函数调用。 pathos
允许您使用带有多个参数的 map
调用。由于您正在处理字典项目,并且项目自然是无序的,因此您可以使用 "unordered iterated map"(在 pathos
中是 uimap
,但在 multiprocessing
中是 imap_unordered
).
我还建议您为代码计时,看看哪个 map
调用会更快。 map
调用有几种不同的变体,以及几种不同的并行后端。我在上面使用了一个线程池,但也有跨进程和套接字的并行(后者对你的情况来说太慢了)。 pathos
为所有选择提供统一的 API,因此您只需编写一次代码,然后放入任何其他 pools/maps,直到找到适合您情况的最快的.
在此处获取 pathos
:https://github.com/uqfoundation