Py学习  »  Python

python多处理比常规的慢。我该如何改进?

wowohweewah • 5 年前 • 1626 次点击  

基本上有一个脚本,它对节点/点的数据集进行梳理,以删除重叠的节点/点。实际的脚本更复杂,但我把它简化为基本上一个简单的重叠检查,它对演示没有任何作用。

我尝试了一些锁、队列、池的变体,一次添加一个作业,而不是批量添加。一些最严重的犯罪者的速度慢了几个数量级。最终我以最快的速度完成了任务。

发送到各个进程的重叠检查算法:

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万次迭代,而实际情况有更多的迭代,我觉得奇怪的是,多处理速度慢了一个数量级。

我缺少什么/我能做些什么来改进?

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/42992
 
1626 次点击  
文章 [ 1 ]  |  最新文章 5 年前