为什么使用Asyncio不会减少Python的总体执行时间并同时运行函数?

时间:2020-09-16 06:50:54

标签: python multithreading async-await multiprocessing python-asyncio

我正在尝试使用asyncio运行一段代码,并减少整个代码的执行时间。下面是我的代码,大约需要6秒钟才能完全执行

常规函数调用-(方法1)

from time import time, sleep
import asyncio


def find_div(range_, divide_by):
    lis_ = []
    for i in range(range_):
        if i % divide_by == 0:
            lis_.append(i)
        
    print("found numbers for range {}, divided by {}".format(range_, divide_by))
    return lis_

if __name__ == "__main__":
    start = time()
    find_div(50800000, 341313)
    find_div(10005200, 32110)
    find_div(50000340, 31238)
    print(time()-start)
    

以上代码的输出仅是总执行时间,即 6秒

多线程方法-(方法2) 在这种情况下使用了多线程,但是令人惊讶的是时间增加了

from time import time, sleep
import asyncio
import threading


def find_div(range_, divide_by):
    lis_ = []
    for i in range(range_):
        if i % divide_by == 0:
            lis_.append(i)
        
    print("found numbers for range {}, divided by {}".format(range_, divide_by))
    return lis_

if __name__ == "__main__":
    start = time()
    t1 = threading.Thread(target=find_div, args=(50800000, 341313)) 
    t2 = threading.Thread(target=find_div, args=(10005200, 32110)) 
    t3 = threading.Thread(target=find_div, args=(50000340, 31238)) 
  
    t1.start() 
    t2.start() 
    t3.start()

    t1.join() 
    t2.join() 
    t3.join()
    print(time()-start)

以上代码的输出为 12秒

多处理方法-(方法3)

from time import time, sleep
import asyncio
from multiprocessing import Pool

def multi_run_wrapper(args):
   return find_div(*args)

def find_div(range_, divide_by):
    lis_ = []
    for i in range(range_):
        if i % divide_by == 0:
            lis_.append(i)
        
    print("found numbers for range {}, divided by {}".format(range_, divide_by))
    return lis_

if __name__ == "__main__":
    start = time()
    with Pool(3) as p:
        p.map(multi_run_wrapper,[(50800000, 341313),(10005200, 32110),(50000340, 31238)])
    
    
    print(time()-start)

多处理代码的输出为 3秒,这比普通的函数调用方法要好。

异步方法-(方法4)

from time import time, sleep

import asyncio

async def find_div(range_, divide_by):
    lis_ = []
    for i in range(range_):
        if i % divide_by == 0:
            lis_.append(i)
        
    print("found numbers for range {}, divided by {}".format(range_, divide_by))
    return lis_


async def task():

    tasks = [find_div(50800000, 341313),find_div(10005200, 32110),find_div(50000340, 31238)]
    result = await asyncio.gather(*tasks)
    print(result)

if __name__ == "__main__":
    start = time()
    asyncio.run(task())
    print(time()-start)

上面的代码还需要大约 6秒,这与通常的执行功能调用(方法1 )相同。

问题-
为什么我的Asyncio方法无法按预期方式工作并减少了总时间?
代码有什么问题?

1 个答案:

答案 0 :(得分:3)

您有专用于CPU的代码。 这样的代码无法使用异步加速。

当您的任务正在等待与CPU不相关的任务时,例如,网络请求或从磁盘读取。通常所有语言都是如此。

在python中,基于线程的方法也无济于事,因为这仍然将您限制在一个核心而不是真正的并行执行。这是由于全局解释器锁定(GIL)。在线程之间启动和切换的开销使其比简单版本慢。 在这方面,线程类似于python中的异步,仅当您等待的时间不是主要花费在CPU上,或者您正在调用不受GIL约束的代码时,它才有帮助。 c个扩展名。

使用multiprocessing实际上使用了多个CPU内核,因此它比普通解决方案要快。