9

我正在做一些例子来了解它是如何异步工作的。checkpoint我阅读了 Trio 文档,我认为每次只能在循环中执行一个任务,并且每次scheduler决定将执行哪个任务。

我做了一个示例来测试它,在三重奏示例中,我没有在我生成的子节点中使用任何检查点,nursery但是这个示例比同步版本快两倍。

异步示例:

import time
import trio

results = []

async def sum_numbers(first, last):
    result = 0
    for i in range(first, last):
        result += i
    results.append(result)

async def main():
    start_time = time.time()
    async with trio.open_nursery() as nursery:
        nursery.start_soon(sum_numbers, 0, 50000000)
        nursery.start_soon(sum_numbers, 50000000, 100000000)

    print(sum(results))
    print("Total time:", time.time() - start_time)

trio.run(main)

结果:

4999999950000000
Total time: 4.150018930435181

同步示例:

import time

start_time = time.time()
result = 0
for i in range(0, 100000000):
    result += i

print(result)
print("Total time:", time.time() - start_time)

结果:

4999999950000000
Total time: 8.002650737762451

为什么?我希望在同一时间,因为我没有在我的代码中使用任何检查点。似乎有 2 个线程同时运行或子函数中是否有任何 I/O?

4

1 回答 1

9

在与 Trio 的作者Nathaniel J. Smith进行了简短的交谈后,他发现了我的代码中的问题。问题出在同步示例中。我使用全局变量而不是异步示例中的局部变量。

Nathaniel:“在 CPython 中,访问局部变量比访问全局变量更优化。(编译器将局部变量转换为数组中的偏移量,而全局变量总是在字典中按名称查找)”

然后我将同步示例中的所有代码放在一个函数中,时间与异步相似,甚至更快。现在明白了,这是理论,现在被证明了,这对我来说很清楚。谢谢!

函数中的同步示例:

import time

start_time = time.time()


def sum_range():
    result = 0
    for i in range(0, 100000000):
        result += i

    return result

print(sum_range())
print("Total time:", time.time() - start_time)

结果:

4999999950000000
Total time: 3.596266984939575
于 2018-08-15T10:00:16.260 回答