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,直到找到适合您情况的最快的.

在此处获取 pathoshttps://github.com/uqfoundation