Skip to content

Conversation

@VitalyFedyunin
Copy link
Contributor

@VitalyFedyunin VitalyFedyunin commented Oct 15, 2019

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).


Stack from ghstack:

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

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]
VitalyFedyunin added a commit that referenced this pull request Oct 15, 2019
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]
@VitalyFedyunin VitalyFedyunin requested a review from ezyang October 18, 2019 17:23
@VitalyFedyunin
Copy link
Contributor Author

VitalyFedyunin commented Oct 18, 2019

@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]
TORCH_CHECK(
!optional_memory_format.has_value(),
"Unsupported memory format for sparse tensor resize_as_ :",
optional_memory_format.value_or(MemoryFormat::Contiguous));
Copy link
Contributor

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?

if (memory_format == MemoryFormat::Preserve) {
memory_format = the_template.suggest_memory_format();
}
self.unsafeGetTensorImpl()->empty_tensor_restride(memory_format);
Copy link
Contributor

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?

Copy link
Contributor Author

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]
Copy link
Contributor

@gchanan gchanan left a 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]
@VitalyFedyunin
Copy link
Contributor Author

Docs added

// 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
Copy link
Contributor

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?

Copy link
Contributor Author

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
Copy link
Contributor

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):
Copy link
Contributor

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:

  1. explicit contiguous test
  2. explicit channels_last test.

@facebook-github-bot
Copy link
Contributor

@VitalyFedyunin merged this pull request in 9f3b347.

zdevito pushed a commit to zdevito/ATen that referenced this pull request Nov 18, 2019
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
@facebook-github-bot facebook-github-bot deleted the gh/VitalyFedyunin/14/head branch November 21, 2019 15:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants