我正在使用这个库,明天,它反过来使用标准库中的ThreadPoolExecutor,以便允许异步函数调用。
调用装饰器@tomorrow.threads(1)可以使用1名工作人员生成一个ThreadPoolExecutor。
问题
1 thread worker执行函数比按原样调用它更快(例如,正常情况下)?10 thread workers来执行相同的代码比只执行1更慢,或者甚至不执行?演示代码
不包括进口
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秒
我测试过的
10、1、None顺序执行与其他排列不同的顺序(1是最快的,然后是10,然后是0)。结果表明,无论最后执行什么do调用,都要比先执行或在中间执行时慢得多。
结果(在收到@Dunes的解后)
0员工: 0.0122秒
1工作人员: 0.0214秒
10员工: 0.0296秒
发布于 2016-11-09 16:18:12
当您调用一个异步函数时,它会返回一个“期货”对象(本例中是tomorrow.Tomorrow的实例)。这样你就可以提交所有的工作,而不必等待它们完成。然而,永远不要真正等待工作完成。因此,do(openAsync1)所做的就是设置所有作业所需的时间(应该非常快)。为了进行更准确的测试,您需要执行以下操作:
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约束的,事情就变得复杂了。更多的工作线程可能会加快速度。这是因为单个线程可能会花费更多的时间等待硬盘驱动器响应,而不是在多线程变体中不同线程之间的上下文切换之间丢失。
附带注意,尽管openAsync1和openAsync10都没有等待作业的完成,但do(openAsync10)可能要慢一些,因为它在提交新作业时需要在线程之间进行更多的同步。
https://stackoverflow.com/questions/40509371
复制相似问题