Skip to content

Commit

Permalink
[BYOC][TensorRT] Make TRT runtime robust to empty or weird subgraphs (a…
Browse files Browse the repository at this point in the history
…pache#7581)

* Prevent TRT runtime crash for duplicate inputs and outputs

* Add empty subgraph unit test
  • Loading branch information
Trevor Morris committed May 6, 2021
1 parent 30a67a2 commit 76c7f3c
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 7 deletions.
8 changes: 8 additions & 0 deletions src/runtime/contrib/tensorrt/tensorrt_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,14 @@ void TensorRTBuilder::AddOutput(const JSONGraphNodeEntry& node, uint32_t entry_i
ICHECK(it != node_output_map_.end()) << "Output was not found.";
auto out_tensor = it->second[node.index_].tensor;
std::string name = "tensorrt_output_" + std::to_string(network_output_names_.size());
// If the network is already marked as an input or output, make a copy to avoid TRT crash.
if (out_tensor->isNetworkOutput()) {
LOG(WARNING) << name << " is a duplicate output.";
out_tensor = network_->addIdentity(*out_tensor)->getOutput(0);
} else if (out_tensor->isNetworkInput()) {
LOG(WARNING) << name << " is both an input and an output.";
out_tensor = network_->addIdentity(*out_tensor)->getOutput(0);
}
out_tensor->setName(name.c_str());
network_->markOutput(*out_tensor);
network_output_names_.push_back(name);
Expand Down
42 changes: 35 additions & 7 deletions tests/python/contrib/test_tensorrt.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ def assert_result_dict_holds(result_dict):
tvm.testing.assert_allclose(r1, r2, rtol=1e-3, atol=1e-3)


def set_func_attr(func, compile_name, symbol_name):
func = func.with_attr("Primitive", tvm.tir.IntImm("int32", 1))
func = func.with_attr("Inline", tvm.tir.IntImm("int32", 1))
func = func.with_attr("Compiler", compile_name)
func = func.with_attr("global_symbol", symbol_name)
return func


def run_and_verify_func(config, target="cuda"):
"""Test a Relay func by compiling, running, and comparing TVM and TRT outputs.
Expand Down Expand Up @@ -1109,13 +1117,6 @@ def test_dynamic_offload():
kernel = relay.var("kernel", shape=(k_shape), dtype="float32")

def get_expected():
def set_func_attr(func, compile_name, symbol_name):
func = func.with_attr("Primitive", tvm.tir.IntImm("int32", 1))
func = func.with_attr("Inline", tvm.tir.IntImm("int32", 1))
func = func.with_attr("Compiler", compile_name)
func = func.with_attr("global_symbol", symbol_name)
return func

# Create a nested TRT function that matches the expected output
mod = tvm.IRModule()
var1 = relay.var("tensorrt_0_i0", shape=(data_shape), dtype="float32")
Expand Down Expand Up @@ -1331,5 +1332,32 @@ def get_maskrcnn_input(in_size: int) -> np.ndarray:
)


def test_empty_subgraph():
if skip_codegen_test():
return
x_shape = (1, 3, 5)
mod = tvm.IRModule()
# Empty tensorrt subgraph.
var1 = relay.var("tensorrt_0_i0", shape=(x_shape), dtype="float32")
f1 = GlobalVar("tensorrt_0")
func = relay.Function([var1], var1)
func = set_func_attr(func, "tensorrt", "tensorrt_0")
mod[f1] = func
mod = relay.transform.InferType()(mod)

# Create the main function
x = relay.var("x", shape=x_shape, dtype="float32")
out = f1(relay.nn.relu(x))
f = relay.Function([x], out)
mod["main"] = f

x_data = np.random.uniform(-1, 1, x_shape).astype("float32")
for mode in ["graph", "vm"]:
with tvm.transform.PassContext(opt_level=3):
exec = relay.create_executor(mode, mod=mod, ctx=tvm.gpu(0), target="cuda")
if not skip_runtime_test():
results = exec.evaluate()(x_data)


if __name__ == "__main__":
pytest.main([__file__])

0 comments on commit 76c7f3c

Please sign in to comment.