Skip to content

Conversation

@glaringlee
Copy link
Contributor

@glaringlee glaringlee commented Oct 8, 2020

Stack from ghstack:

*_like functions are used in pytorch to create a new tensor with the same shape of the input tensor. But we don’t always preserve the layout permutation of the tensor. Current behavior is that, for a dense and non-overlapping tensor, its layout permutation is preserved. For eg. passing a channel last contiguous tensor t with ‘shape/stride’ (2, 4, 3, 2)/(24, 1, 8, 4) to empty_like(t) function will create a new tensor with exactly the same ‘shape/stride’ as the input tensor t. However, if the input tensor is non-dense or has overlap, we simply create a contiguous tensor based on input tensor’s shape, so the tensor layout permutation is lost.

This PR preserves the layout permutation for non-dense or overlapping tensor. The strides propagation rule that used in this PR is exactly the same as what is being used in TensorIterator.

The test is based on empty_like. We compare the output tensor's sizes/strides among the empty_like old code, empty_like new code, and TensorIterator based operator exp(). For each sizes/strides we create tensor from both empty_like() and exp() using the following code and record the output tensor's sizes/stride.

a = torch.empty_strided([sizes], [strides])
b = torch.empty_like(a)
c = torch.exp(a)
// record the result of b (in both old and new code) and c to create the list below

The output strides changes are listed below:

sizes/strides old new unary op description
(4,3,2)/(10,1,2) (4,3,2)/(6,2,1) (4,3,2)/(6,1,3) (4,3,2)/(6,1,3) non-dense but overlap
(4,3,2)/(10,0,3) (4,3,2)/(6,2,1) (4,3,2)/(6,2,1) (4,3,2)/(6,2,1) non-dense but overlap (0 strided)
(4,3,2)/(12,2,6) (4,3,2)/(6,2,1) (4,3,2)/(6,1,3) (4,3,2)/(6,1,3) non-dense non-overlap (sliced)
(4,3,2)/(10,1,3) (4,3,2)/(6,2,1) (4,3,2)/(6,1,3) (4,3,2)/(6,1,3) non-dense non-overlap (with gap)
(4,1,1,2)/(10,0,0,2) (4,1,1,2)/(2,2,2,1) (4,1,1,2)/(2,2,2,1) (4,1,1,2)/(2,2,2,1) non-dense non-overlap (0 strided)
(4,1,2)/(10,3,3) (4,1,2)/(2,2,1) (4,1,2)/(2,1,1) (4,1,2)/(2,1,1) overlap (with equal strides)
(4,2,2,2)/(2,0,0,6) (4,2,2,2)/(8,4,2,1) (4,2,2,2)/(1,8,4,16) (4,2,2,2)/(1,8,4,16) overlap (0 strided with equal size)

This is to solve the non-dense tensor layout problem in #45505

TODO:

  • Fix all the BC broken test cases in pytorch
  • Investigate if any fb internal tests are broken (Update: None so far)

This change will cover all kinds of non-dense tensors.

Differential Revision: D24288970

glaringlee pushed a commit that referenced this pull request Oct 8, 2020
ghstack-source-id: e5abe64
Pull Request resolved: #46046
@glaringlee glaringlee changed the title preserve non-dense tensor's layout in *_like functions [WIP]preserve non-dense tensor's layout in *_like functions Oct 8, 2020
@dr-ci
Copy link

dr-ci bot commented Oct 8, 2020

💊 CI failures summary and remediations

As of commit b844a54 (more details on the Dr. CI page):


💚 💚 Looks good so far! There are no failures yet. 💚 💚


This comment was automatically generated by Dr. CI (expand for details).Follow this link to opt-out of these comments for your Pull Requests.

Please report bugs/suggestions on the GitHub issue tracker or post in the (internal) Dr. CI Users group.

See how this bot performed.

This comment has been revised 67 times.

This is to solve the non-dense tensor layout problem in #45505 

This change will cover all kinds of non-dense tensor.

[ghstack-poisoned]
This is to solve the non-dense tensor layout problem in #45505 

This change will cover all kinds of non-dense tensor.

[ghstack-poisoned]
glaringlee pushed a commit that referenced this pull request Oct 9, 2020
ghstack-source-id: 4bb98c0
Pull Request resolved: #46046
This is to solve the non-dense tensor layout problem in #45505 

TODO:
Add test cases
Fix all the BC broken test cases

This change will cover all kinds of non-dense tensors.

[ghstack-poisoned]
glaringlee pushed a commit that referenced this pull request Oct 10, 2020
ghstack-source-id: 4c16476
Pull Request resolved: #46046
lixinyu added 2 commits October 12, 2020 07:51
This is to solve the non-dense tensor layout problem in #45505 

TODO:
Fix all the BC broken test cases

This change will cover all kinds of non-dense tensors.

[ghstack-poisoned]
This is to solve the non-dense tensor layout problem in #45505 

TODO:
Fix all the BC broken test cases

This change will cover all kinds of non-dense tensors.

[ghstack-poisoned]
glaringlee pushed a commit that referenced this pull request Oct 12, 2020
ghstack-source-id: 8b54390
Pull Request resolved: #46046
This is to solve the non-dense tensor layout problem in #45505 

TODO:
Fix all the BC broken test cases

This change will cover all kinds of non-dense tensors.

[ghstack-poisoned]
glaringlee pushed a commit that referenced this pull request Oct 13, 2020
ghstack-source-id: 65666e1
Pull Request resolved: #46046
@glaringlee glaringlee changed the title [WIP]preserve non-dense tensor's layout in *_like functions [WIP]preserve non-dense or overlapping tensor's layout in *_like functions Oct 13, 2020
…*_like functions"


*_like functions are used in pytorch to create a new tensor with the same shape of the input tensor. But we don’t always preserve the layout permutation of the tensor. Current behavior is that, for a dense and non-overlapping tensor, its layout permutation is preserved. For eg.  passing a channel last contiguous tensor t with ‘shape/stride’  (2, 4, 3, 2)/(24, 1, 8, 4) to empty_like(t) function will create a new tensor with exactly the same ‘shape/stride’ as the input tensor t. However, if the input tensor is non-dense or has overlap, we simply create a contiguous tensor based on input tensor’s shape, so the tensor layout permutation is lost.

This PR preserves the layout permutation for non-dense or overlapping tensor. The strides propagation rule that used in this PR is exactly the same as what is being used in TensorIterator.  The behavior changes are listed below:

| code                                                                                                                                                                                           | old                                                   | new                                                  |
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------|------------------------------------------------------|
| #strided tensors<br>a=torch.randn(2,3,8)[:,:,::2].permute(2,0,1)<br>print(a.stride())<br>print(a.exp().stride())<br>print((a+a).stride())<br>out = torch.empty(0)<br>torch.add(a,a,out=out)<br>print(out.stride()) | (2, 24, 8) <br>(6, 3, 1) <br>(1, 12, 4) <br>(6, 3, 1) | (2, 24, 8)<br>(1, 12, 4)<br>(1, 12, 4)<br>(1, 12, 4) |
| #memory dense tensors<br>a=torch.randn(3,1,1).as_strided((3,1,1), (1,3,3))<br>print(a.stride(), (a+torch.randn(1)).stride())<br>a=torch.randn(2,3,4).permute(2,0,1)<br>print(a.stride())<br>print(a.exp().stride())<br>print((a+a).stride())<br>out = torch.empty(0)<br>torch.add(a,a,out=out)<br>print(out.stride())                                                                                                                                                                                               |  (1, 3, 3) (1, 1, 1)<br>(1, 12, 4)<br>(6, 3, 1)<br>(1, 12, 4)<br>(6, 3, 1)                                                       |  (1, 3, 3) (1, 3, 3)<br>(1, 12, 4)<br>(1, 12, 4)<br>(1, 12, 4)<br>(1, 12, 4) |

This is to solve the non-dense tensor layout problem in #45505 

TODO:
- [x] Fix all the BC broken test cases in pytorch
- [ ] Investigate if any fb internal tests are broken

This change will cover all kinds of non-dense tensors.

[ghstack-poisoned]
…*_like functions"


*_like functions are used in pytorch to create a new tensor with the same shape of the input tensor. But we don’t always preserve the layout permutation of the tensor. Current behavior is that, for a dense and non-overlapping tensor, its layout permutation is preserved. For eg.  passing a channel last contiguous tensor t with ‘shape/stride’  (2, 4, 3, 2)/(24, 1, 8, 4) to empty_like(t) function will create a new tensor with exactly the same ‘shape/stride’ as the input tensor t. However, if the input tensor is non-dense or has overlap, we simply create a contiguous tensor based on input tensor’s shape, so the tensor layout permutation is lost.

This PR preserves the layout permutation for non-dense or overlapping tensor. The strides propagation rule that used in this PR is exactly the same as what is being used in TensorIterator.  The behavior changes are listed below:

| code                                                                                                                                                                                           | old                                                   | new                                                  |
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------|------------------------------------------------------|
| #strided tensors<br>a=torch.randn(2,3,8)[:,:,::2].permute(2,0,1)<br>print(a.stride())<br>print(a.exp().stride())<br>print((a+a).stride())<br>out = torch.empty(0)<br>torch.add(a,a,out=out)<br>print(out.stride()) | (2, 24, 8) <br>(6, 3, 1) <br>(1, 12, 4) <br>(6, 3, 1) | (2, 24, 8)<br>(1, 12, 4)<br>(1, 12, 4)<br>(1, 12, 4) |
| #memory dense tensors<br>a=torch.randn(3,1,1).as_strided((3,1,1), (1,3,3))<br>print(a.stride(), (a+torch.randn(1)).stride())<br>a=torch.randn(2,3,4).permute(2,0,1)<br>print(a.stride())<br>print(a.exp().stride())<br>print((a+a).stride())<br>out = torch.empty(0)<br>torch.add(a,a,out=out)<br>print(out.stride())                                                                                                                                                                                               |  (1, 3, 3) (1, 1, 1)<br>(1, 12, 4)<br>(6, 3, 1)<br>(1, 12, 4)<br>(6, 3, 1)                                                       |  (1, 3, 3) (1, 3, 3)<br>(1, 12, 4)<br>(1, 12, 4)<br>(1, 12, 4)<br>(1, 12, 4) |

This is to solve the non-dense tensor layout problem in #45505 

TODO:
- [x] Fix all the BC broken test cases in pytorch
- [ ] Investigate if any fb internal tests are broken

This change will cover all kinds of non-dense tensors.

Differential Revision: [D24288970](https://our.internmc.facebook.com/intern/diff/D24288970)

[ghstack-poisoned]
…*_like functions"


*_like functions are used in pytorch to create a new tensor with the same shape of the input tensor. But we don’t always preserve the layout permutation of the tensor. Current behavior is that, for a dense and non-overlapping tensor, its layout permutation is preserved. For eg.  passing a channel last contiguous tensor t with ‘shape/stride’  (2, 4, 3, 2)/(24, 1, 8, 4) to empty_like(t) function will create a new tensor with exactly the same ‘shape/stride’ as the input tensor t. However, if the input tensor is non-dense or has overlap, we simply create a contiguous tensor based on input tensor’s shape, so the tensor layout permutation is lost.

This PR preserves the layout permutation for non-dense or overlapping tensor. The strides propagation rule that used in this PR is exactly the same as what is being used in TensorIterator.  The behavior changes are listed below:

| code                                                                                                                                                                                           | old                                                   | new                                                  |
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------|------------------------------------------------------|
| #strided tensors<br>a=torch.randn(2,3,8)[:,:,::2].permute(2,0,1)<br>print(a.stride())<br>print(a.exp().stride())<br>print((a+a).stride())<br>out = torch.empty(0)<br>torch.add(a,a,out=out)<br>print(out.stride()) | (2, 24, 8) <br>(6, 3, 1) <br>(1, 12, 4) <br>(6, 3, 1) | (2, 24, 8)<br>(1, 12, 4)<br>(1, 12, 4)<br>(1, 12, 4) |
| #memory dense tensors<br>a=torch.randn(3,1,1).as_strided((3,1,1), (1,3,3))<br>print(a.stride(), (a+torch.randn(1)).stride())<br>a=torch.randn(2,3,4).permute(2,0,1)<br>print(a.stride())<br>print(a.exp().stride())<br>print((a+a).stride())<br>out = torch.empty(0)<br>torch.add(a,a,out=out)<br>print(out.stride())                                                                                                                                                                                               |  (1, 3, 3) (1, 1, 1)<br>(1, 12, 4)<br>(6, 3, 1)<br>(1, 12, 4)<br>(6, 3, 1)                                                       |  (1, 3, 3) (1, 3, 3)<br>(1, 12, 4)<br>(1, 12, 4)<br>(1, 12, 4)<br>(1, 12, 4) |

This is to solve the non-dense tensor layout problem in #45505 

TODO:
- [x] Fix all the BC broken test cases in pytorch
- [ ] Investigate if any fb internal tests are broken

This change will cover all kinds of non-dense tensors.

Differential Revision: [D24288970](https://our.internmc.facebook.com/intern/diff/D24288970)

[ghstack-poisoned]
glaringlee pushed a commit that referenced this pull request Oct 14, 2020
ghstack-source-id: b61fb32
Pull Request resolved: #46046
…*_like functions"


*_like functions are used in pytorch to create a new tensor with the same shape of the input tensor. But we don’t always preserve the layout permutation of the tensor. Current behavior is that, for a dense and non-overlapping tensor, its layout permutation is preserved. For eg.  passing a channel last contiguous tensor t with ‘shape/stride’  (2, 4, 3, 2)/(24, 1, 8, 4) to empty_like(t) function will create a new tensor with exactly the same ‘shape/stride’ as the input tensor t. However, if the input tensor is non-dense or has overlap, we simply create a contiguous tensor based on input tensor’s shape, so the tensor layout permutation is lost.

This PR preserves the layout permutation for non-dense or overlapping tensor. The strides propagation rule that used in this PR is exactly the same as what is being used in TensorIterator.  

The test is based on empty_like. We compare the output tensor's sizes/strides among the empty_like old code, empty_like new code, and TensorIterator based operator exp(). For each sizes/strides we create tensor from both empty_like() and exp() using the following code and record the output tensor's sizes/stride. 
```
a = torch.empty_strided([sizes], [strides])
b = torch.empty_like(a)
c = torch.exp(a)
```
The output strides changes are listed below:

|sizes/strides       |old                  |new                 |unary op            |description                         |
|--------------------|---------------------|--------------------|--------------------|------------------------------------|
|(4,3,2)/(10,1,2)    |(4,3,2)/(6,2,1)      |(4,3,2)/(6,1,3)     |(4,3,2)/(6,1,3)     |non-dense but overlap               |
|(4,3,2)/(10,0,3)    |(4,3,2)/(6,2,1)      |(4,3,2)/(6,2,1)     |(4,3,2)/(6,2,1)     |non-dense but overlap (0 strided)   |
|(4,3,2)/(12,2,6)    |(4,3,2)/(6,2,1)      |(4,3,2)/(6,1,3)     |(4,3,2)/(6,1,3)     |non-dense non-overlap (sliced)      |
|(4,3,2)/(10,1,3)    |(4,3,2)/(6,2,1)      |(4,3,2)/(6,1,3)     |(4,3,2)/(6,1,3)     |non-dense non-overlap (with gap)    |
|(4,1,1,2)/(10,0,0,2)|(4,1,1,2)/(2,2,2,1)  |(4,1,1,2)/(2,2,2,1) |(4,1,1,2)/(2,2,2,1) |non-dense non-overlap (0 strided)   | 
|(4,1,2)/(10,3,3)    |(4,1,2)/(2,2,1)      |(4,1,2)/(2,1,1)     |(4,1,2)/(2,1,1)     |overlap (with equal strides)        |
|(4,2,2,2)/(2,0,0,6) |(4,2,2,2)/(8,4,2,1)  |(4,2,2,2)/(1,8,4,16)|(4,2,2,2)/(1,8,4,16)|overlap (0 strided with equal size) |

This is to solve the non-dense tensor layout problem in #45505 

TODO:
- [x] Fix all the BC broken test cases in pytorch
- [ ] Investigate if any fb internal tests are broken

This change will cover all kinds of non-dense tensors.

Differential Revision: [D24288970](https://our.internmc.facebook.com/intern/diff/D24288970)

[ghstack-poisoned]
@glaringlee glaringlee changed the title [WIP]preserve non-dense or overlapping tensor's layout in *_like functions preserve non-dense or overlapping tensor's layout in *_like functions Oct 14, 2020
…e functions"


*_like functions are used in pytorch to create a new tensor with the same shape of the input tensor. But we don’t always preserve the layout permutation of the tensor. Current behavior is that, for a dense and non-overlapping tensor, its layout permutation is preserved. For eg.  passing a channel last contiguous tensor t with ‘shape/stride’  (2, 4, 3, 2)/(24, 1, 8, 4) to empty_like(t) function will create a new tensor with exactly the same ‘shape/stride’ as the input tensor t. However, if the input tensor is non-dense or has overlap, we simply create a contiguous tensor based on input tensor’s shape, so the tensor layout permutation is lost.

This PR preserves the layout permutation for non-dense or overlapping tensor. The strides propagation rule that used in this PR is exactly the same as what is being used in TensorIterator.  

The test is based on empty_like. We compare the output tensor's sizes/strides among the empty_like old code, empty_like new code, and TensorIterator based operator exp(). For each sizes/strides we create tensor from both empty_like() and exp() using the following code and record the output tensor's sizes/stride. 
```
a = torch.empty_strided([sizes], [strides])
b = torch.empty_like(a)
c = torch.exp(a)
// record the result of b (in both old and new code) and c to create the list below
```
The output strides changes are listed below:

|sizes/strides       |old                  |new                 |unary op            |description                         |
|--------------------|---------------------|--------------------|--------------------|------------------------------------|
|(4,3,2)/(10,1,2)    |(4,3,2)/(6,2,1)      |(4,3,2)/(6,1,3)     |(4,3,2)/(6,1,3)     |non-dense but overlap               |
|(4,3,2)/(10,0,3)    |(4,3,2)/(6,2,1)      |(4,3,2)/(6,2,1)     |(4,3,2)/(6,2,1)     |non-dense but overlap (0 strided)   |
|(4,3,2)/(12,2,6)    |(4,3,2)/(6,2,1)      |(4,3,2)/(6,1,3)     |(4,3,2)/(6,1,3)     |non-dense non-overlap (sliced)      |
|(4,3,2)/(10,1,3)    |(4,3,2)/(6,2,1)      |(4,3,2)/(6,1,3)     |(4,3,2)/(6,1,3)     |non-dense non-overlap (with gap)    |
|(4,1,1,2)/(10,0,0,2)|(4,1,1,2)/(2,2,2,1)  |(4,1,1,2)/(2,2,2,1) |(4,1,1,2)/(2,2,2,1) |non-dense non-overlap (0 strided)   | 
|(4,1,2)/(10,3,3)    |(4,1,2)/(2,2,1)      |(4,1,2)/(2,1,1)     |(4,1,2)/(2,1,1)     |overlap (with equal strides)        |
|(4,2,2,2)/(2,0,0,6) |(4,2,2,2)/(8,4,2,1)  |(4,2,2,2)/(1,8,4,16)|(4,2,2,2)/(1,8,4,16)|overlap (0 strided with equal size) |

This is to solve the non-dense tensor layout problem in #45505 

TODO:
- [x] Fix all the BC broken test cases in pytorch
- [x] Investigate if any fb internal tests are broken (Update: None so far)

This change will cover all kinds of non-dense tensors.

Differential Revision: [D24288970](https://our.internmc.facebook.com/intern/diff/D24288970)

[ghstack-poisoned]
glaringlee pushed a commit that referenced this pull request Oct 14, 2020
ghstack-source-id: c4eb551
Pull Request resolved: #46046
Copy link
Collaborator

@ngimel ngimel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thank you! Nice that all *like functions are handled by changing just empty_like.

…e functions"


*_like functions are used in pytorch to create a new tensor with the same shape of the input tensor. But we don’t always preserve the layout permutation of the tensor. Current behavior is that, for a dense and non-overlapping tensor, its layout permutation is preserved. For eg.  passing a channel last contiguous tensor t with ‘shape/stride’  (2, 4, 3, 2)/(24, 1, 8, 4) to empty_like(t) function will create a new tensor with exactly the same ‘shape/stride’ as the input tensor t. However, if the input tensor is non-dense or has overlap, we simply create a contiguous tensor based on input tensor’s shape, so the tensor layout permutation is lost.

This PR preserves the layout permutation for non-dense or overlapping tensor. The strides propagation rule that used in this PR is exactly the same as what is being used in TensorIterator.  

The test is based on empty_like. We compare the output tensor's sizes/strides among the empty_like old code, empty_like new code, and TensorIterator based operator exp(). For each sizes/strides we create tensor from both empty_like() and exp() using the following code and record the output tensor's sizes/stride. 
```
a = torch.empty_strided([sizes], [strides])
b = torch.empty_like(a)
c = torch.exp(a)
// record the result of b (in both old and new code) and c to create the list below
```
The output strides changes are listed below:

|sizes/strides       |old                  |new                 |unary op            |description                         |
|--------------------|---------------------|--------------------|--------------------|------------------------------------|
|(4,3,2)/(10,1,2)    |(4,3,2)/(6,2,1)      |(4,3,2)/(6,1,3)     |(4,3,2)/(6,1,3)     |non-dense but overlap               |
|(4,3,2)/(10,0,3)    |(4,3,2)/(6,2,1)      |(4,3,2)/(6,2,1)     |(4,3,2)/(6,2,1)     |non-dense but overlap (0 strided)   |
|(4,3,2)/(12,2,6)    |(4,3,2)/(6,2,1)      |(4,3,2)/(6,1,3)     |(4,3,2)/(6,1,3)     |non-dense non-overlap (sliced)      |
|(4,3,2)/(10,1,3)    |(4,3,2)/(6,2,1)      |(4,3,2)/(6,1,3)     |(4,3,2)/(6,1,3)     |non-dense non-overlap (with gap)    |
|(4,1,1,2)/(10,0,0,2)|(4,1,1,2)/(2,2,2,1)  |(4,1,1,2)/(2,2,2,1) |(4,1,1,2)/(2,2,2,1) |non-dense non-overlap (0 strided)   | 
|(4,1,2)/(10,3,3)    |(4,1,2)/(2,2,1)      |(4,1,2)/(2,1,1)     |(4,1,2)/(2,1,1)     |overlap (with equal strides)        |
|(4,2,2,2)/(2,0,0,6) |(4,2,2,2)/(8,4,2,1)  |(4,2,2,2)/(1,8,4,16)|(4,2,2,2)/(1,8,4,16)|overlap (0 strided with equal size) |

This is to solve the non-dense tensor layout problem in #45505 

TODO:
- [x] Fix all the BC broken test cases in pytorch
- [x] Investigate if any fb internal tests are broken (Update: None so far)

This change will cover all kinds of non-dense tensors.

Differential Revision: [D24288970](https://our.internmc.facebook.com/intern/diff/D24288970)

[ghstack-poisoned]
glaringlee pushed a commit that referenced this pull request Oct 20, 2020
ghstack-source-id: 9008dc0
Pull Request resolved: #46046
@facebook-github-bot
Copy link
Contributor

@glaringlee merged this pull request in a651b87.

1 similar comment
@facebook-github-bot
Copy link
Contributor

@glaringlee merged this pull request in a651b87.

@facebook-github-bot facebook-github-bot deleted the gh/glaringlee/31/head branch October 24, 2020 14:15
@albanD albanD added the module: bc-breaking Related to a BC-breaking change label Mar 1, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Merged module: bc-breaking Related to a BC-breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants