降低阶段¶
降低阶段由多个pass组成,这些pass是将图从高级表示映射到低级表示的操作。每个pass都执行特定的操作,例如内联方法调用。其目的是在实际上映射到TensorRT时,显著减少转换阶段需要处理的内容。我们的目标是更接近1->1的操作转换,而不是寻找适用的子图,限制转换器的数量,并减少每个转换器的范围。
您可以通过将日志级别设置为Level::kGraph来查看每次传递的效果
使用的通行证¶
消除公共子表达式¶
移除图中的常见子表达式
消除死代码¶
死代码消除将检查节点是否有副作用,如果有则不删除它。
消除异常或传递模式¶
脚本模块中的一个常见模式是维度保护,如果输入维度不符合预期,将会抛出异常。
%1013 : bool = aten::ne(%1012, %24) # ~/.local/lib/python3.6/site-packages/torch/nn/modules/batchnorm.py:248:11
= prim::If(%1013) # ~/.local/lib/python3.6/site-packages/torch/nn/modules/batchnorm.py:248:8
block0():
= prim::RaiseException(%23) # ~/.local/lib/python3.6/site-packages/torch/nn/modules/batchnorm.py:249:12
-> ()
block1():
-> ()
由于我们在编译时解决了所有这些问题,并且TensorRT图中没有异常,我们只需将其移除。
消除冗余守卫¶
消除那些输出完全由其输入决定的操作的冗余保护,即如果这些操作的输入受到保护,我们可以移除操作输出的保护。
冻结模块¶
冻结属性和内联常量和模块。在图中传播常量。
融合AddMM分支¶
在脚本模块中,一个常见的模式是不同维度的张量使用不同的构造来实现线性层。我们将这些不同的变体融合成一个单一的变体,该变体将被Unpack AddMM过程捕获。
%ret : Tensor = prim::If(%622)
block0():
%ret.1 : Tensor = aten::addmm(%self.fc.bias, %x9.1, %3677, %3, %3)
-> (%ret.1)
block1():
%output.1 : Tensor = aten::matmul(%x9.1, %3677)
%output0.1 : Tensor = aten::add_(%output.1, %self.fc.bias, %3)
-> (%output0.1)
我们将这组块融合成一个像这样的图:
%ret : Tensor = aten::addmm(%self.fc.bias, %x9.1, %3677, %3, %3)
Fuse Linear¶
匹配aten::linear模式并将其融合为单个aten::linear
此过程将JIT生成的addmm或matmul + add融合回线性
Fuse Flatten Linear¶
当输入层的维度高于1D时,TensorRT会隐式地将输入层展平为全连接层。因此,当存在aten::flatten -> aten::linear模式时,我们会移除aten::flatten。
下图表¶
给定一个方法的图,其中第一个参数是%self,将其降低为一个图,其中所有属性访问都被替换为图的显式输入(而不是在%self上执行的prim::GetAttr的结果)。返回一个元组(图,参数),其中图的最后module.parameters.size()输入是此方法中使用的可训练参数。其余输入是函数的真实输入。
下界元组¶
LowerSimpleTuples:
移除匹配的TupleConstruct和TupleUnpack的元组,但在if语句、循环以及作为输入/输出时保留元组的位置
LowerAllTuples:
移除所有元组,如果某些元组无法移除则抛出错误,ONNX使用此方法来确保在转换之前没有元组,但对于输入包含元组的图将不起作用。
模块回退¶
模块回退由两个必须成对运行的降级过程组成。第一个过程在冻结之前运行,以在图中放置分隔符,标记应在PyTorch中运行的模块。第二个过程在冻结后标记这些分隔符之间的节点,以表示它们应在PyTorch中运行。
NotateModuleForFallback
在模块调用前冻结时,围绕模块调用的分隔节点,以指示在PyTorch中图形节点应在何处运行
MarkNodesForFallback
查找分隔符,然后标记分隔符之间的所有节点,以告诉分区在PyTorch中运行它们
窥孔优化¶
此优化过程的目的是捕捉所有您可能感兴趣的小型、易于捕捉的窥孔优化。
- Right now, it does:
消除无操作的‘expand’节点
只需将 x.t().t() 转换为 x
移除连续¶
移除连续运算符,因为我们正在使用TensorRT,内存已经是连续的。
移除Dropout¶
移除dropout操作符,因为我们正在进行推理。
移除到¶
移除aten::to操作符,这些操作符用于类型转换,因为TensorRT会自行管理。重要的是,这是最后运行的几个步骤之一,以便其他步骤有机会将所需的类型转换操作符移出主命名空间。
解包 AddMM¶
将aten::addmm解包为aten::matmul和aten::add_(并添加一个trt::const操作以在TensorRT图中冻结偏置)。这使我们能够重用aten::matmul和aten::add_转换器,而不需要专门的转换器。
解包LogSoftmax¶
将aten::logsoftmax解包为aten::softmax和aten::log。这使我们能够重用aten::softmax和aten::log转换器,而不需要专门的转换器。
展开循环¶
展开兼容循环的操作(例如足够短的循环),以便您只需遍历循环一次。
用重复替换瓷砖¶
移除dropout操作符,因为我们正在进行推理。