超简单的Python教程系列——异步

Python 3.5 引入了两个新关键字:​ ​async​ ​​和​ ​await​ ​​。这些看似神奇的关键字完全可以在没有任何线程的情况下实现类似线程的并发。在本教程中,我们将介绍异步编程的原因,并通过构建我们自己的小型异步类框架来说明Python的​ ​async/await​ ​关键字如何在内部工作。

为什么要异步编程?

要了解异步编程的动机,我们首先必须了解是什么限制了我们的代码运行速度。理想情况下,我们希望我们的代码以光速运行,立即跳过我们的代码,没有任何延迟。然而,由于两个因素,实际上代码运行速度要慢得多:

  • CPU时间(处理器执行指令的时间)
  • IO时间(等待网络请求或存储读/写的时间)

当我们的代码在等待 IO 时,CPU 基本上是空闲的,等待某个外部设备响应。通常,内核会检测到这一点并立即切换到执行系统中的其他线程。因此,如果我们想加快处理一组 IO 密集型任务,我们可以为每个任务创建一个线程。当其中一个线程停止,等待 IO 时,内核将切换到另一个线程继续处理。

这在实践中效果很好,但有两个缺点:

  • 线程有开销(尤其是在 Python 中)
  • 我们无法控制内核何时选择在线程之间切换

例如,如果我们想要执行 10,000 个任务,我们要么必须创建 10,000 个线程,这将占用大量 RAM,要么我们需要创建较少数量的工作线程并以较少的并发性执行任务。此外,最初生成这些线程会占用 CPU 时间。

由于内核可以随时选择在线程之间切换,因此我们代码中的任何时候都可能出现相互竞争。

引入异步

在传统的基于同步线程的代码中,内核必须检测线程何时是IO绑定的,并选择在线程之间随意切换。使用 Python 异步,程序员使用关键字​ ​await​ ​确认声明 IO 绑定的代码行,并确认授予执行其他任务的权限。例如,考虑以下执行Web请求的代码:

async def request_google():
    reader, writer = await asyncio.open_connection('google.com', 80)
    writer.write(b'GET / HTTP/2\n\n')
    await writer.drain()
    response = await reader.read()
    return response.decode()

在这里,在这里,我们看到该代码在两个地方​ ​await​ ​​。​​因此,在等待我们的字节被发送到服务器(​ ​writer.drain()​ ​​)时,在等待服务器用一些字节(​ ​reader.read()​ ​)回复时,我们知道其他代码可能会执行,全局变量可能会更改。然而,从函数开始到第一次等待,我们可以确保代码逐行运行,而不会切换到运行程序中的其他代码。这就是异步的美妙之处。

​ ​asyncio​ ​是一个标准库,可以让我们用这些异步函数做一些有趣的事情。例如,如果我们想同时向Google执行两个请求,我们可以:

async def request_google_twice():
    response_1, response_2 = await asyncio.gather(request_google(), request_google())
    return response_1, response_2

当我们调用​ ​request_google_twice()​ ​时,神奇的​ ​asyncio.gather​ ​会启动一个函数调用,但是当我们调用时​ ​await writer.drain()​ ​,它会开始执行第二个函数调用,这样两个请求就会并行发生。然后,它等待第一个或第二个请求的​ ​writer.drain()​ ​调用完成并继续执行该函数。

最后,有一个重要的细节被遗漏了:​ ​asyncio.run​ ​。要从常规的 [同步] Python 函数实际调用异步函数,我们将调用包装在​ ​asyncio.run(...)​ ​:

async def async_main():
    r1, r2 = await request_google_twice()
    print('Response one:', r1)
    print(&#
  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
SV小项目-异步FIFO是一个简单的项目,旨在让学生理解FIFO缓存的原理和实现方式。 FIFO缓存是一种常用的数据存储方式,可以用于解决数据传输时的不匹配问题。在异步FIFO中,数据的写入和读取是异步的,意味着数据可以在任何时候写入或读取。这种异步的方式可以增加FIFO的灵活性,并且允许数据的写入和读取在不同的时钟域上应用。 这个小项目的主要目标是实现一个基于Verilog的异步FIFO模块,包括以下功能: 1. 内部缓存的储存和检索 2. 空和满指示器的生成 3. 数据的写入和读取 对于写入操作,当FIFO未满时,它将数据存储在内部缓存中,并更新其指针以指向下一个空位置。当缓存已满时,写入操作将被忽略,并且FIFO满指示器将被设置为高电平。同样,读取操作从内部缓存中检索数据,并将其指针更新以指向下一个位置。当缓存为空时,读操作将被忽略,并且FIFO空指示器将被设置为高电平。 在设计过程中,需要考虑解决的问题包括时序和异步信号的同步。时序问题可以通过FIFO指针和状态机解决,而异步信号可以通过信号同步器进行同步。此外,还需要考虑FIFO的读写顺序和存储器的尺寸,并确保FIFO模块的有效性和可靠性。 总之,通过实现SV异步FIFO项目,学生可以加深对FIFO缓存的理解,并学习基于Verilog的设计和实现。此外,学生还可以通过在项目中遇到的挑战来提高他们的编程和设计技能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值