异步函数以同步(串行)方式运行,任务相互阻塞
Async function runs in a sync (serial) way, tasks block each other
我没有使用 asyncio 获得任何加速。此代码段仍然以与同步作业相同的方式运行。大多数示例使用 asyncio.sleep() 来施加延迟,我的问题是如果部分代码根据输入参数造成延迟怎么办。
async def c(n):
#this loop is supposed to impose delay
for i in range(1, n * 40000):
c *= i
return n
async def f():
tasks = [c(i) for i in [2,1,3]]
r=[]
completed, pending = await asyncio.wait(tasks)
for item in completed:
r.append(item.result())
return r
if __name__=="__main__":
loop = asyncio.get_event_loop()
k=loop.run_until_complete(f())
loop.close()
我希望得到[1,2,3]但我没有(连载运行时也没有时差)
asyncio 不是为了获得加速,而是在异步环境下编程时避免"callback hell",例如(但不限于)non-blockingIO。由于问题中的代码不是异步的,因此使用 asyncio 没有任何好处 - 但您可以改为查看 multiprocessing
。
在上面的例子中,该函数被定义为异步的,但它 运行 完成了它的整个计算而不等待任何东西。它还包含对未分配变量的引用,所以让我们从 运行s:
的版本开始
async def long_calc(n):
p = 1
for i in range(1, n * 10000):
p *= i
print(math.log(p))
return p
末尾的print
立即表示计算完成。启动几个这样的协程 "in parallel" 是用 asyncio.gather
:
完成的
async def wait_calcs():
return await asyncio.gather(*[long_calc(i) for i in [2, 1, 3]])
asyncio.gather
将让计算 运行 和 return 一旦所有这些都完成,return 按照他们计算的顺序列出他们的结果出现在参数列表中。但是 运行ning loop.run_until_complete(wait_calcs())
时打印的输出表明计算并不是真正的 运行ning 并行:
178065.71824964616
82099.71749644238
279264.3442843094
结果对应[2, 1, 3]
顺序。如果协程 运行 并行,则最小的数字将首先出现,因为它的协程到目前为止要做的工作最少。
我们可以通过在内部循环中引入no-op睡眠来强制协程给其他协程一个机会运行:
async def long_calc(n):
p = 1
for i in range(1, n * 10000):
p *= i
await asyncio.sleep(0)
print(math.log(p))
return p
现在的输出显示协程 运行 是并行的:
82099.71749644238
178065.71824964616
279264.3442843094
请注意,此版本 运行 也需要更多时间,因为它涉及协程和主循环之间的更多切换。大约一百个周期只休眠一次就可以避免减速。
我没有使用 asyncio 获得任何加速。此代码段仍然以与同步作业相同的方式运行。大多数示例使用 asyncio.sleep() 来施加延迟,我的问题是如果部分代码根据输入参数造成延迟怎么办。
async def c(n):
#this loop is supposed to impose delay
for i in range(1, n * 40000):
c *= i
return n
async def f():
tasks = [c(i) for i in [2,1,3]]
r=[]
completed, pending = await asyncio.wait(tasks)
for item in completed:
r.append(item.result())
return r
if __name__=="__main__":
loop = asyncio.get_event_loop()
k=loop.run_until_complete(f())
loop.close()
我希望得到[1,2,3]但我没有(连载运行时也没有时差)
asyncio 不是为了获得加速,而是在异步环境下编程时避免"callback hell",例如(但不限于)non-blockingIO。由于问题中的代码不是异步的,因此使用 asyncio 没有任何好处 - 但您可以改为查看 multiprocessing
。
在上面的例子中,该函数被定义为异步的,但它 运行 完成了它的整个计算而不等待任何东西。它还包含对未分配变量的引用,所以让我们从 运行s:
的版本开始async def long_calc(n):
p = 1
for i in range(1, n * 10000):
p *= i
print(math.log(p))
return p
末尾的print
立即表示计算完成。启动几个这样的协程 "in parallel" 是用 asyncio.gather
:
async def wait_calcs():
return await asyncio.gather(*[long_calc(i) for i in [2, 1, 3]])
asyncio.gather
将让计算 运行 和 return 一旦所有这些都完成,return 按照他们计算的顺序列出他们的结果出现在参数列表中。但是 运行ning loop.run_until_complete(wait_calcs())
时打印的输出表明计算并不是真正的 运行ning 并行:
178065.71824964616
82099.71749644238
279264.3442843094
结果对应[2, 1, 3]
顺序。如果协程 运行 并行,则最小的数字将首先出现,因为它的协程到目前为止要做的工作最少。
我们可以通过在内部循环中引入no-op睡眠来强制协程给其他协程一个机会运行:
async def long_calc(n):
p = 1
for i in range(1, n * 10000):
p *= i
await asyncio.sleep(0)
print(math.log(p))
return p
现在的输出显示协程 运行 是并行的:
82099.71749644238
178065.71824964616
279264.3442843094
请注意,此版本 运行 也需要更多时间,因为它涉及协程和主循环之间的更多切换。大约一百个周期只休眠一次就可以避免减速。