-1

我试图找到一种简单的方法来“加速”一个大脚本的简单功能,所以我搜索了它并找到了 3 种方法来做到这一点。但似乎他们需要的时间总是一样的。那么我做错了什么测试它们?

文件1:

from concurrent.futures import ThreadPoolExecutor as PoolExecutor
from threading import Thread
import time
import os
import math
#https://dev.to/rhymes/how-to-make-python-code-concurrent-with-3-lines-of-code-2fpe
def benchmark():
    start = time.time()
    for i in range (0, 40000000):
        x = math.sqrt(i)
        print(x)
    end = time.time()
    print('time', end - start)
with PoolExecutor(max_workers=3) as executor:
    for _ in executor.map((benchmark())):
        pass

文件2:

#the basic way
from threading import Thread
import time
import os
import math

def calc():
    start = time.time()

    for i in range (0, 40000000):
        x = math.sqrt(i)
        print(x)

    end = time.time()
    print('time', end - start)

calc()

文件3:

import asyncio
import uvloop
import time
import math
#https://github.com/magicstack/uvloop
async def main():
    start = time.time()
    for i in range (0, 40000000):
        x = math.sqrt(i)
        print(x)
    end = time.time()
    print('time', end - start)
uvloop.install()
asyncio.run(main())

每个文件大约需要 180-200 秒

所以我“看不出”有什么不同。

4

1 回答 1

1

我搜索了一下,找到了 3 种 [加速功能] 的方法,但似乎他们需要的时间总是一样的。那么我做错了什么测试它们?

您似乎找到了通过并行化某些代码来加速某些代码的策略,但是您未能正确实现它们。首先,加速应该来自并行运行函数的多个实例,并且代码片段没有尝试这样做。然后,还有其他问题。

在第一个示例中,您将结果 benchmark()传递给executor.map,这意味着所有的benchmark()都立即执行完成,从而有效地禁用了并行化。(此外,executor.map应该接收可迭代的,而不是无,并且此代码必须打印问题中未显示的回溯。)正确的方法是:

# run the benchmark 5 times in parallel - if that takes less
# than 5x of a single benchmark, you've got a speedup
with ThreadPoolExecutor(max_workers=5) as executor:
    for _ in range(5):
        executor.submit(benchmark)

为了真正产生加速,您应该尝试使用ProcessPoolExecutor,它在单独的进程中运行其任务,因此不受GIL 的影响。

第二个代码片段实际上从未创建或运行线程,它只是在主线程中执行函数,因此不清楚应该如何加快速度。

最后一个片段没有await任何作用,所以async def它就像一个普通的函数一样工作。请注意,这asyncio是一个基于在 IO 上阻塞的任务之间切换的异步框架,因此永远无法加速 CPU 密集型计算。

于 2019-07-27T21:21:20.130 回答