我们大致可以将收集方式分成三类:
最主要的区别是对各个指标的定义的区别,例如Nvidia中GenAI-Perf对性能指标的定义,或者
一、在client端收集#
原理:当采用流式传输时,client端可以通过记录发送请求和收到tokens的时间戳来收集TTFT、ITL、e2e_latency,自然也就能推算出TPOT和throughput等。但这样的方式里,TTFT会包含token编解码的时间和一些server的启动时间,而ITL不会包含
特点:
- 这种方式可以不影响serve端代码,但是指标的结果可能没那么精确,因为需要做de-tokenization,而且不同工具对于ITL的定义不一致。
- 除了收集perf指标外,这类工具往往也集成了load test功能(基本上都是复现或者直接使用 Locust and K6)和compatibal APIs(如OpenAI的API,etc.)。
当然,我们也可以自己实现这些东西,只要采用了流式传输,这些都很简单。
二、在server端收集#
代表:vllm、我自己写的包装器
原理:这里记录两种方式
- 通过给forward函数进行包装,可以追踪记录model级别或者layer级别的性能。这种方式不会更改模型代码,但需要确保包装是在最上层的。
- 直接修改LLM的代码,例如写一个CustomLM,继承LLaMAforCausalLM,然后在内部修改即可。这种方式可能会更改模型代码,但也可以自定义实现很多其他功能,适合自定义系统。
特点:这种方式可以做到更为精确,可以直接获取TPOT,也不强求流式传输的机制。但这种方式耦合比较严重,适合系统内部集成(例如vllm)。
三、在kernel层面收集#
代表:nsight compute、pytorch profiler、nsight profiler…(这种一般都叫“xxx profiler”)
原理:追踪算子并将其数据收集到一个数据库,例如ncu是sqlite,然后再渲染数据库到dashboard。(更具体的我也不那么清楚) 特点:粒度足够细,信息很全面,但是渲染和插叙也很慢。
四、在cluster层面收集#
代表:DCGM 特点:
- 支持与k8s体系配合,支持exporter、grafana、OpenTelemetry等等。
- 需要集群的root权限,否则一些指标如SM Activity获取不到。