+86-13951940532
contact@oakchina.cn

❶为 getOutputQueue 方法指定参数

❶为 getOutputQueue 方法指定参数

获取输出队列时(下面的示例代码), maxSize 和 blocking 参数应根据消息的使用方式进行设置,其中 name 是输出流的名称。

由于队列在主机上,因此内存 (RAM) 通常并不稀缺。但是,如果您使用的是像 RPI Zero 这样只有 0.5GB RAM 的小型 SBC,您可能还需要指定最大队列大小。

with dai.Device(pipeline) as device:
  queueLeft = device.getOutputQueue(name="manip_left", maxSize=8, blocking=False)

如果只有最新的结果是相关的而以前的结果无关紧要,则可以设置 maxSize = 1 和 blocking = False 。这样只会保留最新的消息( maxSize = 1 )并且它也可能被覆盖以避免等待主机处理每一帧,从而只提供最新的数据( blocking = False )。但是,如果有大量丢弃 / 覆盖的帧,因为主机无法足够快地处理它们(例如,执行一些繁重计算的单线程环境), maxSize 可以设置为更高的数字,这将增加队列大小并减少丢帧数。具体来说,在 30 FPS 下,每~33 毫秒接收一个新帧,因此如果您的主机能够在那个时间内处理一个帧,则可以将 maxSize 设置为 1 ,否则为 2 处理时间到 66ms 等等。

但是,如果需要在检索消息之间有一些等待时间间隔,则可以指定不同的方式。一个示例是根据某些其他事件检查最后 1 秒内 DetectionNetwork 的结果,在这种情况下,可以设置 maxSize = 30 和 blocking = False (假设 DetectionNetwork 以约 30FPS 的速度生成消息)。

blocking = True 选项主要在需要正确的消息顺序时使用。两个例子是:

  • 匹配直通帧及其原始帧(例如,完整的 4K 帧和进入 NN 的较小预览帧),
  • 编码(最突出的是 H264/H265,因为丢帧会导致伪影)。

阻塞行为

默认情况下,队列是阻塞的,其大小为 30,因此当设备填满队列并达到限制时,来自设备的任何其他消息都将被阻塞,库将等待直到它可以将新消息添加到队列中。在将新消息放入队列之前,它将等待主机使用(例如 queue.get() )一条消息。

主机队列填满后,设备上的 XLinkOut.input 队列将开始填满。如果该队列设置为阻塞,则向其发送消息的其他节点也将不得不等待。这是管道阻塞的常见原因,其中一个队列没有及时清空,管道的其余部分等待它再次清空。

非阻塞行为

使队列非阻塞将改变上述情况下的行为 – 库将丢弃最旧的消息并将新消息添加到队列,然后继续其处理循环(因此不会被阻塞)而不是等待). maxSize 决定了队列的大小,也有助于控制内存的使用。

例如,如果一条消息有 5MB 的数据,队列大小为 30,则此队列可以有效地在主机内存中存储多达 150MB 的数据(消息也可以变得非常大,例如,单个 4K NV12 编码帧大约需要 12MB)。

一些额外的信息

  • 将队列大小减小到 1 并设置非阻塞行为将有效地意味着 “我只想要队列中的最新数据包”。
  • 队列是线程安全的 —— 它们可以从任何线程访问。
  • 创建队列时,每个队列都是自己的线程,负责接收、序列化 / 反序列化和向前发送消息(输入 / 输出队列也是如此)。
  • Device 对象不是完全线程安全的。一些 RPC 调用(例如 getLogLevel 、 setLogLevel 、 getDdrMemoryUsage )在设置了互斥体后将获得线程安全(现在可能存在竞争)。