0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

你应该知道的18个PyTorch小技巧

OpenCV学堂 来源:AI公园 作者:AI公园 2022-06-22 10:00 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

导读

你应该知道的18个PyTorch小技巧。

调试深度学习pipelines就像找到最合适的齿轮组合

你为什么要读这篇文章?

深度学习模型的训练/推理过程涉及很多步骤。在有限的时间和资源条件下,每个迭代的速度越快,整个模型的预测性能就越快。我收集了几个PyTorch技巧,以最大化内存使用效率和最小化运行时间。为了更好地利用这些技巧,我们还需要理解它们如何以及为什么有效。

我首先提供一个完整的列表和一些代码片段,这样你就可以开始优化你的脚本了。然后我一个一个地详细地研究它们。对于每个技巧,我还提供了代码片段和注释,告诉你它是特定于设备类型(CPU/GPU)还是模型类型。

列表:

  • 数据加载

    1、把数据放到SSD

    2、Dataloader(dataset, num_workers=4*num_GPU)

    3、Dataloader(dataset, pin_memory=True)

  • 数据操作

    4、直接在设备中创建torch.Tensor,不要在一个设备中创建再移动到另一个设备中

    5、避免CPU和GPU之间不必要的数据传输

    6、使用torch.from_numpy(numpy_array)或者torch.as_tensor(others)

    7、在数据传输操作可以重叠时,使用tensor.to(non_blocking=True)

    8、使用PyTorch JIT将元素操作融合到单个kernel中。

  • 模型结构

    9、在使用混合精度的FP16时,对于所有不同架构设计,设置尺寸为8的倍数

  • 训练

    10、将batch size设置为8的倍数,最大化GPU内存的使用

    11、前向的时候使用混合精度(后向的使用不用)

    12、在优化器更新权重之前,设置梯度为Nonemodel.zero_grad(set_to_none=True)

    13、梯度积累:每隔x个batch更新一次权重,模拟大batch size的效果

  • 推理/验证

    14、关闭梯度计算

  • CNN (卷积神经网络) 特有的

    15、torch.backends.cudnn.benchmark = True

    16、对于4D NCHW Tensors,使用channels_last的内存格式

    17、在batch normalization之前的卷积层可以去掉bias

  • 分布式

    18、用DistributedDataParallel代替DataParallel

第7、11、12、13的代码片段

#CombiningthetipsNo.7,11,12,13:nonblocking,AMP,setting
#gradientsasNone,andlargereffectivebatchsize
model.train()

#ResetthegradientstoNone
optimizer.zero_grad(set_to_none=True)
scaler=GradScaler()
fori,(features,target)inenumerate(dataloader):
#thesetwocallsarenonblockingandoverlapping
features=features.to('cuda:0',non_blocking=True)
target=target.to('cuda:0',non_blocking=True)

#Forwardpasswithmixedprecision
withtorch.cuda.amp.autocast():#autocastasacontextmanager
output=model(features)
loss=criterion(output,target)

#Backwardpasswithoutmixedprecision
#It'snotrecommendedtousemixedprecisionforbackwardpass
#Becauseweneedmorepreciseloss
scaler.scale(loss).backward()

#Onlyupdateweightseveryother2iterations
#Effectivebatchsizeisdoubled
if(i+1)%2==0or(i+1)==len(dataloader):
#scaler.step()firstunscalesthegradients.
#IfthesegradientscontaininfsorNaNs,
#optimizer.step()isskipped.
scaler.step(optimizer)

#Ifoptimizer.step()wasskipped,
#scalingfactorisreducedbythebackoff_factor
#inGradScaler()
scaler.update()

#ResetthegradientstoNone
optimizer.zero_grad(set_to_none=True)

指导思想

总的来说,你可以通过3个关键点来优化时间和内存使用。首先,尽可能减少i/o(输入/输出),使模型管道更多的用于计算,而不是用于i/o(带宽限制或内存限制)。这样,我们就可以利用GPU及其他专用硬件来加速这些计算。第二,尽量重叠过程,以节省时间。第三,最大限度地提高内存使用效率,节约内存。然后,节省内存可以启用更大的batch size大小,从而节省更多的时间。拥有更多的时间有助于更快的模型开发周期,并导致更好的模型性能。

1、把数据移动到SSD中

有些机器有不同的硬盘驱动器,如HHD和SSD。建议将项目中使用的数据移动到SSD(或具有更好i/o的硬盘驱动器)以获得更快的速度。

2. 在加载数据和数据增强的时候异步处理

num_workers=0使数据加载需要在训练完成后或前一个处理已完成后进行。设置num_workers>0有望加快速度,特别是对于大数据的i/o和增强。具体到GPU,有实验发现num_workers = 4*num_GPU 具有最好的性能。也就是说,你也可以为你的机器测试最佳的num_workers。需要注意的是,高num_workers将会有很大的内存消耗开销,这也是意料之中的,因为更多的数据副本正在内存中同时处理。

Dataloader(dataset,num_workers=4*num_GPU)

3. 使用pinned memory来降低数据传输

c72fed82-f177-11ec-ba43-dac502259ad0.png

设置pin_memory=True可以跳过从可分页memory到pinned memory的数据传输

GPU无法直接从CPU的可分页内存中访问数据。设置pin_memory=True 可以为CPU主机上的数据直接分配临时内存,节省将数据从可分页内存转移到临时内存(即固定内存又称页面锁定内存)的时间。该设置可以与num_workers = 4*num_GPU结合使用。

Dataloader(dataset,pin_memory=True)

4. 直接在设备中创建张量

只要你需要torch.Tensor,首先尝试在要使用它们的设备上创建它们。不要使用原生Python或NumPy创建数据,然后将其转换为torch.Tensor。在大多数情况下,如果你要在GPU中使用它们,直接在GPU中创建它们。

#Randomnumbersbetween0and1
#Sameasnp.random.rand([10,5])
tensor=torch.rand([10,5],device=torch.device('cuda:0'))

#Randomnumbersfromnormaldistributionwithmean0andvariance1
#Sameasnp.random.randn([10,5])
tensor=torch.randn([10,5],device=torch.device('cuda:0'))

唯一的语法差异是NumPy中的随机数生成需要额外的random,例如:np.random.rand() vs torch.rand()。许多其他函数在NumPy中也有相应的函数:

torch.empty(),torch.zeros(),torch.full(),torch.ones(),torch.eye(),torch.randint(),torch.rand(),torch.randn()

5. 避免在CPU和GPU中传输数据

正如我在指导思想中提到的,我们希望尽可能地减少I/O。注意下面这些命令:

#BAD!AVOIDTHEMIFUNNECESSARY!
print(cuda_tensor)
cuda_tensor.cpu()
cuda_tensor.to_device('cpu')
cpu_tensor.cuda()
cpu_tensor.to_device('cuda')
cuda_tensor.item()
cuda_tensor.numpy()
cuda_tensor.nonzero()
cuda_tensor.tolist()

#PythoncontrolflowwhichdependsonoperationresultsofCUDAtensors
if(cuda_tensor!=0).all():
run_func()

6. 使用 torch.from_numpy(numpy_array)torch.as_tensor(others)代替 torch.tensor

torch.tensor() 会拷贝数据

如果源设备和目标设备都是CPU,torch.from_numpytorch.as_tensor不会创建数据拷贝。如果源数据是NumPy数组,使用torch.from_numpy(numpy_array) 会更快。如果源数据是一个具有相同数据类型和设备类型的张量,那么torch.as_tensor(others) 可以避免拷贝数据。others 可以是Python的listtuple,或者torch.tensor。如果源设备和目标设备不同,那么我们可以使用下一个技巧。

torch.from_numpy(numpy_array)
torch.as_tensor(others)

7. 在数据传输有重叠时使用tensor.to(non_blocking=True)

c73fd594-f177-11ec-ba43-dac502259ad0.png

重叠数据传输以减少运行时间

本质上,non_blocking=True允许异步数据传输以减少执行时间。

forfeatures,targetinloader:
#thesetwocallsarenonblockingandoverlapping
features=features.to('cuda:0',non_blocking=True)
target=target.to('cuda:0',non_blocking=True)

#Thisisasynchronizationpoint
#Itwillwaitforprevioustwolines
output=model(features)

8. 使用PyTorch JIT将点操作融合到单个kernel中

点操作包括常见的数学操作,通常是内存受限的。PyTorch JIT会自动将相邻的点操作融合到一个内核中,以保存多次内存读/写操作。例如,通过将5个核融合成1个核,gelu函数可以被加速4倍。

@torch.jit.script#JITdecorator
deffused_gelu(x):
returnx*0.5*(1.0+torch.erf(x/1.41421))

9 & 10. 在使用混合精度的FP16时,对于所有不同架构设计,设置图像尺寸和batch size为8的倍数

为了最大限度地提高GPU的计算效率,最好保证不同的架构设计(包括神经网络的输入输出尺寸/维数/通道数和batch size大小)是8的倍数甚至更大的2的幂(如64、128和最大256)。这是因为当矩阵的维数与2的幂倍数对齐时,Nvidia gpu的张量核心(Tensor Cores)在矩阵乘法方面可以获得最佳性能。矩阵乘法是最常用的操作,也可能是瓶颈,所以它是我们能确保张量/矩阵/向量的维数能被2的幂整除的最好方法(例如,8、64、128,最多256)。

这些实验显示设置输出维度和batch size大小为8的倍数,比如(33712、4088、4096)相比33708,batch size为4084或者4095这些不能被8整除的数可以加速计算1.3倍到 4倍。加速度大小取决于过程类型(例如,向前传递或梯度计算)和cuBLAS版本。特别是,如果你使用NLP,请记住检查输出维度,这通常是词汇表大小。

使用大于256的倍数不会增加更多的好处,但也没有害处。这些设置取决于cuBLAS和cuDNN版本以及GPU架构。你可以在文档中找到矩阵维数的特定张量核心要求。由于目前PyTorch AMP多使用FP16,而FP16需要8的倍数,所以通常推荐使用8的倍数。如果你有更高级的GPU,比如A100,那么你可以选择64的倍数。如果你使用的是AMD GPU,你可能需要检查AMD的文档。

除了将batch size大小设置为8的倍数外,我们还将batch size大小最大化,直到它达到GPU的内存限制。这样,我们可以用更少的时间来完成一个epoch。

11. 在前向中使用混合精度后向中不使用

有些操作不需要float64或float32的精度。因此,将操作设置为较低的精度可以节省内存和执行时间。对于各种应用,英伟达报告称具有Tensor Cores的GPU的混合精度可以提高3.5到25倍的速度。

值得注意的是,通常矩阵越大,混合精度加速度越高。在较大的神经网络中(例如BERT),实验表明混合精度可以加快2.75倍的训练,并减少37%的内存使用。具有Volta, Turing, Ampere或Hopper架构的较新的GPU设备(例如,T4, V100, RTX 2060, 2070, 2080, 2080 Ti, A100, RTX 3090, RTX 3080,和RTX 3070)可以从混合精度中受益更多,因为他们有Tensor Core架构,它相比CUDA cores有特殊的优化。

c752d270-f177-11ec-ba43-dac502259ad0.png

带有Tensor Core的NVIDIA架构支持不同的精度

值得一提的是,采用Hopper架构的H100预计将于2022年第三季度发布,支持FP8 (float8)。PyTorch AMP可能会支持FP8(目前v1.11.0还不支持FP8)。

在实践中,你需要在模型精度性能和速度性能之间找到一个最佳点。我之前确实发现混合精度可能会降低模型的精度,这取决于算法,数据和问题。

使用自动混合精度(AMP)很容易在PyTorch中利用混合精度。PyTorch中的默认浮点类型是float32。AMP将通过使用float16来进行一组操作(例如,matmul, linear, conv2d)来节省内存和时间。AMP会自动cast到float32的一些操作(例如,mse_loss, softmax等)。有些操作(例如add)可以操作最宽的输入类型。例如,如果一个变量是float32,另一个变量是float16,那么加法结果将是float32。

autocast自动应用精度到不同的操作。因为损失和梯度是按照float16精度计算的,当它们太小时,梯度可能会“下溢”并变成零。GradScaler通过将损失乘以一个比例因子来防止下溢,根据比例损失计算梯度,然后在优化器更新权重之前取消梯度的比例。如果缩放因子太大或太小,并导致infNaN,则缩放因子将在下一个迭代中更新缩放因子。

scaler=GradScaler()
forfeatures,targetindata:
#Forwardpasswithmixedprecision
withtorch.cuda.amp.autocast():#autocastasacontextmanager
output=model(features)
loss=criterion(output,target)

#Backwardpasswithoutmixedprecision
#It'snotrecommendedtousemixedprecisionforbackwardpass
#Becauseweneedmorepreciseloss
scaler.scale(loss).backward()

#scaler.step()firstunscalesthegradients.
#IfthesegradientscontaininfsorNaNs,
#optimizer.step()isskipped.
scaler.step(optimizer)

#Ifoptimizer.step()wasskipped,
#scalingfactorisreducedbythebackoff_factorinGradScaler()
scaler.update()

你也可以使用autocast 作为前向传递函数的装饰器。

classAutocastModel(nn.Module):
...
@autocast()#autocastasadecorator
defforward(self,input):
x=self.model(input)
returnx

12. 在优化器更新权重之前将梯度设置为None

通过model.zero_grad()optimizer.zero_grad()将对所有参数执行memset ,并通过读写操作更新梯度。但是,将梯度设置为None将不会执行memset,并且将使用“只写”操作更新梯度。因此,设置梯度为None更快。

#Resetgradientsbeforeeachstepofoptimizer
forparaminmodel.parameters():
param.grad=None

#or(PyTorch>=1.7)
model.zero_grad(set_to_none=True)

#or(PyTorch>=1.7)
optimizer.zero_grad(set_to_none=True)

13. 梯度累积:每隔x个batch再更新梯度,模拟大batch size

这个技巧是关于从更多的数据样本积累梯度,以便对梯度的估计更准确,权重更新更接近局部/全局最小值。这在batch size较小的情况下更有帮助(由于GPU内存限制较小或每个样本的数据量较大)。

fori,(features,target)inenumerate(dataloader):
#Forwardpass
output=model(features)
loss=criterion(output,target)

#Backwardpass
loss.backward()

#Onlyupdateweightseveryother2iterations
#Effectivebatchsizeisdoubled
if(i+1)%2==0or(i+1)==len(dataloader):
#Updateweights
optimizer.step()
#ResetthegradientstoNone
optimizer.zero_grad(set_to_none=True)

14. 在推理和验证的时候禁用梯度计算

实际上,如果只计算模型的输出,那么梯度计算对于推断和验证步骤并不是必需的。PyTorch使用一个中间内存缓冲区来处理requires_grad=True变量中涉及的操作。因此,如果我们知道不需要任何涉及梯度的操作,通过禁用梯度计算来进行推断/验证,就可以避免使用额外的资源。

#torch.no_grad()asacontextmanager:
withtorch.no_grad():
output=model(input)

#torch.no_grad()asafunctiondecorator:
@torch.no_grad()
defvalidation(model,input):
output=model(input)
returnoutput

15. torch.backends.cudnn.benchmark = True

在训练循环之前设置torch.backends.cudnn.benchmark = True可以加速计算。由于计算不同内核大小卷积的cuDNN算法的性能不同,自动调优器可以运行一个基准来找到最佳算法。当你的输入大小不经常改变时,建议开启这个设置。如果输入大小经常改变,那么自动调优器就需要太频繁地进行基准测试,这可能会损害性能。它可以将向前和向后传播速度提高1.27x到1.70x。

torch.backends.cudnn.benchmark=True

16. 对于4D NCHW Tensors使用通道在最后的内存格式

c75d0a6a-f177-11ec-ba43-dac502259ad0.png

4D NCHW重新组织成 NHWC格式

使用channels_last内存格式以逐像素的方式保存图像,作为内存中最密集的格式。原始4D NCHW张量在内存中按每个通道(红/绿/蓝)顺序存储。转换之后,x = x.to(memory_format=torch.channels_last),数据在内存中被重组为NHWC (channels_last格式)。你可以看到RGB层的每个像素更近了。据报道,这种NHWC格式与FP16的AMP一起使用可以获得8%到35%的加速。

目前,它仍处于beta测试阶段,仅支持4D NCHW张量和一组模型(例如,alexnetmnasnet家族,mobilenet_v2resnet家族,shufflenet_v2squeezenet1vgg家族)。但我可以肯定,这将成为一个标准的优化。

N,C,H,W=10,3,32,32

x=torch.rand(N,C,H,W)

#Strideisthegapbetweenoneelementtothenextone
#inadimension.
print(x.stride())

#(3072,1024,32,1)#ConvertthetensortoNHWCinmemory
x2=x.to(memory_format=torch.channels_last)

print(x2.shape)#(10,3,32,32)asdimensionsorderpreserved
print(x2.stride())#(3072,1,96,3),whicharesmaller
print((x==x2).all())#Truebecausethevalueswerenotchanged

17. 在batch normalization之前禁用卷积层的bias

这是可行的,因为在数学上,bias可以通过batch normalization的均值减法来抵消。我们可以节省模型参数、运行时的内存。

nn.Conv2d(...,bias=False)

18. 使用 DistributedDataParallel代替DataParallel

对于多GPU来说,即使只有单个节点,也总是优先使用 DistributedDataParallel而不是 DataParallel ,因为 DistributedDataParallel 应用于多进程,并为每个GPU创建一个进程,从而绕过Python全局解释器锁(GIL)并提高速度。

总结

在这篇文章中,我列出了一个清单,并提供了18个PyTorch技巧的代码片段。然后,我逐一解释了它们在不同方面的工作原理和原因,包括数据加载、数据操作、模型架构训练、推断、cnn特定的优化和分布式计算。一旦你深入理解了它们的工作原理,你可能会找到适用于任何深度学习框架中的深度学习建模的通用原则。

审核编辑 :李倩


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • cpu
    cpu
    +关注

    关注

    68

    文章

    11216

    浏览量

    222913
  • 代码
    +关注

    关注

    30

    文章

    4941

    浏览量

    73135
  • pytorch
    +关注

    关注

    2

    文章

    813

    浏览量

    14694

原文标题:优化PyTorch的速度和内存效率(2022)

文章出处:【微信号:CVSCHOOL,微信公众号:OpenCV学堂】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    薄膜电容的关键词是什么知道吗?

    薄膜电容是一种以金属箔作为电极,以聚乙酯、聚丙烯、聚苯乙烯等塑料薄膜作为电介质的电容器,在电子电路中具有重要作用。薄膜电容有哪些关键词知道吗?
    的头像 发表于 10-13 15:30 276次阅读
    薄膜电容的关键词是什么<b class='flag-5'>你</b><b class='flag-5'>知道</b>吗?

    知道板卡厂商参与芯片研发的α阶段意味着什么?

    大家都知道芯片很重要,但是否知道一颗芯片从设计构思到最终量产,需要经历怎样一漫长的过程吗?
    的头像 发表于 09-24 17:08 7260次阅读
    <b class='flag-5'>你</b><b class='flag-5'>知道</b>板卡厂商参与芯片研发的α阶段意味着什么?

    知道光耦的特性参数包括哪些吗?

    知道光耦的特性参数包括哪些吗? 一、输入特性参数 正向工作电压(Forward Voltage):在给定的工作电流下,LED本身的压降。 反向电压(Reverse Voltage):LED所能承受
    的头像 发表于 07-31 09:44 980次阅读
    <b class='flag-5'>你</b><b class='flag-5'>知道</b>光耦的特性参数包括哪些吗?

    Arm方案 基于Arm架构的边缘侧设备(树莓派或 NVIDIA Jetson Nano)上部署PyTorch模型

    本文将为展示如何在树莓派或 NVIDIA Jetson Nano 等基于 Arm 架构的边缘侧设备上部署 PyTorch 模型。
    的头像 发表于 07-28 11:50 2497次阅读

    已收藏!需要知道的57常用树莓派命令!

    初次使用树莓派并不总是那么容易,因为可能还没有使用命令行的习惯。然而,终端命令是必不可少的,而且通常比通过图形用户界面(GUI)操作更高效。那么,有哪些重要的命令是应该知道的呢?有
    的头像 发表于 07-23 18:36 810次阅读
    已收藏!<b class='flag-5'>你</b>需要<b class='flag-5'>知道</b>的57<b class='flag-5'>个</b>常用树莓派命令!

    知道船用变压器有哪些吗?

    在船舶和海洋平台上,电力系统的稳定运行至关重要,而船用变压器作为其中的关键设备,其种类繁多,各具特点。知道船用变压器有哪些吗?让我们一起来揭开它们的神秘面纱。CSD船用变压器是船舶供电系统中
    的头像 发表于 06-01 00:00 469次阅读
    <b class='flag-5'>你</b><b class='flag-5'>知道</b>船用变压器有哪些吗?

    FK10-18S18E2C3 FK10-18S18E2C3

    电子发烧友网为提供AIPULNION(AIPULNION)FK10-18S18E2C3相关产品参数、数据手册,更有FK10-18S18E2C3的引脚图、接线图、封装手册、中文资料、英文资料,FK10-
    发表于 03-20 18:49
    FK10-<b class='flag-5'>18S18</b>E2C3 FK10-<b class='flag-5'>18S18</b>E2C3

    PFD6-18D18E2(C)3 PFD6-18D18E2(C)3

    电子发烧友网为提供AIPULNION(AIPULNION)PFD6-18D18E2(C)3相关产品参数、数据手册,更有PFD6-18D18E2(C)3的引脚图、接线图、封装手册、中文资料、英文资料,PFD6-
    发表于 03-20 18:47
    PFD6-<b class='flag-5'>18D18</b>E2(C)3 PFD6-<b class='flag-5'>18D18</b>E2(C)3

    FK6-18D18E2C3 FK6-18D18E2C3

    电子发烧友网为提供AIPULNION(AIPULNION)FK6-18D18E2C3相关产品参数、数据手册,更有FK6-18D18E2C3的引脚图、接线图、封装手册、中文资料、英文资料,FK6-
    发表于 03-20 18:40
    FK6-<b class='flag-5'>18D18</b>E2C3 FK6-<b class='flag-5'>18D18</b>E2C3

    使用OpenVINO™ 2021.4将经过训练的自定义PyTorch模型加载为IR格式时遇到错误怎么解决?

    使用 OpenVINO™ 2021.4 将经过训练的自定义 PyTorch 模型加载为 IR 格式时遇到错误: RuntimeError: [ GENERAL_ERROR ] Failed
    发表于 03-05 08:40

    操作指南:pytorch云服务器怎么设置?

    设置PyTorch云服务器需选择云平台,创建合适的GPU实例,安装操作系统、Python及Anaconda,创建虚拟环境,根据CUDA版本安装PyTorch,配置环境变量,最后验证安装。过程中需考虑
    的头像 发表于 02-08 10:33 605次阅读

    ADS7883就一地,应该连数字地还是连模拟地?

    ADS7883就一地,应该连数字地还是连模拟地啊...困惑,我板上有数字地和模拟地,我怕模拟信号收干扰,不知道这个地连哪个好....,大神指点下吧
    发表于 01-15 06:01

    AD2S1203在输出的18位中应该怎样选取其中的16位输出呢?

    =64,则输出的数据N=18位,那么问题来了,在输出的18位中应该怎样选取其中的16位输出呢?如果M=128,则N=21位,那么在这21位中怎样选16位呢?
    发表于 01-08 08:15

    利用Arm Kleidi技术实现PyTorch优化

    PyTorch 是一广泛应用的开源机器学习 (ML) 库。近年来,Arm 与合作伙伴通力协作,持续改进 PyTorch 的推理性能。本文将详细介绍如何利用 Arm Kleidi 技术提升 Arm
    的头像 发表于 12-23 09:19 1617次阅读
    利用Arm Kleidi技术实现<b class='flag-5'>PyTorch</b>优化

    vLLM项目加入PyTorch生态系统,引领LLM推理新纪元

    近日,vLLM项目宣布正式成为PyTorch生态系统的一部分,标志着该项目与PyTorch的合作进入了一全新的阶段。本文将从以下几个方面进行介绍,特别提醒:安装方案在第四部分,可选
    的头像 发表于 12-18 17:06 1572次阅读
    vLLM项目加入<b class='flag-5'>PyTorch</b>生态系统,引领LLM推理新纪元