本文转载自公众号上海交大并行与分布式系统研究所第16届 OSDI 于2022年7月11日-7月13日在美国卡尔斯巴德召开。本次会议共收到253篇投稿,接收49篇论文,录取率为19.4%。照惯例,IPADS的同学们将按照会议日程对论文内容进行分期评述。受微信公众号字数限制,本期介绍第二天最后一个以及第三天第一个session的论文。Session-8: Machine Learning 2Orca: A Distributed Serving System for Transformer-Based Generative ModelsGyeong-In Yu and Joo Seong Jeong, Seoul National University; Geon-Woo Kim, FriendliAI and Seoul National University; Soojeong Kim, FriendliAI; Byung-Gon Chun, FriendliAI and Seoul National University本项工作的作者来自首尔大学,主要设计了一个面向Transformer-based的生成模型分布式推理系统 Orca。Orca已经应用在作者所在的FriendliAI公司的真实业务中。Introduction基于 Transformer 的生成模型(Generative Model)近两年受到了很大的关注,最典型的例子就是 OpenAI 提出的拥有1700亿参数的 GPT-3 模型,基于 GPT-3 可以实现很多的任务,例如智能问答、文本生成等等。为了能在真实的生产场景使用如此巨大的模型,一般会部署一个独立的推理服务(Inference Serving System),用于执行用户提交的推理任务,常见的Inference Serving系统包括NVIDIA 的 Triton Inference Server 以及 TensorFlow 的 TensorFlow Serving。用户可以通过 RPC 向这些 Serving System 提交请求,Serving System负责调度并执行这些请求,最终通过RPC向用户返回结果。近几年也有大量的针对 Inference Serving System 的工作,在 Inference Serving System 中最典型的优化方式就是 Batching,也就是将一段时间内到达的用户请求合并到一起,提交到GPU中执行,从而提高系统的吞吐量。然而,与传统的 DNN Model 在推理时只要正向执行一遍不同,基于 Transformer 的 Generative Model 在推理时是迭代式的(Iterative),每个请求都需要迭代式执行多次,每次生成部分结果(一个 Token),且每个请求的迭代次数可能是不同的(例如迭代直到模型生成一个 End-Of-Sequence Token)。因此将现有的 Batching 方式应用在 Generative Model 时,可能导致有的请求已经迭代结束了,但是还需要和同Batch中没有迭代结束的请求继续一起执行。这个问题的核心在于,传统的 Batching 技术是以 Request 为粒度的,将多个 Request 绑定在一起提交给执行引擎,多个 Request 同时开始同时结束。当多个 Request 的计算过程一样时(例如传统CNN模型),以 Request 为粒度的 Batching 技术是合适的,但是在 Generative Model 中,不同 Request 执行过程是不同的(Iteration 的次数不同),因此需要一个新的 Batching 的方式,这也是本项工作核心的 Insight:使用更细粒度的,Iteration-level Batching,在每个 Iteration 中将不同的 Request 合并到一起。Transformer-Based Generative Models为了更好理解 Generative Model,作者以GPT为例子介绍了Generative Model的推理方式。GPT的输入是一段 text,输出是一段新的 text。例如在下图中,输入"I think this"时,输出就是"is great"。GPT是通过迭代的方式生成结果,在每个迭代过程中生成一个 token(例如一个单词),并且将这个token作为下一次迭代的输入。在下图的例子中,初始的输入"I think this"在一次迭代后得到的结果为"is",再将"is"作为输入进行迭代后得到的结果为"great",持续这个过程直到输出为EOS("End-Of-Sequence")为止。State-of-the-art Inference Serving System如下图所示,当前的Inference Serving System使用传统的 Request-level 的 Batching 方式执行多个用户请求,同一个Batch中的Request同时提交到Execution Engine,全部完成计算后一起返回。而这种方式的缺点就在于,同一个 Batch 的请求必须要等待所有请求都完成时,才能被返回。如下图所示,当输入 x2: "I love" 在两次迭代后就得到结果 "you" 之后,必须再等待x1也完成迭代才能返回给用户。Iteration-level scheduling本项工作提出的系统 Orca 的第一项核心技术就是 Iteration-level scheduling,用于解决上述 request-level scheduling 的 early-finish 的问题。如下图所示,Orca在调度任务时,每次只向 Execution Engine 提交一次 Iteration 的计算,而非完成整个 Request,这样 Orca 就可以在每个Iteration都动态选择Batching的Request,从而避免early-finish的请求等待其他请求的结束。Selective batchingIteration-level batching 面临新的挑战:并非所有的请求都能在任意Iteration被Batch到一起。典型的问题就是Batching的Input需要有相同Shape(例如相同的 sequence length)。为了解决这个问题,Orca 提出了第二点核心技术:Selective batching。这个技术的Insight是:Transformer Layer里并非所有的算子都需要Batching的Input有相同的Shape,如下图所示,Add,Linear,GeLU等算子在计算时可以将一个Batch进行Flatten,这样不同 Sequence Length 的Input也可以Batch到一起进行计算;而对于其他必须有相同Shape才能Batching的算子(例如Attention),则对不同的输入进行单独的计算。Evaluation作者对比了 Orca 和 FasterTransformer 的性能,如下图所示,在不同大小的 GPT-3 模型下,Orca 可以提高最多 36.9 倍的吞吐量。Conclusion本项工作提出了 Orca 系统,用于提供 Transformer-Based Generative Models 的推理服务。Orca 根据 Generative Model 执行时的 Iterative 的特点,提出了 Iteration-level Scheduling 以及 Selection Batching 技术,实现了细粒度的 Batching,相比现有系统提高了 36.9 倍吞吐量。Microsecond-scale Preemption for Concurrent GPU-accelerated DNN InferencesMingcong Han, Institute of Parallel and Distributed Systems, SEIEE, Shanghai Jiao Tong University; Shanghai AI Laboratory; Hanze Zhang, Institute of Parallel and Distributed Systems, SEIEE, Shanghai Jiao Tong University; MoE Key Lab of Artificial Intelligence, AI Institute, Shanghai Jiao Tong University, China; Rong Chen, Institute of Parallel and Distributed Systems, SEIEE, Shanghai Jiao Tong University; Shanghai AI Laboratory; Haibo Chen, Institute of Parallel and Distributed Systems, SEIEE, Shanghai Jiao Tong University; Engineering Research Center for Domain-specific Operating Systems, Ministry of Education, China本项工作来自IPADS实验室,提出了面向强实时低时延场景的DNN推理系统 REEF。REEF是第一个结合了抢占式GPU任务调度以及保证性能隔离的可控并发执行机制的DNN推理系统。Motivation目前很多智能系统会同时使用多个DNN模型来满足多种的功能,而不同功能下使用的DNN模型的推理任务具有不同的时延要求。以智能汽车为例,智能汽车使用DNN模型来检测障碍物,同时也会使用DNN模型来监控司机的驾驶状态。这两个任务拥有不用时延要求,障碍物检测的DNN推理任务具有强实时的要求,推理系统需要优先满足此类任务的低时延要求,在本工作中被称为real-time task(RT task),而用于司机监控的DNN推理任务则具有较低的优先级和较宽松时延要求,在本工作中被称为 best-effort task(BE task)。本项工作关注在使用单个GPU服务以上两类任务时,如何同时满足以下两个目标:real-time task应该具有最高的优先级,从而保证其具有最低的端到端时延(low end-to-end latency)。best-effort task应该能够在不影响real-time task的前提下,与其并发执行,从而提高系统的资源利用率和吞吐量(work-conserving)。为了满足以上两个目标,本项工作提出了 REEF 系统,REEF 使用了两个核心技术:Reset-based Preemption:基于DNN推理任务的GPU Kernel具有幂等性的观察,本工作提出了通过"kill"来实现在GPU上的快速任务抢占。Dynamic Kernel Padding: 基于DNN推理任务的GPU Kernel具有时延可预测性的观察,本工作提出了一种可控的并发执行方法,在 real-time kernel 执行时,根据其执行的时延,动态的填充合适的 best-effort kernel 与其并发执行。GPU-accelerated DNN Inference本工作首先总结了 GPU-accelerated DNN Inference 的一些特性,以及这些特性对于推理系统设计的影响:Idempotence:一个 DNN inference 任务一般是由一连串顺序执行的 GPU kernel 组成,而这些 GPU Kernel 基本上都具有幂等性,因为他们大多都是无状态的代数运算,对于相同的输入总会得到相同的输出。并且打断一个正在执行的kernel,并重新执行它,也会得到相同的输出。因此,我们可以通过直接kill正在执行的任务来实现快速的任务抢占,并且在恢复任务时,只需要从被killed掉的kernel开始重新执行。Massive kernels:传统的GPGPU应用一般只有几个或十几个GPU Kernel,而DNN Inference任务往往具有数十或上百个GPU Kernel(在本工作的测试中,一个模型最多具有307个Kernel)。在执行巨大数量的GPU kernel时,kernel launch的性能开销会尤为明显。为了避免kernel launch的性能开销,一般的execution engine都会选择异步的将所有kernel全部提交到GPU runtime后,再同步等待结果。这个特性导致在实现GPU任务抢占时,除了正在执行的kernel,还有数十上百的kernel存在于GPU runtime中,对这些kernel的抢占也会显著的影响任务抢占的时延。Latency predictability:DNN Inference任务中的GPU Kernel的执行时间具有可预测性,因为他们的大多都是没有逻辑分支、无状态的代数运算,当使用固定大小的输入进行计算时,计算过程是固定的。因此我们可以在离线阶段提前记录每个kernel的执行时延,并在运行时实现精准的资源分配和任务调度。Varied parallelism:同一个DNN Inference任务中不同的GPU Kernel具有不同的并行度,如下图所示,在执行VGG模型的执行过程中,不同时刻对于 GPU 中计算单元(Compute Unit,CU)的利用率是动态变化的。因此在多个任务并行执行时,应该具有一个动态的计算资源分配机制,来满足不同任务的性能需求。State-of-the-art GPU Scheduling接下来,本工作总结了现有的 GPU 任务调度方法,以及他们在实现本项工作关注的性能目标时所存在的问题。Sequential execution:最典型的调度方法就是将 GPU 视为一个整体,每次执行一个任务,这也是现有的Serving System(例如 ClockWork)的典型调度方式。由于这种调度策略是非抢占式的,如上图所示,如果一个RT任务到达时,系统正在执行一个BE任务,那么这个RT任务只能等BE任务完成之后,才能被执行,现在会严重影响RT任务的响应时延。同样的,这种调度方式没有能够充分利用GPU的并行性,造成了计算资源的浪费,从而导致了较低的吞吐量。Block-level preemption:由于现有的商用GPU没有提供“抢占式调度”的用户API,因此现有工作利用GPU kernel中的block具有独立性的特点,实现了block-level preemption。当一个kernel被抢占时,它不会等待所有的block都计算完成,而是只等待正在执行的block完成后则退出。通过这个方式可以实现GPU的抢占式任务调度,在RT任务到达时抢占BE任务,从而降低RT任务的响应时延。而这一方式存在以下三个问题:首先这个方法的抢占时延取决于正在执行的block还有多久结束,这在严格意义上并非是“抢占”,并且在有多个kernel并行执行时会有较大的抢占时延;其次,这个方法要求GPU runtime中只能存在一个kernel,在DNN Inference具有 massive kernels的特征下会显著放大kernel launch的开销,显著降低推理的性能,而若不做此限制(即允许GPU Runtime中存在多个kernel),则会显著影响抢占时延(至毫秒级);最后,抢占式调度存在一个著名的“饥饿”问题,当RT任务到达频率很高时,BE任务会因为被频繁抢占而被“饿死”。Multiple GPU streams:为了避免饥饿和提高系统吞吐,现有的GPU Runtime提供了Stream的抽象(例如CUDA Stream),可以利用多个Stream实现任务的并行执行。而GPU Stream虽然能够提高系统吞吐量,也同时由于多个任务对计算资源的竞争,显著影响RT任务的执行时延。REEF: A real-time GPU-accelerated DNN inference serving system针对现有方法存在的问题,本工作提出了 REEF 系统,REEF系统的设计目标是同时保证RT任务的低时延以及BE任务的高吞吐。REEF的系统架构如上图所示,REEF在离线阶段通过DL Compiler生成DNN模型,并预先profile每个GPU kernel的执行时延。在运行阶段,REEF系统将DNN Inference Task分为两类:RT Task 以及 BE Task。根据当前是否存在RT Task,REEF分为两种调度模式:Normal Mode:如果系统中没有RT Task,则REEF处于Normal Mode。Normal Mode下,REEF使用多个GPU Stream并发地执行多个BE Task,从而提高BE Task的吞吐量。Real-time Mode:当用户提交了一个RT Task后,REEF通过抢占正在执行的BE Task从而切换到Real-time Mode,并执行RT Task。在Real-time Mode下,REEF同一时刻只会执行一个RT Task,并且通过Dynamic kernel padding技术选择BE Task与RT Task并行执行。下图给出了一个REEF的任务调度例子。在起始阶段,系统中不存在RT Task,REEF使用多个GPU Stream并行执行多个BE Task(红色和绿色),而当蓝色的RT Task到达时,REEF通过Reset-based Preemption技术实现快速的任务抢占,并切换到Real-time Mode执行RT Task。在Real-time Mode下,REEF使用Dynamic Kernel Padding技术,实现RT/BE任务的并行执行,避免BE任务的饥饿并提高系统吞吐。在RT任务结束后,REEF切换回Normal Mode,继续执行BE任务。Reset-based Preemption为了实现从Normal Mode到Real-time Mode的快速切换,REEF首先提出了Reset-based Preemption技术来完成微秒级的GPU任务抢占,其核心insight为:DNN的GPU kernel具有幂等性,可以通过kill来实现快速任务抢占,通过re-execute被kill的kernel实现快速任务恢复。而一个DNN任务,除了GPU中正在执行的kernel,在GPU Runtime中还存在大量未执行的正在排队的kernel。Reset-based Preemption的核心思路就是“Reset”所有位置的kernel,包括GPU中正在执行的和队列里的正在等待的。具体的步骤如下:Reset HQs: 用户提交的kernel首先被缓存在GPU Runtime中一个称为Host Queue的链表里,抢占一个任务时首先需要清理掉Host Queue里的kernel,而由于Host Queue是通过链表实现,可以直接替换链表头,实现快速的清理。Reset DQs:Host Queue里的Kernel会被异步的提交到一个称为Device Queue的环状数组里,抢占一个任务时也需要清理掉Device Queue里的kernel;与Host Queue不同,Device Queue是CPU和GPU同时读写的内存,清理时需要避免竞争。因此我们选择了一个更安全的方法,即允许Device Queue里的kernel在被抢占后继续提交到GPU中执行,但是在执行开始时直接退出(通过检查一个flag实现)。Reset CUs:最后一步就是kill掉正在执行的kernel,这里我们复用了GPU Driver中功能,通过重置所有CU的状态实现kill。Dynamic Kernel Padding在Real-time Mode,REEF使用Dynamic Kernel Padding技术,实现RT/BE 两类Task的并行执行,主要的思路是:以RT为核心,在RT Task执行过程中动态进行CU的划分,优先为RT Kernel分配足够的CU,再将剩余的CU分配给BE kernel。为了实现动态细粒度的CU划分,我们使用了类似kernel-fusion的方式,将两个不同的kernel合并到一起执行,但不同于kernel-fusion在编译阶段将kernel源代码合并到一起,我们采用function pointer的形式在运行阶段动态跳转到待执行的kernel。上图给出了dynamic kernel padding的伪代码,在运行阶段,dynamic kernel padding在执行一个RT Task时,通过"kern_select"函数依次为每个RT Kernel选择并行执行的BE Kernel,并将这些kernel作为名为dkp的kernel的参数提交到GPU runtime中。dkp是所有kernel的入口,dkp在执行时首先为RT kernel分配足够的CU,再为BE kernel分配剩余的CU。最后通过function pointer的方式跳转到RT/BE Kernel执行。为了降低BE kernel对RT kernel性能的影响,DKP利用了DNN kernel的时延可预测性,只选择执行时延小于RT kernel的BE kernel。然而上述方式面临一个关键的技术挑战:GPU的function pointer具有极大的性能开销。为了优化GPU中function pointer的开销,本工作提出了global function pointer和proxy kernel的方法,将function pointer的性能开销降低到1%,具体内容可以参考论文。EvaluationREEF首先部署在AMD Instinct MI50 GPU,因为其具有开源的GPU Driver、Runtime和ISA。为了测试REEF的综合性能,本工作还提出了一个面向实时场景的DNN推理测试基准(DISB),DISB使用了多个具有代表性的DNN模型,并提供了五个具有不同特性的负载。在DISB中,client按照固定的频率或者随机提交推理请求,不同的负载具有不同数量的client或者不同的client任务提交频率,如下图所示。本工作对比了REEF与以下三个任务调度方式:SEQ:非抢占式顺序调度DNN任务,但是在提交时优先选择RT任务。GPUStreams:使用多个GPU Stream并发执行多个任务。RT-Only:只执行RT任务,作为最优的rt latency参考下图给出了REEF与以上三个调度方式在DISB上的测试结果,本工作主要关注两个性能指标,首先是RT任务的端到端时延(end-to-end real-time task latency),以及系统的整体吞吐(overall throughput)。在DISB测试中,相比RT-Only,REEF在只提高RT任务2%时延的前提下,可以提高1.14 ~ 7.7倍的吞吐量。下图给出了REEF提出的任务抢占技术(Reset-based)与现有方法(Wait-based)的性能对比,在DISB测试中,REEF可以在百微秒内抢占并发的DNN任务,相比现有方法抢占时延降低了15倍 ~ 18倍。Conclusion本项工作提出了面向实时场景的DNN推理调度系统REEF,REEF主要提出了两个核心技术:首先,基于DNN推理任务GPU kernel的幂等性,提出了reset-based preemption技术,通过直接kill正在执行的kernel,实现了微秒级的DNN推理任务GPU抢占;其次,基于DNN推理任务GPU kernel的时延可预测性,提出了dynamic kernel padding技术,允许RT和BE任务并行执行,同时可以保证RT任务的时延不受影响。Alpa: Automating Inter- and Intra-Operator Parallelism for Distributed Deep LearningLianmin Zheng, Zhuohan Li, and Hao Zhang, UC Berkeley; Yonghao Zhuang, Shanghai Jiao Tong University; Zhifeng Chen and Yanping Huang, Google; Yida Wang, Amazon Web Services; Yuanzhong Xu, Google; Danyang Zhuo, Duke University; Eric P. Xing, MBZUAI and Carnegie Mellon University; Joseph E. Gonzalez and Ion Stoica, UC Berkeley本工作来自UC Berkeley的RISE Lab。这篇工作尝试为深度学习应用自动寻找最优的模型并行方案。近年来,深度学习中模型大小不断增长,基于Transformer的大模型更是加快了这一增长趋势。无论从在内存,还是算力上,这些大模型都已经超出了单机的承载能力。然而,高效的分布式训练并非易事。在硬件上,集群中不同设备的算力、内存存在差异,设备间通信的带宽也存在着层级的差异。软件上,深度学习更是存在如数据并行、模型并行的多种并行方案。在确定深度学习的计算图之后,如下图所示,计算图中每个算子内部可以从不同维度进行划分,将任务分配到不同的设备上;相邻算子的划分方式的多种组合方式还会导致不同的通信开销;算子之间也可以划分到不同的设备,并利用流水线并行起来。这些并行方案组合在一起,同时加上复杂的硬件情况,使得求解最优的并行策略成为一个复杂度十分高的问题。而现有的在分布式深度学习系统在制定并行策略上或多或少都存在着许多缺陷。大部分系统都需要手工针对特定结构的模型来设计优秀的并行策略,因此在通用性上存在天然不足。而现有的自动构建并行策略的工作,为了降低求解复杂度,只考虑了上述划分方式中数据并行与至多一种模型并行的组合,因此距离全局最优的并行策略仍有较大距离。那么,我们能否找到一种构建并行策略的方法,既能同时考虑多种并行方式,同时又不会引入太大的求解复杂度呢?作者观察到,上述的并行技术对设备间通信能力的要求存在差异,并根据这一差异将这些并行技术抽象为了两大类:算子内并行,即将同一算子按照数据维度划分到不同设备的并行方式,通常会需要合并计算结果,其带来的如All-Gather通信会引入较大的通信开销,因此对设备间的通信带宽与延时有较大要求;算子间并行,即将不同算子划分到不同设备的并行方式,则只需要在相邻算子之间进行单向通信,因此对通信带宽的要求较低。这两类并行技术对通信的要求,正好与集群中设备之间的层次关系对应:例如,同一台机器内的不同CPU核、不同GPU卡可以以较大带宽互联,而不同机器则由较低带宽的网络互联。基于这一观察,作者提出可以将求解分为两个层次的子问题,并与集群资源的层次对应起来:在第一层,仅考虑粗粒度的算子间并行,将整个计算图以算子为粒度,划分为不同的stage。同时,将集群中的设备划分为多个submesh,并与stage一一对应。在第二层,仅考虑细粒度的算子内并行,根据第一层指定的计算图与设备的划分方式,求解出最优的算子内并行方式。基于这种分解方式,原本复杂的问题被拆分成了两个可以“独立”的子问题,并大大缩小了每个子问题的求解范围。当然,代价是只能得到近似最优解。虽然本工作并未给出与全局最优解的差距的理论分析,但从实验中我们可以看到这一差距非常小。具体来说,Alpa首先将整个集群抽象为一个2维网格(mesh),并假定每行(列)内的设备都能以同一带宽相互通信。基于这一抽象,Alpa仅允许在这2维网格内以行为粒度,或在单行内进行划分,以此来保证submesh内的带宽,同时降低解空间的复杂度。在第一层中,为了找出最优的划分策略,Alpa会尝试不同的stage与submesh的组合方式,并将每种划分方式都交给第二层的求解过程去求解出每个stage的执行时间。基于第二层给出的stage执行时间,Alpa便能估计出这种划分方式在流水线执行模式下的整体执行时间(如下图),从而判断这种划分方式的好坏。当然,为每一种可能的组合都去做这样的计算的效率十分低下,因此Alpa使用动态规划,并应用了许多剪枝方法来减少求解的开销。在第二层中,对于每个stage,Alpa为其中所有算子枚举所有可能的划分方式,并通过整数线性规划来找到其中最优的划分方式,来最小化由计算、划分导致的通信、不同算子之间划分方式不匹配导致的额外通信,这三部分组成的总开销。由于算子的种类并不多,因此可以通过枚举与profiling的方式构造出这一线性规划问题。基于上述两层求解得到的结果,Alpa便能构造出每个设备所需的计算图,并基于XLA以及GSPMD来实现具体的训练逻辑。Alpa针对几个具有代表性的大模型进行了测试。在GPT中,Megatron-LM是一个人工优化非常极致的baseline,但其仅针对GPT模型,而Alpa能始终达到与其持平的性能。在其他两个模型中,Alpa则能获得比手工优化的策略高出数倍的性能。与高性能相对的,是Alpa引入的编译计算图的开销。不过与动辄数天甚至数周的大模型训练相比,小时级别的编译开销尚处在可接受范围内。Looking Beyond GPUs for DNN Scheduling on Multi-Tenant ClustersJayashree Mohan, Amar Phanishayee, and Janardhan Kulkarni, Microsoft Research; Vijay Chidambaram, University of Texas at Austin and VMware Research这篇文章来自Microsoft Research。该工作提供了一种面向多租户集群的DNN任务调度器,在传统调度器的基础上将任务对CPU及内存资源分配的敏感度纳入考虑,从而更好地分配和利用现有的集群资源,提高平均任务完成时间。背景近年来由于神经网络的广泛普及,DNN训练已经成为众多企业和云数据中心的一项主流工作负载。企业通常会设置大型多租户集群,配备GPU等硬件,来供多个用户和生产组共享。除了一些特定于模型的参数与脚本外,一项训练任务在运行前还需要人为指定其GPU需求,而后将被交由集群的任务调度器进行调度和管理。这些 DNN 任务调度器决定如何将 GPU 资源分配给多个任务,同时实施复杂的集群范围的调度策略以优化目标,例如平均任务完成时间 (JCT)和用户级公平性。问题现有集群使用的任务调度器主要分为两类,一类是传统的大数据调度器,例如 Kubernetes 或 YARN;另一类是新式调度器,能够利用 DNN 任务特征以获得更好的性能和利用率。这两种调度器都存在一个问题,即它们都假定GPU为调度任务的主要资源,而CPU、内存等其他资源只是简单的根据用户指定的GPU数量进行成比例分配,我们将这种分配方式称为GPU-proportional allocation。然而这种GPU-proportional allocation忽视了DNN训练任务的一种特性,那就是不同的DNN训练任务对于CPU、内存等资源表现出不同的敏感度。上图就展示了不同DNN训练任务的训练时长随着CPU数量增加的变化,左图显示多数图像和语音模型对 CPU 分配很敏感,比如将 CPU:GPU 比率从 3 增加到 12 会使 AlexNet 的训练速度提高 3.1 倍,将其增加到 9 会使 ResNet18 的训练速度提高 2.3 倍;而如右图所示,大多数语言模型对 CPU 分配不敏感,这是因为它们往往对于输入数据预处理的要求相对较少(而图像分类模型往往需要在每个 epoch 中为每个数据项执行数据增强操作)。此外先前有工作表明,CPU 周期在多租户集群中往往是没有得到充分利用的。因此基于上述观察,本文提出可以使用资源敏感分配(此处的资源指CPU、内存等除GPU之外的硬件资源)来代替 GPU-proportional allocation 以提高整体集群的利用率和效率。例如,我们可以将一个 CPU 敏感任务与一个 CPU 不敏感任务放在同一台机器上执行,从而提高集群的总吞吐量。本工作这篇工作提出Synergy是一个基于时间片机制的调度器,它能够整合GPU、CPU、内存等多种资源信息来对DNN训练任务进行资源分配与调度。在每个时间片中Synergy会对现有任务进行一次调度,每一次调度分为两个步骤:使用一种名为Optimistic Profiling(乐观分析)的机制,计算出能够使任务效率达到最佳的CPU与内存配额根据任务的GPU需求找出一组可运行任务,而后利用启发式调度算法(Synergy-Opt与Synergy-Tune算法)确认每个任务最终的资源分配情况并将它们分配到可用服务器上由于 DNN 训练具有高度可预测的结构,通过几次迭代的训练就能够对实际任务训练时间形成较为准确的估计。然而,简单地对所有CPU、内存资源的组合进行测试评估显然会带来非常大的开销,因此Synergy引入了Optimistic Profiling机制。Optimistic Profiling首先对每种CPU分配下的最高内存分配情况进行测试评估,剩余的资源组合由于DNN中缓存机制的使用能够很容易的被估算出来。Optimistic Profiling机制在保持高准确性(与实际值的偏差在3%以内)的同时,大大降低了资源分析的开销,其效率是简单枚举分析的近10倍。Synergy 的调度算法需要结合集群的硬件资源信息对各个任务进行资源分配与调度,其本质类似于一个多维装箱问题。这样的要求带来了两个挑战:一是找到 CPU 和内存的最佳分配,在确保公平分配的同时最大化吞吐;其次,找到这些任务在某个集群环境中实际可行的分配方式。对此文章提出了Synergy-Opt与Synergy-Tune两种算法:Synergy-OPT 算法:利用线性规划的思想找出分配最佳方案,并确定可能的吞吐上限。由于其计算成本过高,且往往在实际部署中无法实现,因此仅被用于衡量针对该问题实际解决方案的有效性。Synergy-Tune算法:利用启发式思想快速找出接近最佳的方案,与Synergy-OPT算法的偏差在10%以内,在Synergy中被实际应用。性能作者在物理集群上用不同工作负载对Synergy与GPU-proportional allocation两种资源分配模式进行了对比测试。在静态trace下,Synergy将makespan缩短了 1.4 倍;而在动态trace中,Synergy 将平均JCT 降低了 1.5 倍。作者还对Synergy与GPU-proportional allocation进行了模拟测试,在各种workload、各种调度策略下,Synergy相对GPU-proportional allocation均有不同程度的性能提升。最后,实验还显示Synergy带来了更高的资源利用率,在低负载下Synergy的CPU利用率为GPU-proportional allocation的1.5倍。Session-9: Isolation and OS ServicesCAP-VMs: Capability-Based Isolation and Sharing in the CloudVasily A. Sartakov and Lluís Vilanova, Imperial College London; David Eyers, University of Otago; Takahiro Shinagawa, The University of Tokyo; Peter Pietzuch, Imperial College London背景这篇论文是CHERI团队在RISC-V架构上实现CHERI扩展后,将其应用在机密虚拟机场景中。可以说是新瓶装旧酒,本身并没有很多创新的技术点。但是CHERI团队从2014年在ISCA上发表第一篇CHERI论文后,一直在该架构上持续研究(ASPLOS'15, SP'15, MICRO'16, ASPLOS'17, ASPLOS'19, MICRO19, SP'20, ISCA'21),并且尝试推到Arm和RISC-V架构中。这样的长期持续的工作还是值得我们学习和肯定的。这篇论文聚焦于解决现有的云计算栈的TCB大,同时只能够按照页粒度进行数据的共享与传递,跨VM之间的通信不高效(受限于页粒度,以及频繁的user/kernel/hypervisor的转换)。所以作者希望通过修改硬件的方式,提供一个动态的细粒度的内存划分机制,来支持机密计算。作者这里复用了CHERI的设计方案。CHERI的设计:CHERI将指针扩展为了capability。每一个cap规定能够访问内存的大小以及所对应的权限。CHERI通过特殊指令对cap进行创建,传递,销毁等。CAP能够存在寄存器以及内存中,如果cap被spill到内存中,会采用tag memory的方式,对存放cap的内存进行保护。CHERI的cap有三大特性:起源验证性:所有的cap只能够派生出来或者通过特殊的指令创建出来,不能够将任何的byte转换为cap。cap的完整性:存放在内存中cap不能够被修改。(通过tag memory 保护)cap的单调性:cap的权限和范围只能够收缩,比如范围减小,将读写变成只读。创建基于cap的划分:因为cap的存在,可以让不同的模块运行在同一个地址空间中,通过cap进行消息的传递以及function call。在此基础上又分为两个模式:pure cap以及hybrid cap:Pure cap:所有的指针都必须是cap,同时必须使用cap-aware的指令Hybrid cap:包含了未经修改的代码,以及一小部分cap aware的代码,能够使用cap对应的新指令。在该模式下,代码的隔离依赖两个cap:default data capability (ddc) 以及program counter capability (pcc)CHERI通过特殊的指令Cinvoke进行函数的调用,Cinvoke包含两个cap: 一个是目标函数的地址cap,一个是参数的cap。同时为了保护cap 不会被滥用,通过seal的方式对cap进行保护。使用cap实现cVM的挑战:能够支持cap-unware的软件,不需要代码修改:作者采用hybraid cap的方式,大部分的应用程序都不需要修改代码。能够兼容已有的OS的抽象,例如POSIX接口:采用了libOS的设计思路,兼容已有的OS抽象。能够提供一个高效且安全的IPC的机制:提供了两个基于cap 的通信原语,实现了异步的读写和跨cVM的函数调用。设计与实现在CHERI的cVM架构中,library OS和用户程序运行在一个cVM中,在cVM下运行了一个Intravisor,作为可信基的一部分,管理所有的cap权限,负责cVM的生命周期,同时实现了在libOS中无法实现的特权原语(storage, network ,time,同步等)。在该架构中libOS和component是不可信的。在该架构中有两层隔离的边界:(1)通过libOS实现的program之间的隔离,用户程序通过C library使用Cinvoke调用libOS提供的syscall,其中用户的程序可以做到cap不感知;(2)通过Intravisor使用cap实现cVM之间的隔离,同样libaOS通过Cinovke和Intravisor进行交互。cVM的创建和通信cp_cvm_make,类似于fork/exec接受一个磁盘的镜像,创建一个cVM,同时指定需要运行的函数。CP_FILE:CP_FILE能够绕过Intravisor的干预直接进行内存的访问。通过cp_file_make在Intravisor中注册一个共享内存区域,接收者可以通过一把相同的key在intravisor中找到对应的share buffer,并获得对应的cap,之后libOS会使用cap-aware的代码将数据拷贝到目标的cVM中。为了实现异步的读写,作者除了使用read,write接口之外还使用了notify和wait的接口。CP_call: cp_call_make会在Intravisor中注册一个对外暴露的函数,cp_call_get允许caller查找是否有对应注册的函数(通过相同的key),之后通过cp_call 调用其他cVM暴露的函数。CP_stream:结合了CP_file和CP_call,能够提供复杂的通信抽象,例如以stream为对象的通信接口。OCALL与ICALL:CInvoke会带有两个受保护的cap:Program Counter Capability (pcc)以及default data capability (DDC)。当跳转到callee中的时候,cap会被unseal被赋值到对应的cap寄存器中。对于ICALL而言,Intravisor会entry point的pcc cap以及要传的参数对应的cap作为参数传给CInoke。对于OCALL而言, Introvisor事先会将out layer的dcc以及ret或者ocall的目标地址对应的pcc的cap以sealed形式存在内存中。隔离域内部的程序,通过从内存中加载这些cap,作为参数传给CInvoke。CAP的管理和撤销:只有标准C library,libOS以及Introvisor能够管理cap,使用cap-ware的指令。只有Introvisor能够将cap存在内存中,其他部分都只能使用cap register。这样introvisor想要revoke一个cap只需要将对应的cap寄存器清除即可,省去了复杂的GC过程。安全性分析因为libOS是可以受到攻击者控制,那它会不会将cVM对应的cap扩大,从而非法的访问其他的cVM。一般而言,libOS是无法创建一个超越自己cap范围的新cap,但是libOS有两个途径会接受外部的cap:在return/ocall的时候,会从内存中加载cap。但是这些cap都是sealed的形式的,所以无法unsealed创建出一个新的cap出来。对于CP_File而言,通信中传递的cap都是data cap,不会让libOS跳转到其他可以执行的代码中,因此也无法创建一个新可执行代码的cap。测试与实验实验平台CHERI支持的FPGA平台(100MHZ,5 stage,single core),但是有以下的缺点:1. 单核并且频率很低;2. 持久化设备是通过host进行模拟的;3. DRAM的latency相较于CPU的频率来说非常低。因此虽然有CHERI支持能够获得真实的性能,但是不能够用来测试内存以及IO intensive的应用。Sifive RISC-V Unmatch,没有CHERI的支持。将CHERI的指令用原始的RISC-V的指令进行模拟。应用测试作者采用NGINX/Redis作为两个microservice部署,并且用YCSB测试集进行测试。NGINX作为API的gateway,并且将请求最后发给Redis进行key/value的存储。作者将cVM和docker进行了对比的测试。对于一次收发的请求,docker的通信是通过TCP进行的,需要多次下陷以及4次拷贝;而对于cVM来说,只需要2次copy,这里cVM采用的CP_Stream的通信抽象取代了慢速的TCP通信。以上的测试只能够在sifive的平台中进行,测试结果表明cVM相较于docker有更好的99%和50%的延迟,减少了20% ~ 40%的开销。为了更好的测试真实平台上的性能,作者只测试Redis通过TCP/IP以及CP_Stream做通信的latency分布。这个测试在FPGA以及sifive上都进行了实现。测试结果表明,不论是Sifive还是FPGA平台,cVM都有更好的latency分布。不同的通信机制对比作者将CP_file和CP_Stream以及pipe,sockets,TCP/IP以及mmap+memcpy+munmap (MAP+CPY)的性能做了对比。可以发现不管在哪种配置下CP_file拥有最接近memcpy的性能。CP_stream因为采用异步的操作,所以在单核上的FPGA上性能较差。其他的IPC baseline都比CP_file至少有两倍的性能下降,因为存在更多的data copy。其中Unix socket的性能最好,因为支持双向的发包。另外作者还测试了memcpy+mmap的开销,mmu的操作也会带来较大的性能开销。(这里两个平台上性能差距很大,相较而言sifive的性能数据更加真实)。KSplit: Automating Device Driver IsolationYongzhe Huang, Pennsylvania State University; Vikram Narayanan, David Detweiler, University of California, Irvine; Kaiming Huang, Gang Tan, Trent Jaeger, Pennsylvania State University; Anton Burtsev, University of California, Irvine & University of Utah在先前的研究中已经有许多工作展示出最近的CPU扩展支持实用的、低开销的驱动隔离,从而保护内核不被这些设备驱动的漏洞所攻陷。本文认为性能已经不再是这类工作的主要问题,主要挑战已经变成了隔离设备驱动的复杂性。由于设备驱动和内核扩展是在共享内存环境下开发的,内核和驱动会共同使用许多复杂且层级化的数据结构,这就使得编程者很难去保证这些共享状态被正确同步了。本文认为先前的驱动隔离工作主要有两点不足:自动化程度低,需要大量人工成本,如LXD,LXFI。适用范围小,如Decaf,Microdriver本文提出了KSplit,一个可以在当前完整特性的内核中对未经修改的设备驱动进行隔离的框架。其优势优势在于:适用范围广,而不是像Decaf只能针对个别类型的驱动。自动化程度高,在分析复杂驱动时人工介入会非常小。对同步数据这一过程进行了优化,从而使得隔离后的性能开销低。需要注意的是本文的威胁模型更聚焦于safety,不是security。场景是防止驱动触发Bug后错误操作内核内存而导致kernel崩溃。对于来自驱动的恶意攻击是不能防御的,这和不相信内核接口的LXFI的安全性相比是有所下降的。KSplit能对未经修改的内核代码和驱动代码进行高度自动化的分析,从而:识别内核和驱动之间共享的状态分析出这个共享状态在高效隔离下的同步需求具体来说,KSplit会对内核和驱动的代码运行一系列静态分析从而生成在隔离环境下运行驱动的同步代码。如上图所示,它会把内核和驱动代码作为clang的输入转换成LLVM IR,然后在llvm中进行分析:识别内核和驱动间的共享状态为每次跨边界处计算数据同步(就是精准算出这次要同步的数据,不要把所有数据都同步一遍)为并发原语计算数据同步推测有歧义的数据类型分析的结果是一系列过程调用,以KSplit的IDL(interface definition language)的形式记录。其后会被交给KS的IDL(interface definition language)编译器以生成胶水代码从而保证被隔离子系统间的数据同步。对于那些有歧义的地方编译器会报warning给开发者去人工介入处理。开发者要把每个warning变成一个IDL才能让编译器跑完,然后会生成让隔离系统之间数据同步的glue code。本文基于LVD进行了实现并在Linux内核的九个子系统上进行测试。测试中使用KSplit为来自多个Linux子系统的354个驱动生成IDL。然后通过隔离与验证其中10个驱动来评估其有效性。例如,对于一个完整的ixgbe驱动,KSplit仅需要对自动生成的2476行接口specification修改53行并且修改原本驱动代码19行。这展现出KSplit是一个实用的驱动隔离工具。(而另外那344个并没有被实际运行过,因此是否真的有效并不清楚,但是作者认为通过把它们生成出来的过程就能看出这个方案的通用性好且人工介入成本不高。)性能方面,首先测试了microbenchmark,对比的是LVD。本文对于跨隔离边界的调用由于涉及额外的数据同步,因此会带来一定的开销。从下表可知,同步的参数数据量越多,开销也就越大。microbenchmark可能不太直观,本文进一步用真实应用memcached进行了测试,在一个10核的机器上逐渐增加server进程数量,下图可以看出开销都在5.4% ~ 18.7%之间,性能也可以接受。Operating System Support for Safe and Efficient Auxiliary ExecutionYuzhuo Jing, Peng Huang, Johns Hopkins University现在很多生产环境下的应用需要频繁靠运维去测试,优化,调试和控制它们的执行。以前这大部分靠人工,不过现在越来越多应用采用自我管理的方式。事实上,已经有许多应用执行辅助任务(auxiliary task)来帮助自身进行错误检测,性能监控,线上诊断和资源管理等操作。在当前操作系统上通常有两种方案来开发auxiliary task:auxiliary task和主程序运行在同一个进程内,作为一个线程或是直接函数调用被主程序使用,auxiliary task和主程序共享同一个地址空间。但是这样做的话auxiliary task就可以对主程序的性能造成干扰,并且auxiliary task的bug可能会影响主程序的可靠性。auxiliary task运行在另一个进程中。但是这种方案就会限制auxiliary task去观察主程序的状态,即使能够观察到,也难以去修改主程序的状态。从上面两点可以看出目前操作系统上可观测性和隔离性是矛盾的,因为当前的OS抽象(进程和线程)都是为了主程序而设计的,并不适合auxiliary task。那么之前有没有工作想解决类似问题?有,先前在系统和安全社区已经有很多工作为sub-process提出了很多机制。但是如下图所示,作者将这类保护主程序免受auxiliary task影响的场景进一步细分为3类:应用的扩展(插件)场景;安全隔离场景;运维场景。本文关注的是第三个运维场景,而先前的工作则都关注于前两个。类似SFI等机制是为了应用的扩展(插件)场景,设计的目的是安全地执行一些不可信的第三方扩展,例如浏览器扩展和在数据库查询中的用户定义函数。另一类抽象是Wedge和IwC,是为了安全隔离场景而设计的,具体来说保护主程序中的一些敏感过程,如session handler和秘钥签名,防止应用被攻占。这些现有的机制对第三个场景:运维场景,是不合适的。该场景下auxiliary task是相同开发者开发的,是可信的。它们天生就需要和主程序交互并不断观察主程序的最新状态。他们常常还需要修改主程序的一些状态!如下图所示,本文为OS引入一个新的抽象:Orbit。Orbit使得开发者能够方便地为主程序增加许多auxiliary task,并且这些auxiliary task能够安全(safely)且高效地辅助应用。先比现有sub-process抽象,orbit有一些独特之处:它是一等的执行实体,有着专属的地址空间并且可以被调度。每个Orbit都和一个主进程绑定,但是提供了很强的隔离性:a. 如果一个orbit任务有bug或者挂了,它不会影响主程序b. orbit是异步执行并且可以直接限制资源,因此主进程不会受到auxiliary task的性能干扰。orbit提供了很好的可观测性。每个orbit的地址空间几乎就是主程序的镜像,因此,当主进程调用一个orbit,后者可以在最新主进程的状态下运行auxiliary task。为了满足部分auxiliary task需要修改主进程,orbit也提供了受控制的改变能力从而safely apply updates。设计orbit有两大挑战:隔离性和可观测性是很难同时达到的;隔离性的开销很大,而共享内存等传统高效手段又和隔离性冲突。针对第一个挑战,本文设计了一个轻量级的内存snapshot解决方案。它利用了copy-on-write机制并且提供了自动状态同步机制。无论主进程何时调用orbit任务,都能够把内存状态从主进程的地址空间同步到orbit任务的地址空间。针对第二个挑战,本文观察到尽管auxiliary task可能会观察主进程中多个状态变量,但是每次调用中所需要观察的数据量对于整个程序的状态来说都是相对较小的。因此,本工作使用了一个简单的方法,把这些auxiliary task需要的状态合并(coalesce)到orbit area中。内核动态地识别调用所需的orbit area中active的内存页,并且只同步这些内存页到orbit中。轻量级的内存snapshot解决方案能够以page为粒度运行,这使得其在简单和鲁棒性上有优势,也易于移植到所有主流的OS中,而不用像一些复杂的技术如shadow memory那样要依赖完备的插桩。缺点是page粒度会导致写放大问题使得snapshot的开销更大(哪怕一个小object被改了都要snapshot整个page)。并且由于共享的COW page上的写保护它还常常会false sharing。本文设计了几个优化,包括增量式的snapshot,动态page模式选择和托管对象来降低开销。本文在linux 5.4.91上实现了orbit的原型,并且从6个大型应用中收集了7个auxiliary task来评估orbit抽象的通用性。本文还用orbit为apache写了一个新的auxiliary task。为了证明orbit的隔离能力,本文向orbit任务中注入错误。有些错误是代码里真的有的bug引起的。实验证明orbit能够保护主程序免受auxiliary task所有情况下的错误影响。本文还测试了应用的性能开销,结果显示orbit只会引入3.3%的开销。Q&AQ1:请问你能谈谈把Oribit应用在其它不同的代码项目上吗?例如SQL和Redis。你认为把Oribit适配给不同的数据库能有多容易?A1:我们提出Orbit是一种通用的方法,可以安全地检查任何内存状态,但与应用程序的类别解耦。它适用于应用程序中任何需要观察的任务。在我们的评估中,我们也将Orbit应用于网络服务器中的任务,如Apache(HTTPD)代理平衡器、Nginx WebDAV和Varnish池。适应每个任务所需的工作量取决于任务本身的复杂性,特别是它需要检查的变量的数量,以及它将对主程序进行的改变的复杂性。From Dynamic Loading to Extensible Transformation: An Infrastructure for Dynamic Library TransformationYuxin Ren, Kang Zhou, Jianhai Luan, Yunfeng Ye, Shiyuan Hu, Xu Wu, Wenqin Zheng, Wenfeng Zhang, and Xinwei Hu, Poincare lab, Huawei Technologies Co., Ltd, China这篇论文由来自华为的研究者们发表。动态装载器 (dynamic loader) 是软件基础设施中的重要一员,动态装载 (dynamic loading) 允许程序在运行时将需要的动态库加载到内存中,近期研究表明 Ubuntu 中超过 99% 的二进制都是动态链接程序。随着软硬件技术的不断发展,学术界和工业界都对 dynamic loader 提出了新的功能需求 (e.g., Intel MPK & SGX, library debloating, code re-randomization, binary rewriting, CFI, etc.)。然而目前原生的 dynamic loader 无法满足这些多样化的功能需求,导致不同的项目、产品各自会对 dynamic loader 做 ad-hoc 的修改。作者认为根据他们多年的工业界经验,这种定制化的修改会带来无法接受的维护成本,不同的修改之间难以兼容,已有的修改也很难被集成或复用。作者认为根本的原因在于目前的 dynamic loader 采取了一种 monolithic fashion 的实现方式,没有提供用于扩展的接口 。所以作者在本文提出了一套新的 dynamic loader 架构设计 iFed,iFed 采用模块化的设计方式,功能更多,配置更灵活且功能可扩展性更好 (新 feature 可以以 plug-in 的形式加入进来),同时与现有的 dynamic loader 接口兼容,对应用透明。iFed 的整体架构和工作流如上图所示。iFed 采取了基于 pass 的架构,除了基础的 library lookup 和 ELF parsing 功能之外,其核心组件就是一系列作用于动态库、对动态库进行变换和优化的 pass。不同的 pass 之间解耦且独立,每个 pass 都可以被单独启用或关闭,这也是 iFed 具有高度可扩展性和灵活性的原因。Pass manager 起到 meta loader 的作用,它会读取用户提供的配置文件 (包括用户期望启用哪些 pass 以及 pass 的执行顺序),加载并管理所有的pass,控制 pass 流水线的执行。然而为了达到上述的可扩展性和灵活性,就需要 pass 之间不会互相依赖,并且每个 pass 需要知道其他的 pass 是怎样变换动态库的。为此,iFed 提出了 RiMF (Runnable In-memory Format) 来描述动态库的状态。iFed 为每个程序维护一份 RiMF,其中包含该程序需要的所有动态库的状态信息,pass 之间共享这一份 RiMF,pass 可以通过 pass manager 提供的接口来查看和修改 RiMF 来对动态库做变换和优化。为了证明 iFed 可以灵活的支持更多的 feature,作者基于 iFed 实现了两个性能优化的 pass。第一个优化是 Dynamic Library Concatenation。通常我们会使用大页 (hugepage) 来降低 TLB miss 以减少地址翻译带来的开销,然而以往为动态库使用大页的方法各有缺点。如上图 (b) 所示,如果将一个较小的动态库的所有 section 放入同一个大页当中,那么就会因为页表权限问题造成安全隐患。又如上图 (c) 所示,使用 Linux 内核提供的 THP (transparent hugepage) 机制对于只使用几个大的动态库的程序来说可行,然而却无法扩展到动态库数目较多的情况。为了解决此问题,作者实现了一个 iFed pass,由于 RiMF 具有一个程序所需的所有动态库的信息,所以该 pass 可以从 RiMF 中收集到不同动态库的段信息,并修改 RiMF 将来自不同的动态库但具有相同页表权限的段加载到一起,形成一个更大的段并使用大页进行映射,如上图 (d) 所示。第二个优化是 Relocation Branch Elimination,动态链接程序在调用动态库的代码时,会先直接跳转到 plt (procedure linkage table) 中保存的跳板代码,然后再间接跳转到 got (global offset table) 表中保存的函数地址上,这也就导致了函数调用时需要额外的内存访问和跳转指令。为了消除额外的内存访问和跳转带来的开销,达到与静态链接相同的效果,作者实现的 iFed pass 直接将动态库中 cross-library 函数调用处的跳转地址修改为函数真正的地址,而不是 plt 中的跳板代码。值得注意的是,因为此优化需要重写动态库中的直接跳转指令,所以启用此优化后不同进程将将无法共享动态库的代码 (动态库在不同进程的地址空间中具有不同的 memory layout)。根据作者的测试结果,iFed 不仅能够支持不同架构下广泛的真实应用场景,而且作者提出的两点基于 iFed 的优化在 ARM 服务器上对应用最高有 33% 的加速,在 x86 的虚拟机上也对应用有最高 18% 的性能提升,而且这些性能提升是无需修改应用程序自身代码的。Application-Informed Kernel Synchronization PrimitivesSujin Park, Georgia Tech; Diyu Zhou and Yuchen Qian, EPFL; Irina Calciu, Graft; Taesoo Kim, Georgia Tech; Sanidhya Kashyap, EPFL该工作面向内核同步原语,旨在允许应用程序开发人员部署针对工作负载和硬件感知的内核同步策略,以提高应用程序的性能,解决内核锁的病态使用,甚至可以对感兴趣的内核锁进行动态分析。随着多核、异构硬件的发展,针对不同场景特定优化的锁被不断提出,以CNA和SHFLLOCK为代表的前序工作允许通过以策略的形式抽象出硬件和软件的要求来设计新的锁算法。然而在内核锁的场景下,这些前序工作的方法无法支持动态地改变内核中的锁策略,开发者仍然需要重新编译内核、重启机器来部署和测试新的锁策略,这显然给开发者带来很大麻烦。另一方面,支持用户态应用对内核进行动态定制以提升性能已经成为一种新的范式,例如Linux eBPF框架允许用户态应用动态定制网络数据通路操作、Syrup与ghOSt则允许动态定制调度策略等。因此该工作提出了支持用户态应用动态定制内核锁算法的框架SYNCORD,允许用户对内核中的每个锁进行定制以及细粒度分析调优。SYNCORD有三个主要目标:1)正确性,保证用户定制后的内核锁正确性不会受到影响;2)隔离性,防止用户定制代码导致内核崩溃;3)易用性,保证框架能够提供丰富的语义以满足多种用户、平台的需求。SYNCORD的关键构成以及一个工作流程样例如上图所示:1) 用户编写自定义锁代码并指定要定制的锁实例;2) SynCord基于eBPF编译用户的锁代码;3) 验证编译后的字节码的基本属性以保障正确性;4) 如果验证失败,SynCord会通知用户;5) 否则会将字节码加载到内核中并生成相应的补丁;6)最后将补丁打入内核,这样就可以通过预定义的钩子节点调用用户定制的锁代码了。在实现方面,SYNCORD在现有成熟的eBPF框架以及Kpatch工具基础上进行了扩展,支持了对用户自定义所代码的验证以及对内核锁实例的细粒度补丁。为了评测SYNCORD在不同锁应用场景中的效果,作者使用SYNCORD框架针对这些场景实现了相应优化并与前序工作的性能进行了对比。以非对称多核处理器(AMP)场景为例,作者基于前序工作LibASL的设计(LibASL是由IPADS实验室发表于PPOPP'22的锁优化工作)在SYNCORD中实现了相应优化。测试结果如下图所示,使用SYNCORD框架的实现在多种场景下的性能达到了与LibASL原有实现接近的水平。本文由以下作者共同完成:张懿雯,上海交通大学IPADS实验室准硕士一年级王子轩,上海交通大学IPADS实验室准博士一年级陈家浩,上海交通大学IPADS实验室博士二年级冯二虎,上海交通大学IPADS实验室博士二年级韩明聪,上海交通大学IPADS实验室博士二年级李鼎基,上海交通大学IPADS实验室博士二年级宋小牛,上海交通大学IPADS实验室博士三年级
正文
OSDI 2022 阅读评述连载(三)
此篇文章发布距今已超过972天,您需要注意文章的内容或图片是否可用!
还没有评论,来说两句吧...