Open fong-git opened 1 month ago
嗨,我也发现了类似的问题,我这边简单分析了下,lmdeploy比vllm在vit部分平均增加的耗时是由于lmdeploy需要将vit的feature遍历从gpu到cpu,也就是下面图中的x.cpu()引起的。vllm不需要此环节
哈喽 下午好! 非常感谢你的解答,我这边把x.cpu()注释掉以后 vit的处理时间还是很慢呢,还是要300ms左右。不知道你那边注释了以后推理速度怎么样呢
丰 @.***
------------------ 原始邮件 ------------------ 发件人: "InternLM/lmdeploy" @.>; 发送时间: 2024年10月23日(星期三) 下午2:48 @.>; @.**@.>; 主题: Re: [InternLM/lmdeploy] [Bug] InternVL2-2B的推理速度慢,发现是视觉特征提取的耗时很长 (Issue #2604)
嗨,我也发现了类似的问题,我这边简单分析了下,lmdeploy比vllm在vit部分平均增加的耗时是由于lmdeploy需要将vit的feature遍历从gpu到cpu,也就是下面图中的x.cpu()引起的
image.png (view on web)
— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you authored the thread.Message ID: @.***>
我这边注释掉之后基本上就少了对应的to cpu的时间,而且vit整体的性能我测试来看lmdeploy和vllm是近似的(去掉to cpu的话)。
但是这里虽然是去掉了to cpu时间,后面还是会进行gpu到cpu同步的,lmdeploy逻辑是这样实现的
但是这里虽然是去掉了to cpu时间,后面还是会进行gpu到cpu同步的,lmdeploy逻辑是这样实现的
所以是lmdeploy这里即便注释掉tocpu()了,后面还是会进行GPU到CPU的同步是吗,就是整体的时间哈还是不会减少吗
@fong-git
我不确定你是怎么统计的时间,比较准确的方式是去除预处理时间,然后 vision model forward 前后对 stream 进行同步。下面是我之前测的两个vision模型 forward 的时间。
lmdeploy 没有对 vision 模型做 tp,所以 tp 对 lmdeploy 的 vision部分没有收益。大 batch tp 下会比 vllm 慢一些,不过现在 vision 模型都比较大,显存不一定支持跑那么大的 batch。
@fong-git @sjzhou4
关于 to cpu 的问题,之前 pytorch backend 遇到一个问题,就是如果不做 to cpu 的话,得到的图片特征结果会不正确,这可能跟 vision模型跑在单独的线程有关系 (asyncio executor)。to cpu 对单个请求的时延会有影响,对整体吞吐应该没影响,因为并不会阻塞请求。
另外感觉 to cpu 其实省略不了,因为如果后面要支持 prefix caching的话,是要保存一定数量的图片特征的,这样可以避免在对话过程中重复提取特征,而因为显存的原因,特征存在内存中是一个比较好的方式。
@irexyc 我测了vision model的单纯GPU计算feature的时间和vllm是差不多的,但是在VLAsyncEngine类的_get_prompt_input中统计features = await self.vl_encoder.async_infer(images)的时间会比vllm慢很多,导致实际测下来的推理速度比vllm慢
@fong-git 我这边实测在tp均为4的情况下,lmdeploy比vllm慢500ms左右,feature推理时间基本一致,问题就在于to cpu这部分,vllm是直接把GPU 的torch tensor传入后续流程的:
def merge_multimodal_embeddings(input_ids: torch.Tensor,
inputs_embeds: torch.Tensor,
multimodal_embeddings: NestedTensors,
placeholder_token_id: int) -> torch.Tensor:
"""
Merge ``multimodal_embeddings`` into ``inputs_embeds`` by overwriting the
positions in ``inputs_embeds`` corresponding to placeholder tokens in
``input_ids``.
Note:
This updates ``inputs_embeds`` in place.
"""
mask = (input_ids == placeholder_token_id)
num_expected_tokens = mask.sum().item()
assert isinstance(num_expected_tokens, int)
flattened = _flatten_embeddings(multimodal_embeddings)
if flattened.shape[0] != num_expected_tokens:
expr = _embedding_count_expression(multimodal_embeddings)
raise ValueError(
f"Attempted to assign {expr} = {flattened.shape[0]} "
f"multimodal tokens to {num_expected_tokens} placeholders")
inputs_embeds[mask] = flattened
return inputs_embeds
@irexyc @fong-git 是的,lmdeploy的to cpu 是不能缺少的,就像 @Dimensionzw 说的那样,lmdeploy和vllm的架构设计有区别的,lmdeploy更多的是在上层进行模版拼接、特征提取等工作,最后把这些inputs信息传递到turomind backend端进行处理。而且像 @irexyc 说的,后面的prefix caching等,也可能会使用内存、甚至硬盘来存储特征信息,进而优化显存的占用,这些都是需要to cpu操作的
@irexyc @fong-git 是的,lmdeploy的to cpu 是不能缺少的,就像 @Dimensionzw 说的那样,lmdeploy和vllm的架构设计有区别的,lmdeploy更多的是在上层进行模版拼接、特征提取等工作,最后把这些inputs信息传递到turomind backend端进行处理。而且像 @irexyc 说的,后面的prefix caching等,也可能会使用内存、甚至硬盘来存储特征信息,进而优化显存的占用,这些都是需要to cpu操作的
在lmdeploy里,如果不开启prefix caching,是不是就不需要to cpu操作?
我们部署到V100后也发现推理巨慢,4B模型,推理一张要20秒,还在找原因中,太慢了。
原因基本是:lmdeploy在al或者vl模型使用的特征抽取,其实都是用的python去做的,而vllm是用算子kernel实现的,我这边简单测试了下,在vit网络的foward,基本上lmdeploy的性能是vllm的1/3。然后大batch,性能下降更明显
还有就是上面提到的.cpu()的问题,其实这部分的时间在目前al和vl消耗并不大,比如vl上面,256 n hidden_size 2 / 1024 /1024/ 1024 /pcie带宽 1000 ms,基本上都在10ms以内了
internvl2-2B, 一张(131, 259)的图片,to cpu耗时80ms,preprocess+vision model加起来才30ms 0.5几的版本开启过prefix-caching,VLM结果不正确,我理解目前只适用于LLM 现在用0.6.3,我打算直接禁掉to cpu这步操作了...
Checklist
Describe the bug
使用Transformer、vllm、LMdeploy对InternVL2-2B进行推理,max_num_patch都设置为12,推理结果发现: Transformer平均691ms/条 VLLM平均308ms/条 LMdeploy平均523ms/条 对VLLM和LMdeploy耗时进行分析发现,vllm的vit部分平均耗时9ms,LMdeploy的vit部分平均耗时323ms。 LMdeploy的vit统计时间在VLAsyncEngine类的_get_prompt_input中统计``
Reproduction
from lmdeploy import pipeline, TurbomindEngineConfig, PytorchEngineConfig from lmdeploy.vl import load_image import os import time
PROMPT_SYSTEM = """ 根据图片,判断该文档所属的文档类别。 请严格按照如下的格式进行回复,不要输出多余的解释(注意不要强行给文档分一个不正确的类别:对于不属于特定类别的文档,判别为‘其他文档’): 文档类别:该文档所属的文档类别 """
model = 'model/OpenGVLab/InternVL2-1B'
model = 'model/OpenGVLab/InternVL2-2B' pipe = pipeline(model, backend_config=TurbomindEngineConfig(session_len=8192,model_format='hf')) img_path = './cs_function_recommendation_bak/test_data/image' imgs = os.listdir(img_path) totle_time = 0 vit_time_total =0 for img in imgs[:100]: image = load_image(os.path.join(img_path,img))
print(vit_time_total) print(totle_time)
Environment
Error traceback
No response