[PT FE] Fix for prim::Constant optional or containing list of tensors (#16754)

* Fix Constant list of tensor

* Write TorchScript transformation

* Handle Optional Tensor Constants

* Improve tests

* Add comments

* Try fix flake
This commit is contained in:
Mateusz Mikolajczyk authored and GitHub committed 2023-04-24 22:56:42 +02:00
1 parent b452dab8f0
commit 8e5b0650a0
2 files changed
+137 -1

No files matched your search

@@ -109,6 +109,10 @@ class TorchScriptPythonDecoder (Decoder):
if self._input_signature is not None and self.raw_inputs[0].debugName() == "self":
self._input_signature.insert(0, "self")
if isinstance(self.graph_element, torch.Graph):
self._transform_tensor_list_constants_to_listconstruct(self.graph_element)
self._transform_optional_constants(self.graph_element)
def _get_scripted_model(self, pt_module, example_inputs=None, freeze=True):
import torch
import inspect
@@ -277,6 +281,7 @@ class TorchScriptPythonDecoder (Decoder):
return decoder
def get_op_type(self) -> str:
assert isinstance(self.graph_element, torch.Node), "Function can be called only when self.graph_element is of type torch.Node"
return self.graph_element.kind()
def get_schema(self) -> str:
@@ -309,10 +314,11 @@ class TorchScriptPythonDecoder (Decoder):
return []
def as_constant(self):
if not isinstance(self.graph_element, torch.Node):
return None
if not self.get_op_type() == "prim::Constant":
return None
pt_value = self._raw_output(0)
pt_type = pt_value.type()
if isinstance(pt_type, torch.TensorType):
return ivalue_to_constant(pt_value.toIValue())
@@ -369,3 +375,48 @@ class TorchScriptPythonDecoder (Decoder):
pt_value = get_value_from_getattr(in_node, self.pt_module)
return pt_value is None
return False
@staticmethod
def _transform_tensor_list_constants_to_listconstruct(graph: torch.Graph):
# Function replaces prim::Constant containing List of Tensors with
# prim::ListConstruct containing prim::Constant Tensors.
assert isinstance(graph, torch.Graph), "Function can be called only with parameters of type torch.Graph."
for node in graph.nodes():
if node.kind() != "prim::Constant":
continue
output_type = node.output().type()
allowed_types = [
output_type.isSubtypeOf(torch.ListType.ofTensors()),
output_type.isSubtypeOf(torch.ListType(torch.OptionalType.ofTensor())),
]
if not any(allowed_types):
continue
const_inputs = []
for val in node.output().toIValue():
const_input = graph.insertConstant(val)
const_input.node().moveBefore(node)
const_input.node().copyMetadata(node)
const_inputs.append(const_input)
replacement = graph.create("prim::ListConstruct", const_inputs)
replacement.insertBefore(node)
replacement.output().setType(torch.ListType.ofTensors())
replacement.copyMetadata(node)
node.output().replaceAllUsesWith(replacement.output())
@staticmethod
def _transform_optional_constants(graph: torch.Graph):
# Function replaces prim::Constant containing torch.OptionalType with
# prim::Constant containing torch.NoneType or type of IValue.
assert isinstance(graph, torch.Graph), "Function can be called only with parameters of type torch.Graph."
for node in graph.nodes():
if node.kind() != "prim::Constant":
continue
output_type = node.output().type()
if not isinstance(output_type, torch.OptionalType):
continue
value = node.output().toIValue()
const_input = graph.insertConstant(value)
const_input.node().moveBefore(node)
const_input.node().copyMetadata(node)
node.output().replaceAllUsesWith(const_input)