一、总论
在形形色色的系统设计中,无论是嵌入式系统、个人桌面系统、分布式系统还是 LLM 推理引擎系统,通常有一些非常恒定的指标,或者说追求的目标。而且为了达到这些指标,采用的方法论甚至都是类似的。
我想在这篇文章,去记录一下系统中涉及的那些指标,以及常见的方法论,进而分析一下这些指标的本质。
二、Throughput
2.1 降低 Latency
降低 latency 是非常直观提高吞吐的一种方式。只要对于单个任务的处理时延降低了,那么单位时间内能处理的任务就会增加。
但是这种方式并没有什么好讨论的必要,很多时候,我们优化吞吐量,基于的前提都是,单个任务的时延是不可改变的。
2.2 Batch
虽然处理一个任务的时延不可改变,但是我们可以通过同时处理多个任务的方式,来提高吞吐。
批处理本质是并行的一种子类,因为不同任务之间完全没有依赖,所以这是最为简单的一种并行。只要系统资源足够,那么批处理就可以大大提高吞吐。
三、Latency
3.1 本质
在一个多任务系统中,一个任务的总时延可以分为两个部分:
- 排队时延
- 处理时延
针对这两种不同的时延,我们有不同的方法。
降低时延的方法论,往往是通过提高瓶颈资源的利用率的方式来实现的。
3.2 Schedule
调度不同任务的执行顺序,可以有效的减少任务的排队时延。
调度有的时候也会改善吞吐。但是仔细思考就会发现,如果计算资源一直满负荷运行(这本质上是处理时延无法再压缩了),无论怎么调度,完成一批任务所需要的时间都是相同的,也就是吞吐并不会变化。
在实践中,调度改善吞吐,是因为有些资源被闲置了,而调度可以更加充分的利用这些闲置的资源。这本质上是缩短处理时延的一种体现。
3.3 Asynchronous
异步同样也是改善处理时延的一种方式。任务通常由很多个存在依赖、计算资源利用率不同的子任务组成的。如果能够打破“串行执行子任务”的思维定势,将没有依赖的子任务异步执行,减少忙等时间,提高资源的利用率。那么就可以降低时延。
3.4 Speculation
投机是一种在时间维度上预先完成子任务,甚至是减少子任务数量的数量。为了实现投机,必须能够预测任务的行为,这就要求我们深入考量任务的计算特性。
Prefetch 就是常见的投机手段。
其实在某种意义上,cache 也是一种投机手段,它通过利用任务的局部性(locality)来实现投机,减少数据的搬运。
3.5 Pool
池化从两个方面改善时延。一方面,池化将资源变得更加“细粒度”,因此气泡会减少,资源利用率会提高。
另一方面,池化会将许多不同任务的相同子任务“合并同类项”,比如将所有线程都初始化好,等待处理任务。
在某种程度上来说,分页式的虚拟内存,都可以理解成一种对于物理内存的池化管理。
3.6 Trading
比较直观的,就是”以存代算“和”以算代存“两种。Trading 的本质,是用非瓶颈的资源,去交换那些瓶颈的资源。
交换的方式也可以比较隐晦,比如说”近存计算“,就是将原本的数据搬运改成了控制流搬运。