concurrent.futures.ThreadPoolExecutor比列表理解慢

时间:2017-04-26 15:37:35

标签: python concurrency

我使用list comprehension vs concurrent.futures测试一个简单的函数:

 func tableView(_ tableView: UITableView, 
         didSelectRowAt indexPath: IndexPath)
{
}

测量时间,我得到:

class Test:

    @staticmethod
    def something(times = 1):
        return sum([1 for i in range(times)])

    @staticmethod
    def simulate1(function, N):
        l = []

        for i in range(N):
            outcome = function()
            l.append(outcome)

        return sum(l) / N

    @staticmethod
    def simulate2(function, N):
        import concurrent.futures

        with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
            l = [outcome for outcome in executor.map(lambda x: function(), range(N))]

        return sum(l) / N

    @staticmethod
    def simulate3(function, N):
        import concurrent.futures

        l = 0

        with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
            futures = [executor.submit(function) for i in range(N)]
            for future in concurrent.futures.as_completed(futures):
                l += future.result()

        return l / N

def simulation():
    simulationRate = 100000

    import datetime

    s = datetime.datetime.now()
    o = Test.simulate1(lambda : Test.something(10), simulationRate)
    print((datetime.datetime.now() - s))

    s = datetime.datetime.now()
    o = Test.simulate2(lambda : Test.something(10), simulationRate)
    print((datetime.datetime.now() - s))

    s = datetime.datetime.now()
    o = Test.simulate3(lambda : Test.something(10), simulationRate)
    print((datetime.datetime.now() - s))

simulation()

我开始使用并发性,所以我不明白阻止线程运行得更快的瓶颈是什么。

1 个答案:

答案 0 :(得分:0)

如果您将任务功能更改为此,您将看到差异:

def something(n):
    """ simulate doing some io based task.
    """
    time.sleep(0.001)
    return sum(1 for i in range(n))

在我的mac pro上,这给出了:

0:00:13.774700
0:00:01.591226
0:00:01.489159

此次,concurrent.future显然更快。

原因是:你正在模拟一个基于cpu的任务,因为python的GIL,concurrent.future使它变慢。

concurrent.future提供了一个用于异步执行callables的高级接口,你将它用于错误的场景。