-
Notifications
You must be signed in to change notification settings - Fork 26.3k
Add memory format support to resize_as_ operator
#27979
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add memory format support to resize_as_ operator
#27979
Conversation
Adds memory_format keyword argument (positional for cpp). 'Preserve' behavior now follows next rules: 1) If tensor is non-overlapping and dense - output tensor will have the same strides as input tensor. 2) If not (1) and tensor is stored in the channels last format, output tensor going to have channels last format. 3) Output tensor is going to be contiguous in all other cases. --- Dense tensor is the tensor that store values in a contiguous block of memory. Non-overlapping tensor is the tensor in which elements occupy individual non-repetitive memory. [ghstack-poisoned]
Adds memory_format keyword argument (positional for cpp). 'Preserve' behavior now follows next rules: 1) If tensor is non-overlapping and dense - output tensor will have the same strides as input tensor. 2) If not (1) and tensor is stored in the channels last format, output tensor going to have channels last format. 3) Output tensor is going to be contiguous in all other cases. --- Dense tensor is the tensor that store values in a contiguous block of memory. Non-overlapping tensor is the tensor in which elements occupy individual non-repetitive memory. ghstack-source-id: e6b4b32 Pull Request resolved: #27979
… operator" Adds memory_format keyword argument (positional for cpp). 'Preserve' behavior now follows next rules: 1) If tensor is non-overlapping and dense - output tensor will have the same strides as input tensor. 2) If not (1) and tensor is stored in the channels last format, output tensor going to have channels last format. 3) Output tensor is going to be contiguous in all other cases. --- Dense tensor is the tensor that store values in a contiguous block of memory. Non-overlapping tensor is the tensor in which elements occupy individual non-repetitive memory. [ghstack-poisoned]
…_as_` operator" Adds memory_format keyword argument (positional for cpp). 'Preserve' behavior now follows next rules: 1) If tensor is non-overlapping and dense - output tensor will have the same strides as input tensor. 2) If not (1) and tensor is stored in the channels last format, output tensor going to have channels last format. 3) Output tensor is going to be contiguous in all other cases. --- Dense tensor is the tensor that store values in a contiguous block of memory. Non-overlapping tensor is the tensor in which elements occupy individual non-repetitive memory. [ghstack-poisoned]
…ator" Adds memory_format keyword argument (positional for cpp). 'Preserve' behavior now follows next rules: 1) If tensor is non-overlapping and dense - output tensor will have the same strides as input tensor. 2) If not (1) and tensor is stored in the channels last format, output tensor going to have channels last format. 3) Output tensor is going to be contiguous in all other cases. --- Dense tensor is the tensor that store values in a contiguous block of memory. Non-overlapping tensor is the tensor in which elements occupy individual non-repetitive memory. [ghstack-poisoned]
…ator" Adds memory_format keyword argument (positional for cpp). 'Preserve' behavior now follows next rules: 1) If tensor is non-overlapping and dense - output tensor will have the same strides as input tensor. 2) If not (1) and tensor is stored in the channels last format, output tensor going to have channels last format. 3) Output tensor is going to be contiguous in all other cases. --- Dense tensor is the tensor that store values in a contiguous block of memory. Non-overlapping tensor is the tensor in which elements occupy individual non-repetitive memory. Differential Revision: [D17980311](https://our.internmc.facebook.com/intern/diff/D17980311) [ghstack-poisoned]
Adds memory_format keyword argument (positional for cpp). 'Preserve' behavior now follows next rules: 1) If tensor is non-overlapping and dense - output tensor will have the same strides as input tensor. 2) If not (1) and tensor is stored in the channels last format, output tensor going to have channels last format. 3) Output tensor is going to be contiguous in all other cases. --- Dense tensor is the tensor that store values in a contiguous block of memory. Non-overlapping tensor is the tensor in which elements occupy individual non-repetitive memory. Differential Revision: [D17980311](https://our.internmc.facebook.com/intern/diff/D17980311) [ghstack-poisoned]
|
@ailzhang ideally I want to land this stack (up to this PR) Monday morning |
…ator" Adds memory_format keyword argument (positional for cpp). 'Preserve' behavior now follows next rules: 1) If tensor is non-overlapping and dense - output tensor will have the same strides as input tensor. 2) If not (1) and tensor is stored in the channels last format, output tensor going to have channels last format. 3) Output tensor is going to be contiguous in all other cases. --- Dense tensor is the tensor that store values in a contiguous block of memory. Non-overlapping tensor is the tensor in which elements occupy individual non-repetitive memory. Differential Revision: [D17980311](https://our.internmc.facebook.com/intern/diff/D17980311) [ghstack-poisoned]
…perator" Adds memory_format keyword argument (positional for cpp). 'Preserve' behavior now follows next rules: 1) If tensor is non-overlapping and dense - output tensor will have the same strides as input tensor. 2) If not (1) and tensor is stored in the channels last format, output tensor going to have channels last format. 3) Output tensor is going to be contiguous in all other cases. --- Dense tensor is the tensor that store values in a contiguous block of memory. Non-overlapping tensor is the tensor in which elements occupy individual non-repetitive memory. Differential Revision: [D17980311](https://our.internmc.facebook.com/intern/diff/D17980311) [ghstack-poisoned]
Adds memory_format keyword argument (positional for cpp). 'Preserve' behavior now follows next rules: 1) If tensor is non-overlapping and dense - output tensor will have the same strides as input tensor. 2) If not (1) and tensor is stored in the channels last format, output tensor going to have channels last format. 3) Output tensor is going to be contiguous in all other cases. --- Dense tensor is the tensor that store values in a contiguous block of memory. Non-overlapping tensor is the tensor in which elements occupy individual non-repetitive memory. Differential Revision: [D17980311](https://our.internmc.facebook.com/intern/diff/D17980311) [ghstack-poisoned]
…` operator" Adds memory_format keyword argument (positional for cpp). 'Preserve' behavior now follows next rules: 1) If tensor is non-overlapping and dense - output tensor will have the same strides as input tensor. 2) If not (1) and tensor is stored in the channels last format, output tensor going to have channels last format. 3) Output tensor is going to be contiguous in all other cases. --- Dense tensor is the tensor that store values in a contiguous block of memory. Non-overlapping tensor is the tensor in which elements occupy individual non-repetitive memory. Differential Revision: [D17980311](https://our.internmc.facebook.com/intern/diff/D17980311) [ghstack-poisoned]
Adds memory_format keyword argument (positional for cpp). 'Preserve' behavior now follows next rules: 1) If tensor is non-overlapping and dense - output tensor will have the same strides as input tensor. 2) If not (1) and tensor is stored in the channels last format, output tensor going to have channels last format. 3) Output tensor is going to be contiguous in all other cases. --- Dense tensor is the tensor that store values in a contiguous block of memory. Non-overlapping tensor is the tensor in which elements occupy individual non-repetitive memory. Differential Revision: [D17980311](https://our.internmc.facebook.com/intern/diff/D17980311) [ghstack-poisoned]
…perator" Rationale to add optional memory format to `resize_as_` and `resize_` operators is the fact that they are frequently used as inplace `empty_like` and `empty` operators inside of our code base. So having them to accept memory format similarly to `empty_like` and `empty` seems to be logical. We could also add two new operators, but it will be more confusing (taking into account that renaming existing operators in not an option). --- Adds memory_format keyword argument (positional for cpp). 'Preserve' behavior now follows next rules: 1) If tensor is non-overlapping and dense - output tensor will have the same strides as input tensor. 2) If not (1) and tensor is stored in the channels last format, output tensor going to have channels last format. 3) Output tensor is going to be contiguous in all other cases. --- Dense tensor is the tensor that store values in a contiguous block of memory. Non-overlapping tensor is the tensor in which elements occupy individual non-repetitive memory. Differential Revision: [D17980311](https://our.internmc.facebook.com/intern/diff/D17980311) [ghstack-poisoned]
Rationale to add optional memory format to `resize_as_` and `resize_` operators is the fact that they are frequently used as inplace `empty_like` and `empty` operators inside of our code base. So having them to accept memory format similarly to `empty_like` and `empty` seems to be logical. We could also add two new operators, but it will be more confusing (taking into account that renaming existing operators in not an option). --- Adds memory_format keyword argument (positional for cpp). 'Preserve' behavior now follows next rules: 1) If tensor is non-overlapping and dense - output tensor will have the same strides as input tensor. 2) If not (1) and tensor is stored in the channels last format, output tensor going to have channels last format. 3) Output tensor is going to be contiguous in all other cases. --- Dense tensor is the tensor that store values in a contiguous block of memory. Non-overlapping tensor is the tensor in which elements occupy individual non-repetitive memory. Differential Revision: [D17980311](https://our.internmc.facebook.com/intern/diff/D17980311) [ghstack-poisoned]
aten/src/ATen/native/Resize.cpp
Outdated
| TORCH_CHECK( | ||
| !optional_memory_format.has_value(), | ||
| "Unsupported memory format for sparse tensor resize_as_ :", | ||
| optional_memory_format.value_or(MemoryFormat::Contiguous)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can't you use optional_memory_format.value() or *optional_memory_format, because you know it has a value?
aten/src/ATen/native/Resize.cpp
Outdated
| if (memory_format == MemoryFormat::Preserve) { | ||
| memory_format = the_template.suggest_memory_format(); | ||
| } | ||
| self.unsafeGetTensorImpl()->empty_tensor_restride(memory_format); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doesn't this change the behavior, even in cases where there's no channel_last tensors? i.e. non_contig.resize_as_(contig.shape) will make a tensor contiguous when it didn't previously.
Is that what you want?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally line 38 above Tensor& result = self.resize_(the_template.sizes()); was already setting up strides to contiguous.
But thank to this comment I found the only case when it is not intended and might be BC breaking:
x = torch.empty(2,3).t()
x.resize_as_(x)
# x.is_contiguous() == True but supposed to keep original strides.Gonna fix it now and test cover (we had no such test).
…_as_` operator" Rationale to add optional memory format to `resize_as_` and `resize_` operators is the fact that they are frequently used as inplace `empty_like` and `empty` operators inside of our code base. So having them to accept memory format similarly to `empty_like` and `empty` seems to be logical. We could also add two new operators, but it will be more confusing (taking into account that renaming existing operators in not an option). --- Adds memory_format keyword argument (positional for cpp). 'Preserve' behavior now follows next rules: 1) If tensor is non-overlapping and dense - output tensor will have the same strides as input tensor. 2) If not (1) and tensor is stored in the channels last format, output tensor going to have channels last format. 3) Output tensor is going to be contiguous in all other cases. --- Dense tensor is the tensor that store values in a contiguous block of memory. Non-overlapping tensor is the tensor in which elements occupy individual non-repetitive memory. Differential Revision: [D17980311](https://our.internmc.facebook.com/intern/diff/D17980311) [ghstack-poisoned]
Rationale to add optional memory format to `resize_as_` and `resize_` operators is the fact that they are frequently used as inplace `empty_like` and `empty` operators inside of our code base. So having them to accept memory format similarly to `empty_like` and `empty` seems to be logical. We could also add two new operators, but it will be more confusing (taking into account that renaming existing operators in not an option). --- Adds memory_format keyword argument (positional for cpp). 'Preserve' behavior now follows next rules: 1) If tensor is non-overlapping and dense - output tensor will have the same strides as input tensor. 2) If not (1) and tensor is stored in the channels last format, output tensor going to have channels last format. 3) Output tensor is going to be contiguous in all other cases. --- Dense tensor is the tensor that store values in a contiguous block of memory. Non-overlapping tensor is the tensor in which elements occupy individual non-repetitive memory. Differential Revision: [D17980311](https://our.internmc.facebook.com/intern/diff/D17980311) [ghstack-poisoned]
gchanan
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the behavior looks correct but this badly needs documentation.
…rator" Rationale to add optional memory format to `resize_as_` and `resize_` operators is the fact that they are frequently used as inplace `empty_like` and `empty` operators inside of our code base. So having them to accept memory format similarly to `empty_like` and `empty` seems to be logical. We could also add two new operators, but it will be more confusing (taking into account that renaming existing operators in not an option). --- Adds memory_format keyword argument (positional for cpp). 'Preserve' behavior now follows next rules: 1) If tensor is non-overlapping and dense - output tensor will have the same strides as input tensor. 2) If not (1) and tensor is stored in the channels last format, output tensor going to have channels last format. 3) Output tensor is going to be contiguous in all other cases. --- Dense tensor is the tensor that store values in a contiguous block of memory. Non-overlapping tensor is the tensor in which elements occupy individual non-repetitive memory. Differential Revision: [D17980311](https://our.internmc.facebook.com/intern/diff/D17980311) [ghstack-poisoned]
|
Docs added |
aten/src/ATen/native/Resize.cpp
Outdated
| // Strides of the output tensor of `resize_as_` operator is defined by input | ||
| // tensor strides and the value of memory_format argument. | ||
| // | ||
| // If memory_format is not defined or equals to MemoryFormat::Contiguous |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is correct.
Don't we not restride if memory_format is not set and the sizes match?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
…rator" Rationale to add optional memory format to `resize_as_` and `resize_` operators is the fact that they are frequently used as inplace `empty_like` and `empty` operators inside of our code base. So having them to accept memory format similarly to `empty_like` and `empty` seems to be logical. We could also add two new operators, but it will be more confusing (taking into account that renaming existing operators in not an option). --- Adds memory_format keyword argument (positional for cpp). 'Preserve' behavior now follows next rules: 1) If tensor is non-overlapping and dense - output tensor will have the same strides as input tensor. 2) If not (1) and tensor is stored in the channels last format, output tensor going to have channels last format. 3) Output tensor is going to be contiguous in all other cases. --- Dense tensor is the tensor that store values in a contiguous block of memory. Non-overlapping tensor is the tensor in which elements occupy individual non-repetitive memory. Differential Revision: [D17980311](https://our.internmc.facebook.com/intern/diff/D17980311) [ghstack-poisoned]
…rator" Rationale to add optional memory format to `resize_as_` and `resize_` operators is the fact that they are frequently used as inplace `empty_like` and `empty` operators inside of our code base. So having them to accept memory format similarly to `empty_like` and `empty` seems to be logical. We could also add two new operators, but it will be more confusing (taking into account that renaming existing operators in not an option). --- Adds memory_format keyword argument (positional for cpp). 'Preserve' behavior now follows next rules: 1) If tensor is non-overlapping and dense - output tensor will have the same strides as input tensor. 2) If not (1) and tensor is stored in the channels last format, output tensor going to have channels last format. 3) Output tensor is going to be contiguous in all other cases. --- Dense tensor is the tensor that store values in a contiguous block of memory. Non-overlapping tensor is the tensor in which elements occupy individual non-repetitive memory. Differential Revision: [D17980311](https://our.internmc.facebook.com/intern/diff/D17980311) [ghstack-poisoned]
| // tensor strides and the value of memory_format argument. | ||
| // | ||
| // If memory_format is omitted and input tensor have the same shape as output | ||
| // tensor, strides of the output will remain unchanged. Strides going to be |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: strides are going to be...
| x.resize_as_(x) | ||
| self.assertEqual(x.stride(), old_strides) | ||
|
|
||
| def test_memory_format_resize_as(self, device): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should have tests for all the cases, i.e. add a:
- explicit contiguous test
- explicit channels_last test.
|
@VitalyFedyunin merged this pull request in 9f3b347. |
Summary: Pull Request resolved: pytorch/pytorch#27979 Adds memory_format keyword argument (positional for cpp). 'Preserve' behavior now follows next rules: 1) If tensor is non-overlapping and dense - output tensor will have the same strides as input tensor. 2) If not (1) and tensor is stored in the channels last format, output tensor going to have channels last format. 3) Output tensor is going to be contiguous in all other cases. --- Dense tensor is the tensor that store values in a contiguous block of memory. Non-overlapping tensor is the tensor in which elements occupy individual non-repetitive memory. Test Plan: Imported from OSS Differential Revision: D17980311 Pulled By: VitalyFedyunin fbshipit-source-id: 12d013521091fcc9c045833577f6dc78d7b1e68f
Rationale to add optional memory format to
resize_as_andresize_operators is the fact that they are frequently used as inplaceempty_likeandemptyoperators inside of our code base. So having them to accept memory format similarly toempty_likeandemptyseems to be logical.We could also add two new operators, but it will be more confusing (taking into account that renaming existing operators in not an option).
Stack from ghstack:
resize_op. #28292 Add memory format support to theresize_op.operator==of TensorOptions as confusing one #28076 Killoperator==of TensorOptions as confusing oneresize_as_operator #27979 Add memory format support toresize_as_operatorAdds memory_format keyword argument (positional for cpp).
'Preserve' behavior now follows next rules:
Dense tensor is the tensor that store values in a contiguous block of memory.
Non-overlapping tensor is the tensor in which elements occupy individual non-repetitive memory.
Differential Revision: D17980311