首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么有一个工作人员的ThreadPoolExecutor比正常执行还要快呢?

为什么有一个工作人员的ThreadPoolExecutor比正常执行还要快呢?
EN

Stack Overflow用户
提问于 2016-11-09 14:29:59
回答 1查看 1K关注 0票数 1

我正在使用这个库,明天,它反过来使用标准库中的ThreadPoolExecutor,以便允许异步函数调用。

调用装饰器@tomorrow.threads(1)可以使用1名工作人员生成一个ThreadPoolExecutor。

问题

  • 为什么使用1 thread worker执行函数比按原样调用它更快(例如,正常情况下)?
  • 为什么用10 thread workers来执行相同的代码比只执行1更慢,或者甚至不执行?

演示代码

不包括进口

代码语言:javascript
复制
def openSync(path: str):
    for row in open(path):
        for _ in row:
            pass

@tomorrow.threads(1)
def openAsync1(path: str):
    openSync(path)

@tomorrow.threads(10)
def openAsync10(path: str):
    openSync(path)

def openAll(paths: list):
    def do(func: callable)->float:
        t = time.time()
        [func(p) for p in paths]
        t = time.time() - t
        return t
    print(do(openSync))
    print(do(openAsync1))
    print(do(openAsync10))

openAll(glob.glob("data/*"))

注意:data文件夹包含18个文件,每700行随机文本。

输出

0员工: 0.0120秒

1工作人员: 0.0009秒

10员工: 0.0535秒

我测试过的

  • 我已经运行了超过几个黄昏的代码,不同的程序在后台运行(昨天运行了一堆,今天运行了几个程序)。号码会变,ofc,但是顺序总是一样的。(即1是最快的,然后是0然后10)。
  • 我还尝试更改执行顺序(例如,移动do调用),以消除缓存作为一个因素,但仍然一样。
    • 结果表明,按照101None顺序执行与其他排列不同的顺序(1是最快的,然后是10,然后是0)。结果表明,无论最后执行什么do调用,都要比先执行或在中间执行时慢得多。

结果(在收到@Dunes的解后)

0员工: 0.0122秒

1工作人员: 0.0214秒

10员工: 0.0296秒

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-11-09 16:18:12

当您调用一个异步函数时,它会返回一个“期货”对象(本例中是tomorrow.Tomorrow的实例)。这样你就可以提交所有的工作,而不必等待它们完成。然而,永远不要真正等待工作完成。因此,do(openAsync1)所做的就是设置所有作业所需的时间(应该非常快)。为了进行更准确的测试,您需要执行以下操作:

代码语言:javascript
复制
def openAll(paths: list):
    def do(func: callable)->float:
        t = time.time()
        # do all jobs if openSync, else start all jobs if openAsync
        results = [func(p) for p in paths]
        # if openAsync, the following waits until all jobs are finished
        if func is not openSync:
            for r in results:
                r._wait()
        t = time.time() - t
        return t
    print(do(openSync))
    print(do(openAsync1))
    print(do(openAsync10))

openAll(glob.glob("data/*"))

在python中使用其他线程通常会减慢速度。这是因为全局解释器锁,这意味着只有一个线程可以一直处于活动状态,不管CPU有多少核心。

然而,由于你的工作是IO约束的,事情就变得复杂了。更多的工作线程可能会加快速度。这是因为单个线程可能会花费更多的时间等待硬盘驱动器响应,而不是在多线程变体中不同线程之间的上下文切换之间丢失。

附带注意,尽管openAsync1openAsync10都没有等待作业的完成,但do(openAsync10)可能要慢一些,因为它在提交新作业时需要在线程之间进行更多的同步。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40509371

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档