OnnxRuntime.InferenceSession 이용
build_onnxrt_session = SessionFromOnnx("identity.onnx")
backend/onnxrt/loader.py
: class SessionFromOnnx(BaseLoader)
@mod.export(*funcify*=True)
역할
인스턴스 초기화 및 호출을 한 번에 실행
**__init__
과 call_impl
한 번에 실행 ← provider setting 및 ort InferenceSession 반환**
IcudaEngine instance 추출
build_engine = EngineFromNetwork(NetworkFromOnnxPath("identity.onnx"))
cf. “내가 직접 customizing한 onnx to trt의 경우, serialized engine까지 뽑아냈지만, polygraphy의 경우, ICudaEngine 뽑아낸 후에, serialized해서 engine으로 저장하지 않는다.!”
TensorRT Engine을 구성하기 위한 객체 :
1번의 “INetworkDefinition”을 포함하여, “IBuilder”, “OnnxParser” 들을 대표적으로 생각해 볼 수 있다.
trt.Logger : logging을 어떻게 활용할 것 인지에 대한 객체, 직접 customizing도 가능
builder 객체를 생성할 때 담아줘서 사용함
TRT_LOGGER = trt.Logger(trt.Logger.WARNING)
builder = trt.Builder(TRT_LOGGER)
builder : immutable한 network properties
config : (=IbuilderConfig)
Int8로 quantizing 가능 여부 flag list 등등
optimize 된 profile을 config에 추가할 수 있음
cf. profile은 보통 input,ouptut shape에 대한 optimizing 정보를 담으려고 함
IOptimizationProfile - NVIDIA TensorRT Standard Python API Documentation 8.4.1 documentation
profile.set_shape("image", (1,3, 416, 416),(1,3, 416, 416),(1,3, 416, 416))
config = builder.create_builder_config()
config.add_optimization_profile(profile)
config.max_workspace_size = 8 << 30
network : network에 대한 정보들(==INetworkDefinition)
EXPLICIT_BATCH = 1 << (int)(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH)
network = builder.create_network(EXPLICIT_BATCH)
parser : Onnx 모델을 parsing 해주는 역할 (=trt.OnnxParser)
parser.parse(onnx모델) : parsing된 network definition을 network에 써줌
Onnx Parser - NVIDIA TensorRT Standard Python API Documentation 8.4.1 documentation
parser = trt.OnnxParser(network, TRT_LOGGER)
parser.parse(onnx모델)
IcudaEngine Instance :
ort_session.run(None, ort_inputs)
#customizing
ort_inputs = {ort_session.get_inputs()[0].name: to_numpy(x)}
ort_outs = ort_session.run(None, ort_inputs)
#[polygraphy]
for node in self.sess.get_inputs():
dtype = ONNX_RT_TYPE_TO_NP[node.type] if node.type in ONNX_RT_TYPE_TO_NP else None
meta.add(node.name, dtype=dtype, shape=node.shape)
return meta
def infer_impl(self, feed_dict):
start = time.time()
inference_outputs = self.sess.run(None, feed_dict)
end = time.time()
out_dict = OrderedDict()
for node, out in zip(self.sess.get_outputs(), inference_outputs):
out_dict[node.name] = out
self.inference_time = end - start
return out_dict
cuda stream 활용하여 async inference
self.context = self.engine.create_execution_context()
cuda.Stream() :
정의 - 호스트(CPU) 코드에서 기술된 순서대로 디바이스(GPU)에서 동작하는 일련의 연속된 연산을 의미
순차적 실행을 보장하지만, 다른 스트림의 연산과는 함께 동작이 가능
Inference 과정에서 context의 메서드인 execute_async_v2
를 활용하여 비동기적으로 추론을 여러 스트림에서 진행하기 위해 사용
추론을 위해서 호스트 버퍼와 디바이스 버퍼의 사이즈를 정해줘야 함. 이는 일반적으로 input shape 크기만큼 할당해주면 됨.
IExecutionContext - NVIDIA TensorRT Standard Python API Documentation 8.4.1 documentation