Add memory_format support to and type operators#27107
Add memory_format support to and type operators#27107VitalyFedyunin wants to merge 11 commits intogh/VitalyFedyunin/2/basefrom
to and type operators#27107Conversation
[ghstack-poisoned]
[ghstack-poisoned]
[ghstack-poisoned]
[ghstack-poisoned]
[ghstack-poisoned]
to and type operatorsto and type operators
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-poisoned]
Define what it means to be in 'channels last' format? :) |
aten/src/ATen/core/TensorBody.h
Outdated
| Tensor to(Device device, ScalarType dtype, bool non_blocking=false, bool copy=false) const; | ||
| Tensor to(ScalarType dtype, bool non_blocking=false, bool copy=false) const; | ||
| Tensor to(const Tensor & other, bool non_blocking=false, bool copy=false) const; | ||
| Tensor to(const TensorOptions & options, bool non_blocking=false, bool copy=false, c10::optional<MemoryFormat> memory_format=c10::nullopt) const; |
There was a problem hiding this comment.
I told you this before, and I'm going to complain about it again here: MemoryFormat should be a parameter in TensorOptions, not a freestanding positional argument as it is here. The state of positional arguments here is basically unusable for actual users of this API.
There was a problem hiding this comment.
Going to be merged into TensorOptions as soon as TensorOptions codegen rewrite finished ( CC @izdeby )
| "to(Tensor tensor, bool non_blocking=False, bool copy=False)", | ||
| "to(Device device=None, ScalarType dtype=None, bool non_blocking=False, bool copy=False, *, MemoryFormat? memory_format=None)", | ||
| "to(ScalarType dtype, bool non_blocking=False, bool copy=False, *, MemoryFormat? memory_format=None)", | ||
| "to(Tensor tensor, bool non_blocking=False, bool copy=False, *, MemoryFormat? memory_format=None)", |
There was a problem hiding this comment.
Ugh, we should have made non_blocking and copy keyword only too XD
There was a problem hiding this comment.
Going to be separate PR.
native_functions_test_metadata.yaml
Outdated
| @@ -0,0 +1,678 @@ | |||
| - func: __and__ | |||
There was a problem hiding this comment.
Not supposed to be part of PR. Removing.
|
Please rerequest review when this is ready |
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]
Line 1643 in d70f8dd |
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]
…ators" 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]
…operators" 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]
| auto memory_format = | ||
| optional_memory_format.value_or(MemoryFormat::Contiguous); | ||
|
|
||
| if (self.options() == options && !copy && |
There was a problem hiding this comment.
Result of in person conversation: Let's add something like "match TensorOptions with Tensor". This tests if a Tensor is "compatible" with a TensorOptions. (This is not an equality test, because options can be left unspecified, and in that case you always match.)
| if (self.is_non_overlapping_and_dense()) { | ||
| // Copy all strides | ||
| auto r = at::empty_strided(self.sizes(), self.strides(), options); | ||
| r.copy_(self); |
There was a problem hiding this comment.
I'm pleasantly surprised to learn copy_ does the right thing in this case :>
| return to_impl(self, self.options().device(device).dtype(dtype), non_blocking); | ||
| return to_impl( | ||
| self, | ||
| self.options().device(device).dtype(dtype), |
There was a problem hiding this comment.
I know this code originally existed, but I want to point out that it is pretty weird that we have to call self.options() here, because the point of TensorOptions is that it has optional fields, so to_impl should be the method that actually handles the population in the end. No change necessary.
ezyang
left a comment
There was a problem hiding this comment.
I did not carefully check the Python arg parser changes
|
To clarify on TensorOptions equality testing: I see in other parts of the code that this was a preexisting pattern. So I won't require it to be fixed in this PR. |
|
@ailzhang breaks XLA (as almost every PR in this stack) |
Summary: Pull Request resolved: pytorch/pytorch#27107 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: D17931062 Pulled By: VitalyFedyunin fbshipit-source-id: 2c5dd3dd05bf58a9a29f25562cd45190b009c3f9
|
@VitalyFedyunin merged this pull request in d39ab03. |
ghstack-source-id: 46697e1 Pull Request resolved: pytorch/pytorch#27107
Summary: Pull Request resolved: pytorch#27107 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: D17931062 Pulled By: VitalyFedyunin fbshipit-source-id: 2c5dd3dd05bf58a9a29f25562cd45190b009c3f9
Stack from ghstack:
resize_as_operator #27979 Add memory format support toresize_as_operatorrandn_likeoperator #27890 Add memory format support torandn_likeoperatorrandint_likeoperator #27889 Add memory format support torandint_likeoperatorzeros_likeoperator #27562 Add memory format support tozeros_likeoperatorrand_likeoperator #27561 Add memory format support torand_likeoperatorones_likeoperator #27270 Add memory format support toones_likeoperatorfull_likeoperator #27262 Add memory format support tofull_likeoperatorempty_likeoperator #27244 Add memory format support toempty_likeoperatorbyte,char,double,bool,half,int,long,short,float,bfloat16#27228 Add memory format support to typecasting shortcutsbyte,char,double,bool,half,int,long,short,float,bfloat16cpuandcudaoperators #27223 Add memory format support tocpuandcudaoperatorstoandtypeoperators #27107 Add memory_format supporttoandtypeoperatorsAdds 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: D17931062