接上篇的遗留问题,“tensorrt的内部network的“自动构建”究竟是如何完成的?”
ConversionContext
第一篇中曾提到ctx的实例,这个实例是每一个converter的参数;下面分析下ConversionContext这个类的定义:
构造函数中的其中一个参数converters就是上篇提到过的字典。重点是self.hooks的定义,它本身又是由另一个ConversionHook,通过字典中的key, converter实例化的对象组成的列表。在去查看ConversionHook的定义之前,我们首先看一下ConversionContext的两个"hook"。
ConversionContext的__enter__通过调用每一个ConversionHook的__enter__,__exit__同理。(其实这里有个问题,一般__enter__是什么时候调用的,在这份代码里是在使用“with”时会通过python的hook机制自动调用,之后会再提到)
ConversionHook
ConversionContext的功能主要依赖于ConversionHook,看一下ConversionHook的定义:
ConversionHook的定义也很简单,先看__enter__()方法,是将attach_converter()方法作为参数传递给_set_method()。至于attach_converter方法本身大家自行查看,第三个参数self.converter,通过ConversionContext也可以得知即是字典里每个key对应的value(由(一)知这个value本身是一个字典);中间有一句话最为关键,
converter["converter"](ctx)
converter[“converter”]是形如conv2d_converter的converter单元,正是在此处逐步构建network的每个结构。attach_converter本身作为method传给_set_method(),再看一句:
exec('module.%s = method' % self.converter['qual_name'])
每当执行module.forward就相当于执行attach_converter。
举个例子,每当执行conv2d.forward就会相应地找到conv2d_converter执行。这就是pytorch的module与converter之间的“绑定”,也解释了为什么torch model只跑了一次前向,tensorrt的network也构建完成了。这里还有一个问题是method_args的参数是如何更新拿到的?因为这决定了网络参数的赋值。
除此之外,源码里还有非常多的零碎的方法没有谈到,这些我也没仔细看,或者也不太理解。此外,torch2trt还支持插件层的创建,有时间我大概再介绍一下。