GitOrigin-RevId: 7461de704e
tags/v1.7.2.m1
@@ -153,6 +153,65 @@ void TensorRTOpr::GpuAllocator::free(void* memory) { | |||
} | |||
/* ========================== TensorRTManager ========================== */ | |||
const intl::TensorRTUniquePtr<nvinfer1::IExecutionContext>& TensorRTManager:: | |||
create_trt_context( | |||
const TensorShapeArray& inp_shape, nvinfer1::ICudaEngine* engine) { | |||
if (!m_context) { | |||
m_context = {engine->createExecutionContextWithoutDeviceMemory(), {}}; | |||
#if NV_TENSOR_RT_VERSION >= 6001 | |||
for (size_t i = 0; i < inp_shape.size(); ++i) { | |||
auto dims = m_context->getBindingDimensions(i); | |||
for (int j = 0; j < dims.nbDims; j++) { | |||
if (dims.d[j] == -1) { | |||
dims.d[j] = inp_shape.at(i)[j]; | |||
} | |||
} | |||
m_context->setBindingDimensions(i, dims); | |||
} | |||
// check if input shape is set correctly | |||
for (int i = inp_shape.size(); i < engine->getNbBindings(); ++i) { | |||
auto dims = m_context->getBindingDimensions(i); | |||
if (dims.nbDims == -1) { | |||
for (int j = 0; j < engine->getNbOptimizationProfiles(); j++) { | |||
mgb_log_debug("TensorRT profile %d:\n", j); | |||
for (size_t k = 0; k < inp_shape.size(); k++) { | |||
mgb_log_debug( | |||
"input[%zu]'s minimum shape is: %s\n", k, | |||
TensorRTOpr::dims2shape( | |||
engine->getProfileDimensions( | |||
j, k, | |||
nvinfer1::OptProfileSelector::kMIN)) | |||
.to_string() | |||
.c_str()); | |||
mgb_log_debug( | |||
"input[%zu]'s optimum shape is: %s\n", k, | |||
TensorRTOpr::dims2shape( | |||
engine->getProfileDimensions( | |||
j, k, | |||
nvinfer1::OptProfileSelector::kOPT)) | |||
.to_string() | |||
.c_str()); | |||
mgb_log_debug( | |||
"input[%zu]'s maximum shape is: %s\n", k, | |||
TensorRTOpr::dims2shape( | |||
engine->getProfileDimensions( | |||
j, k, | |||
nvinfer1::OptProfileSelector::kMAX)) | |||
.to_string() | |||
.c_str()); | |||
} | |||
} | |||
mgb_throw( | |||
MegBrainError, | |||
"Invalid network output, this might be caused by inconsistent " | |||
"input shapes.Correct input optimization profiles as above."); | |||
} | |||
} | |||
#endif | |||
} | |||
return m_context; | |||
} | |||
void TensorRTManager::exec( | |||
cg::SingleCNOperatorNodeBase* opr, CompNode comp_node_check, | |||
nvinfer1::ICudaEngine* engine, size_t batch, bool use_trt_profiler) { | |||
@@ -169,9 +228,11 @@ void TensorRTManager::exec( | |||
auto workspace_ptr = opr->output().back()->dev_tensor().raw_ptr(); | |||
bool should_reinit_device_memory = | |||
!m_context || m_device_workspace_memory_ptr != workspace_ptr; | |||
if (!m_context) { | |||
m_context = {engine->createExecutionContextWithoutDeviceMemory(), {}}; | |||
TensorShapeArray arr; | |||
for (auto&& i : opr->input()) { | |||
arr.push_back(i->shape()); | |||
} | |||
create_trt_context(arr, engine); | |||
m_trt_iobuf.resize(opr->input().size() + opr->output().size() - 1); | |||
bool is_trt_opr = false; | |||
if (opr->same_type<TensorRTOpr>()) { | |||
@@ -101,7 +101,8 @@ TensorRTRuntimeOpr::TensorRTRuntimeOpr( | |||
void TensorRTRuntimeOpr::get_output_var_shape( | |||
const TensorShapeArray& inp_shape, TensorShapeArray& out_shape) const { | |||
auto batch = inp_shape.at(0)[0]; | |||
auto get_mgb_shape = [this, batch](int binding_idx) -> TensorShape { | |||
auto&& context = m_manager.create_trt_context(inp_shape, m_engine.get()); | |||
auto get_mgb_shape = [&](int binding_idx) -> TensorShape { | |||
auto dims = m_engine->getBindingDimensions(binding_idx); | |||
#if NV_TENSOR_RT_VERSION >= 6001 | |||
auto format = m_engine->getBindingFormat(binding_idx); | |||
@@ -121,8 +122,25 @@ void TensorRTRuntimeOpr::get_output_var_shape( | |||
dims.d[dims.nbDims - 1] = 4; | |||
} | |||
#endif | |||
return m_trt_engine_has_batch ? TensorRTOpr::dims2shape(dims) | |||
: TensorRTOpr::dims2shape(dims, batch); | |||
auto shape = m_trt_engine_has_batch ? TensorRTOpr::dims2shape(dims) | |||
: TensorRTOpr::dims2shape(dims, batch); | |||
#if NV_TENSOR_RT_VERSION >= 6001 | |||
if (static_cast<size_t>(binding_idx) < inp_shape.size()) { | |||
for (int i = 0; i < dims.nbDims; i++) { | |||
if (dims.d[i] == -1) { | |||
shape[i] = inp_shape.at(binding_idx)[i]; | |||
} | |||
} | |||
} else { | |||
auto trt_infer_dims = context->getBindingDimensions(binding_idx); | |||
for (int i = 0; i < dims.nbDims; i++) { | |||
if (dims.d[i] == -1) { | |||
shape[i] = trt_infer_dims.d[i]; | |||
} | |||
} | |||
} | |||
#endif | |||
return shape; | |||
}; | |||
for (size_t i = 0; i < inp_shape.size(); ++i) { | |||
mgb_assert(batch == inp_shape[i][0], "input batchsize not equal"); | |||
@@ -135,6 +153,8 @@ void TensorRTRuntimeOpr::get_output_var_shape( | |||
out_shape[i] = get_mgb_shape(i + input().size()); | |||
} | |||
out_shape.back() = {intl::workspace_size(m_engine.get())}; | |||
// must clear context, otherwise it may cause unknwon error. | |||
m_manager.clear_trt_context(); | |||
} | |||
void TensorRTRuntimeOpr::add_input_layout_constraint() { | |||
@@ -52,6 +52,8 @@ class TensorRTManager { | |||
void* m_device_workspace_memory_ptr; | |||
public: | |||
const TensorRTUniquePtr<nvinfer1::IExecutionContext>& create_trt_context( | |||
const TensorShapeArray& inp_shape, nvinfer1::ICudaEngine* engine); | |||
void exec( | |||
cg::SingleCNOperatorNodeBase* opr, CompNode comp_node_check, | |||
nvinfer1::ICudaEngine* engine, size_t batch = 1, | |||
@@ -86,7 +86,7 @@ private: | |||
// note: gpu allocator must be released after other trt objects | |||
std::shared_ptr<TensorRTOpr::GpuAllocator> m_gpu_allocator; | |||
std::shared_ptr<nvinfer1::ICudaEngine> m_engine; | |||
intl::TensorRTManager m_manager; | |||
mutable intl::TensorRTManager m_manager; | |||
// if m_engine's dims with batch | |||
bool m_trt_engine_has_batch; | |||
}; // namespace mgb | |||