使用场景及原理
一个op能否运行在BPU上取决于两个条件:
1.该op是否可被BPU支持
2.能否找到该op的量化阈值
对于部分非计算密集op,其量化阈值依赖于上下游op的featuremap Tensor,因此若您在模型首尾处使用了非计算密集op(concat,reshape等),且为了追求极致性能想让该op运行在bpu上,则可通过在该算子前/后插入unitconv,通过unitconv的featuremap Tensor引入新的量化阈值统计,可以保证unticonv的上下游op找到量化阈值,进而可以将其量化在BPU上。
由于硬件特性,地平线工具链支持模型尾部的conv计算以int32高精度输出,若为其他算子(concat,reshape等),则只能以int8输出,同时会导致其前面的conv无法高精度输出,因此使用unit_conv量化非计算密集op有可能会对模型精度产生影响,若确认会导致精度降低,则建议您将concat等算子从模型中摘除,合入到前后处理中完成。
使用方式
在模型中插入unit_conv可参考如下代码:
class unit_conv(nn.Module):
def __init__(self):
super(unit_conv,self).__init__()
··· ···
self.cat = torch.cat
# in_channels = out_channels = 前一个节点输出tensor的channle
self.unitconv = torch.nn.Conv2d(8,8,1,1,groups=8,bias=False)
# 初始化 unit_conv 权重,确保unit_conv输入输出相等。该节点仅在部署时插入即可
torch.nn.init.dirac_(self.unitconv.weight.data,groups=8)
def forward(self, x):
··· ···
out = self.cat((a,b),axis=1)
out = self.unitconv(out)
return out
def __init__(self):
super(unit_conv,self).__init__()
··· ···
self.cat = torch.cat
# in_channels = out_channels = 前一个节点输出tensor的channle
self.unitconv = torch.nn.Conv2d(8,8,1,1,groups=8,bias=False)
# 初始化 unit_conv 权重,确保unit_conv输入输出相等。该节点仅在部署时插入即可
torch.nn.init.dirac_(self.unitconv.weight.data,groups=8)
def forward(self, x):
··· ···
out = self.cat((a,b),axis=1)
out = self.unitconv(out)
return out
原始模型:

插入unit_conv后:


