Edge resource utilization & network design

前言

2022年的第一篇博客,分享一下如何有效利用GPU资源完成I&ML任务以及介绍一下Scapy网络工具和P4编程语言。

文章中的图片选自论文:Machine Learning at the Edge Efficient Utilization of Limited CPU GPU Resources by Multiplexing, Adaptive Addresses for Next Generation IP Protocol in Hierarchical Networks。

利用寒假的时间,我打算把后一篇论文的工作复刻一遍,作者利用P4和Scapy实现了分层网络中IPvn协议的转换,而且IPvn的heading是灵活的,可以自适应改变的,我觉得这是一件很让人兴奋和激动的事情,非常有学习的必要。

第一部分:Machine learning at the edge

我刚看到这个edge的时候,在边缘计算edge的位置那里钻牛角尖了,因为网上的资料千奇百怪,后来明白了,不需要在这个问题上花费精力,作者想表达的意思是,位于网络边缘的机器学习或推理,即I&ML。
在这里插入图片描述
位于网络边缘的计算延迟很低,可以满足实时性要求,但是计算资源相对网络中心薄弱,经典的例子是章鱼模型。所以,edge的计算资源有限,为了达到更好的效果,我们需要充分利用计算资源,提高资源利用效率,节省CPU开销,提高GPU利用率。

因此,为了在多个并发运行的客户端之间保证效率并尽可能降低推理延迟,需要资源共享。然而,跨应用程序多路复用GPU并不容易,况且服务器要处理大量的数据流,从网络获取数据,再把数据交递给GPU,也会限制GPU的工作量。在后面的实验中表明,GPU存在着很多的空闲时间。最后,我们发现,GPU的利用率并不高。

那么,我们应该采取什么样的策略呢?

  1. 受控的GPU资源隔离(空间共享)——可以限制应用程序间的干扰。
  2. 采用尽可能CPU开销小的数据复制方法——采用GPU DMA引擎将数据卸载到GPU。
  3. 使用CUDA库提供及时、低开销的通知——让CPU知道GPU何时完成任务。(CUDA Stream的回调方法在功能上受到限制,并在处理回调之前暂停GPU的执行,因此GPU会有较长的空闲。)

最后,实验结果显示,可以降低并提高DNN推理吞吐率。

接下来,比较一下几种GPU共享的方法:时间共享(分时复用)VS空间共享(资源隔离)VS受控空间共享(资源隔离)。

注:时间共享和空间共享是我按照论文的小标题翻译过来的,分时复用和资源隔离是我调查相关资料后更为专业的表述。

  • GPU分时复用和CPU分时复用很相似,即把一个GPU的时间按照特定时间段分片,每个VM拿到特定的时间片,享用GPU硬件的全部资源。这实际上是并发,伪并行。然而,单个进程通常无法充分利用所有的GPU资源,GPU利用率不高,但这种方法用得很多。(both CUDA and OpenCL support GPU kernels from different processes to time-share the GPU)
    在这里插入图片描述
    可以看到:当Densenet作为GPU中唯一运行的模型时,延迟是非常低的,每轮推理20ms延迟。当ResNeXt开始推理时,Densenet网络延迟增加了两倍。而VGG-16的启动同时增加了Densenet和ResNeXt的延迟。模型完成计算又会让Densenet降回20ms。因此,通过分时复用GPU来增加并发运行模型的数量会增加所有并发运行GPU应用程序的延迟。(在后面的实验中可以看到,Densenet实际上只使用了25%的资源,把资源全都交给它,它利用不了,就造成了浪费)
  • CUDA流和MPS利用Hyper-Q分别在多个进程内和跨多个进程提供GPU内核任务的并行多路复用。当使用NVIDIA MPS时,MPS Sever会通过一个CUDA Context管理GPU硬件资源,多个MPS Clients会将它们的任务通过MPS Server传入GPU,从而越过了硬件时间分片调度的限制,使得它们的CUDA kernels实现真正意义上的并行。然而,来自不同线程的内核的资源争用,也导致应用程序在不同时间段的性能变化,以及不可预测的延迟。
    在这里插入图片描述
    可以看到:使用默认MPS共享GPU,与分时复用GPU相比,所有三种模型的延迟都更低。这是因为与CUDA MPS共享GPU允许应用程序在空间上共享GPU并使用备用GPU资源,从图中我们还可以看到,当ResNeXt模型出现时,Densenet的延迟不会增加,因为有足够的GPU资源允许两者同时执行。然而,当VGG-16模型出现时,Densenet的延迟显著增加,而ResNeXt的延迟只增加了少量。我们观察到延迟的增加量,以及哪个并发运行的模型遭受额外的延迟是不可预测的,并且取决于GPU资源提交给模型的顺序。虽然默认MPS可能会提高GPU利用率,但它会导致并发运行的模型出现不可预测的延迟。(灵魂拷问:你的分配合理吗?怎么分配的?公平吗?)
  • CUDA架构Volta有一个支持资源调配限制的MPS版本,即它允许我们限制单个MPS客户端使用特定部分的可用线程(以 SMs为单位)。特别地,Volta MPS可以兼容docker容器,并且支持执行资源配置(即每个Client context只能获取一定比例的threads),提高了多容器共享GPU的QoS。这使我们能减少GPU内存并实现性能隔离,我们证明,虽然这一功能很有用,但它仍然需要更仔细的考虑和资源管理,才能真正获得GPU的好处和充分利用。
    在这里插入图片描述
    在GPU中同时运行三个DNN模型,每个模型的GPU%固定。在本实验中,我们为Densenet提供了25%的GPU,为ResNeXt-50提供了15%的GPU,为VGG-16提供了60%的GPU。
    可以看到:在整个实验中,模型的延迟保持不变。在同时运行的模型之间几乎没有干扰。我们进一步观察到Densenet模型的延迟与GPU中运行的唯一模型相同。我们得出结论,只有25%的GPU是Densenet运行所必需的,并且仍然可以在不同的多路复用选项中实现最低的延迟。从这里还可以看出分时复用不好的一面,因为它把所有的资源都给了一个任务,而那一个任务不见得会善用所有的资源。(回答了第一个实验的问题)

进一步,考量CUDA Stream吞吐率

尽管由于空间共享,CUDA Streams能够提高GPU利用率和总体吞吐量,但它们对延迟有不利影响。通过对不同batch size的模型进行试验,以了解使用多个Streams的影响。我们在图4中给出了带有TensortRT的ResNet-50模型的结果。
在这里插入图片描述
我们可以观察到,超过2个Stream(batch size均为1,8)时,吞吐量几乎没有任何改善,但延迟不断增加,而VGG19也是如此。
分析:只有当有足够的资源可以利用多路复用时,空间共享才有帮助,否则任务会争夺有限的资源,从而导致高执行开销,这反映在延迟的形式上。因此,CUDA Streams仅对light weight的模型和small batch size有利。

如何有效的将数据复制到GPU?对比CPU复制方式。

CPU复制:DPDK使以太网NIC能够将数据包传输到共享的hugepage缓冲区,这些缓冲区可以以零复制开销进行访问。将有效负载从每个数据包分别复制到GPU(使用CUDA API调用,如cudaMemcpy)非常昂贵。更好的方法是首先将数据包有效负载中的数据复制并聚合到一个连续的缓冲区中,然后将该缓冲区DMA到GPU。然而,即使这种方法仍然需要CPU将数据从数据包有效负载复制到连续的缓冲区,并使用CUDA API将数据移动到GPU。这些方法在连续缓冲区中复制和存储数据,对CPU和内存造成负担。

NetML:运用GPU内核。该内核使用GPU的DMA引擎从主机CPU内存执行分散 - 收集。在应用程序初始化期间,NetML固定DPDK的数据包内存缓冲池(mbuf池)。这确保所有网络数据包都驻留在固定内存区域中。一旦主机端的OpenNetVM应用程序接收到所有数据包,就会启动CUDA内核,将这些数据包中的数据收集到GPU缓冲区中。
在这里插入图片描述
通过测量将数据传输到GPU所花费的CPU周期占一个推理任务中使用的所有CPU周期的百分比来测量CPU Copy和NetML的CPU利用率。

如何更便利有效的通知CPU,GPU中的任务已经完成了?
在这里插入图片描述
在这里插入图片描述
我们可以观察到GPU在相当长的时间内保持空闲状态。每次执行间隔700微秒。此时间间隔对应于通知CPU推理完成和CPU端处理以执行清理和返回回调所需的时间。请注意,在回调完成之前,CUDA驱动程序不会启动下一次推理执行,即使它在任务之前已排队。(由于剖面分析,间隔非常高;我们观察到,在没有评测的情况下,回调的延迟约为40µs。)这里就会产生一个问题,谁通知CPU推理完成?

CUDA API提供了一个“回调”函数cudaStreamAddCallback(),通过在CPU上运行回调函数来通知GPU中的处理结束。尽管回调有助于通知特定任务的结束,但回调的当前实现对GPU多路复用提出了挑战。

首先,回调会阻止GPU上的所有后续执行,直到在CPU上完成回调例程的执行,从而导致GPU空闲。其次,GPU生成的回调函数禁止CPU线程运行任何CUDA API函数。此限制要求额外的CPU上下文和信令方案来执行任何与GPU相关的操作。

How to feedback? Event Flags!

为了克服这些限制,作者设计了一种轻量级的方法来检查GPU任务完成状态,利用CUDA基于事件的API记录DNN正在执行的“事件”(可以是每个GPU流)。CUDA事件充当一个标志,当GPU执行时,它记录执行时间。

  1. CUDA API函数cudaEventRecord()允许我们在DNN执行结束时放置事件标记。
  2. 然后,我们可以使用另一个API函数cudaEventQuery()来检查我们放置的事件是否已执行。

这使我们不仅可以避免GPU的空闲,还可以提供在同一CPU线程上下文中执行不同GPU任务的灵活性。事件检查是轻量级的,在我们的系统中大约需要5µ秒。由于DNN通常需要几毫秒来执行推断,因此我们以1毫秒的粗略间隔检查事件,以确定DNN计算何时结束,从而为CPU线程提供了以所需频率检查事件完成状态的灵活性。

第二部分:Scapy 和 P4

OSI、TCP/IP、网络协议、路由器转发、路由决策、网络部署,暂且不介绍,但是非常建议读者弄明白这些含义,这对处理网络工作非常有帮助。

Scapy是一个 python 程序,允许用户执行以下行为:

  • 发送packet
  • 资源嗅探
  • 解析数据包
  • 伪造网络数据包

由于以上行为,它允许构建网络工具用于:

  • 探测
  • 扫描
  • 攻击网络

它能够伪造或解码多种协议的数据包,通过网络发送数据包,捕获数据包,匹配请求,回复,等;它可以轻松处理大多数经典任务,如扫描、跟踪、探测、单元测试、攻击或网络发现;它可以取代hping、ARPSOOF、arp sk、arp、p0f,甚至是Nmap、tcpdump和tshark的某些部分;它在许多其他工具无法处理的特定任务上也表现出色,如发送无效帧、注入您自己的802.11帧、组合技术(VLAN跳跃+ARP缓存中毒、WEP加密通道上的VOIP解码等)。

traceroute:
在这里插入图片描述
在这里插入图片描述
可以构建任何形式的数据包:
在这里插入图片描述
在这里插入图片描述
P4,是SDN(软件定义网络)的一种实现方式,而SDN又是网络虚拟化的一种实现方式,其核心技术OpenFlow通过将网络设备的控制平面与数据(转发)平面分离开来,从而实现了网络流量的灵活控制,使网络作为管道变得更加智能,为核心网络及应用的创新提供了良好的平台。

它能做什么?它就能给上面提到的那个分层网络编程。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
结语

新年第一篇文章,写的比较随性,但是介绍的内容比较认真。介绍的工具和方法也非常建议大家去尝试。新的一年,让我们共同学习,共同进步,共同努力!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值