diff --git a/onnxruntime/core/framework/allocation_planner.cc b/onnxruntime/core/framework/allocation_planner.cc index 257db07fd8..4f6f21ba45 100644 --- a/onnxruntime/core/framework/allocation_planner.cc +++ b/onnxruntime/core/framework/allocation_planner.cc @@ -257,6 +257,20 @@ class PlannerImpl { // Find if there exists some input tensor that we can use in-place for output_arg_num-th input in the node. bool FindReusableInput(const onnxruntime::Node& node, int output_arg_num, OrtValueIndex* reusable_input) { +#ifdef ENABLE_TRAINING + // Inputs of Yields are essentially the outputs for FW partial subgraph + // Thses tensors will be pass back to pytorch, thus cannot share the buffer with other tensors + + // Unhandled corner case: + // If FW output tensor is consumed by BW graph, and pytorch performs an inplace operation on th returned tensor, + // we will run into a buffer corruption problem. + // One potential fix is returning a copy of output tensor, if it has downstream dependency + auto p_next_node = node.OutputNodesBegin(); + if (p_next_node != node.OutputNodesEnd() && p_next_node->OpType() == "YieldOp") { + return false; + } +#endif //ENABLE_TRAINING + auto p_output_arg = node.OutputDefs()[output_arg_num]; const KernelCreateInfo& ci = GetKernelCreateInfo(kernel_create_info_map_, node.Index()); diff --git a/orttraining/orttraining/test/python/orttraining_test_ortmodule_api.py b/orttraining/orttraining/test/python/orttraining_test_ortmodule_api.py index 20963c38b9..8ebb9c1c61 100644 --- a/orttraining/orttraining/test/python/orttraining_test_ortmodule_api.py +++ b/orttraining/orttraining/test/python/orttraining_test_ortmodule_api.py @@ -46,6 +46,8 @@ class NeuralNetMultiplePositionalArgumentsMultiOutputsWithoutDependency(torch.nn self.fc2 = torch.nn.Linear(input_size, hidden_size) self.softmax1 = torch.nn.Softmax(dim=1) self.softmax2 = torch.nn.Softmax(dim=1) + self.relu1 = torch.nn.ReLU() + self.relu2 = torch.nn.ReLU() def forward(self, input1, input2): model_input = input1 + input2 @@ -53,11 +55,8 @@ class NeuralNetMultiplePositionalArgumentsMultiOutputsWithoutDependency(torch.nn out2 = self.fc2(model_input) out1 = self.softmax1(out1) out2 = self.softmax2(out2) - # TODO: Using relu here will cause the forward prediction error - # ORT's Relu output is sharing the same buffer as input, - # and this buffer is returned as ORTModule's output to Pytorch - # out1 = self.relu1(out1) - # out2 = self.relu2(out2) + out1 = self.relu1(out1) + out2 = self.relu2(out2) return out1, out2 class NeuralNetMultiplePositionalArgumentsMultiOutputsWithDependency(torch.nn.Module): @@ -593,7 +592,7 @@ def test_gradient_correctness_conv1d(use_fp16, input_requires_grad): if use_fp16: _test_helpers.assert_values_are_close(ort_prediction, pt_prediction, atol=1e-3, rtol=1e-3) - _test_helpers.assert_gradients_match_and_reset_gradient(ort_model, pt_model, rtol=1e-2, atol=1e-2) + _test_helpers.assert_gradients_match_and_reset_gradient(ort_model, pt_model, rtol=1e-2, atol=1.1e-2) else: _test_helpers.assert_values_are_close(ort_prediction, pt_prediction, atol=1e-5) _test_helpers.assert_gradients_match_and_reset_gradient(ort_model, pt_model, rtol=5e-3, atol=4e-3)