Skip to content

[ET-VK][Ops] aten.index_select #3744

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

Closed
wants to merge 1 commit into from

Conversation

jorgep31415
Copy link
Contributor

@jorgep31415 jorgep31415 commented May 24, 2024

Stack from ghstack (oldest at bottom):

The Operator

nn.Module invocations of torch.index_select get compiled to aten.index_select.default in the Edge Dialect, which carries the following signature.

- func: index_select(Tensor self, int dim, Tensor index) -> Tensor

Implementation

This is a C-packing-only implementation. It is very similar to aten.slice: #3171

- func: slice.Tensor(Tensor(a) self, int dim=0, SymInt? start=None, SymInt? end=None, SymInt step=1) -> Tensor(a)

It features a similar split between a shader for N,H,W and a shader for C, because copying from the C-dimension is more difficult due to C-packing.

Both index_select and slice copy specific indices across 1 dimension. The difference is in the way these indices are specified.

  • slice uses start=1/end=5/step=2 as three scalars for indices 1,3.
  • index_select lists the exact indices inside a tensor e.g. index=torch.tensor([1,3]).

Hence, slice uses a offset=1 and step=2 to compute input position. In index_select, we read the index tensor to compute input position.

Differential Revision: D57745489

## The Operator
`nn.Module` invocations of [`torch.index_select`](https://pytorch.org/docs/stable/generated/torch.index_select.html) get compiled to `aten.index_select.default` in the Edge Dialect, which carries the following signature.
```
- func: index_select(Tensor self, int dim, Tensor index) -> Tensor
```

## Implementation
This is a C-packing-only implementation. It is very similar to `aten.slice`: #3171
```
- func: slice.Tensor(Tensor(a) self, int dim=0, SymInt? start=None, SymInt? end=None, SymInt step=1) -> Tensor(a)
```

It features a similar split between a shader for N,H,W and a shader for C, because copying from the C-dimension is more difficult due to C-packing.

Both `index_select` and `slice` copy specific indices across 1 dimension. The difference is in the way these indices are specified.
- `slice` uses `start=1`/`end=5`/`step=2` as three scalars for indices `1,3`.
- `index_select` lists the exact indices inside a tensor e.g. `index=torch.tensor([1,3])`.

Hence, `slice` uses a `offset=1` and `step=2` to compute input position. In `index_select`, we read the index tensor to compute input position.

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

[ghstack-poisoned]
Copy link

pytorch-bot bot commented May 24, 2024

🔗 Helpful Links

🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/3744

Note: Links to docs will display an error until the docs builds have been completed.

✅ No Failures

As of commit 7b36eff with merge base 1343224 (image):
💚 Looks good so far! There are no failures yet. 💚

This comment was automatically generated by Dr. CI and updates every 15 minutes.

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label May 24, 2024
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D57745489

jorgep31415 added a commit that referenced this pull request May 24, 2024
## The Operator
`nn.Module` invocations of [`torch.index_select`](https://pytorch.org/docs/stable/generated/torch.index_select.html) get compiled to `aten.index_select.default` in the Edge Dialect, which carries the following signature.
```
- func: index_select(Tensor self, int dim, Tensor index) -> Tensor
```

## Implementation
This is a C-packing-only implementation. It is very similar to `aten.slice`: #3171
```
- func: slice.Tensor(Tensor(a) self, int dim=0, SymInt? start=None, SymInt? end=None, SymInt step=1) -> Tensor(a)
```

It features a similar split between a shader for N,H,W and a shader for C, because copying from the C-dimension is more difficult due to C-packing.

Both `index_select` and `slice` copy specific indices across 1 dimension. The difference is in the way these indices are specified.
- `slice` uses `start=1`/`end=5`/`step=2` as three scalars for indices `1,3`.
- `index_select` lists the exact indices inside a tensor e.g. `index=torch.tensor([1,3])`.

Hence, `slice` uses a `offset=1` and `step=2` to compute input position. In `index_select`, we read the index tensor to compute input position.

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

ghstack-source-id: 227736336
Pull Request resolved: #3744
@facebook-github-bot
Copy link
Contributor

This pull request has been merged in c665c17.

jorgep31415 added a commit that referenced this pull request May 29, 2024
## The Operator
`nn.Module` invocations on the embedding returned by [`torch.nn.Embedding`](https://pytorch.org/docs/stable/generated/torch.nn.Embedding.html) get compiled to `aten.embedding.default` in the Edge Dialect, which carries the following signature.
```
- func: embedding(Tensor weight, Tensor indices, SymInt padding_idx=-1, bool scale_grad_by_freq=False, bool sparse=False) -> Tensor
```

## Implementation
This is a C-packing-only implementation.

Interestingly, the 1D-`indices` case is equivalent to the `dim=0` case of the preceding `aten.index_select`: #3744
```
- func: index_select(Tensor self, int dim, Tensor index) -> Tensor
```
I naïvely thought the rest of the operator would be similarly easy but it wasn't. The 2D and 3D-`indices` cases are more involved to the extent that we require a standalone `cpp`/`glsl` file.

## Codegen
We add support for making 2D and 3D index tensors. This requires new generation functions as well as renaming of the `case_name` string to recursively handle list `pylist`s.
```
// 1D
Test(weight=[10, 9], indices=[0, 2]),
// 2D
Test(weight=[10, 9], indices=[[0, 2], [1, 4], [7, 7]]),
// 3D
Test(weight=[10, 9], indices=[[[3, 1, 4], [1, 5, 9]], [[2, 6, 5], [3, 5, 8]]]),
```

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

[ghstack-poisoned]
@facebook-github-bot
Copy link
Contributor

This pull request was exported from Phabricator. Differential Revision: D57745489

jorgep31415 added a commit that referenced this pull request May 29, 2024
## The Operator
`nn.Module` invocations on the embedding returned by [`torch.nn.Embedding`](https://pytorch.org/docs/stable/generated/torch.nn.Embedding.html) get compiled to `aten.embedding.default` in the Edge Dialect, which carries the following signature.
```
- func: embedding(Tensor weight, Tensor indices, SymInt padding_idx=-1, bool scale_grad_by_freq=False, bool sparse=False) -> Tensor
```

## Implementation
This is a C-packing-only implementation.

Interestingly, the 1D-`indices` case is equivalent to the `dim=0` case of the preceding `aten.index_select`: #3744
```
- func: index_select(Tensor self, int dim, Tensor index) -> Tensor
```
I naïvely thought the rest of the operator would be similarly easy but it wasn't. The 2D and 3D-`indices` cases are more involved to the extent that we require a standalone `cpp`/`glsl` file.

## Codegen
We add support for making 2D and 3D index tensors. This requires new generation functions as well as renaming of the `case_name` string to recursively handle list `pylist`s.
```
// 1D
Test(weight=[10, 9], indices=[0, 2]),
// 2D
Test(weight=[10, 9], indices=[[0, 2], [1, 4], [7, 7]]),
// 3D
Test(weight=[10, 9], indices=[[[3, 1, 4], [1, 5, 9]], [[2, 6, 5], [3, 5, 8]]]),
```

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

ghstack-source-id: 228038402
Pull Request resolved: #3762
jorgep31415 added a commit that referenced this pull request May 29, 2024
## The Operator
`nn.Module` invocations on the embedding returned by [`torch.nn.Embedding`](https://pytorch.org/docs/stable/generated/torch.nn.Embedding.html) get compiled to `aten.embedding.default` in the Edge Dialect, which carries the following signature.
```
- func: embedding(Tensor weight, Tensor indices, SymInt padding_idx=-1, bool scale_grad_by_freq=False, bool sparse=False) -> Tensor
```

## Implementation
This is a C-packing-only implementation.

Interestingly, the 1D-`indices` case is equivalent to the `dim=0` case of the preceding `aten.index_select`: #3744
```
- func: index_select(Tensor self, int dim, Tensor index) -> Tensor
```
I naïvely thought the rest of the operator would be similarly easy but it wasn't. The 2D and 3D-`indices` cases are more involved to the extent that we require a standalone `cpp`/`glsl` file.

## Codegen
We add support for making 2D and 3D index tensors. This requires new generation functions as well as renaming of the `case_name` string to recursively handle list `pylist`s.
```
// 1D
Test(weight=[10, 9], indices=[0, 2]),
// 2D
Test(weight=[10, 9], indices=[[0, 2], [1, 4], [7, 7]]),
// 3D
Test(weight=[10, 9], indices=[[[3, 1, 4], [1, 5, 9]], [[2, 6, 5], [3, 5, 8]]]),
```

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

[ghstack-poisoned]
jorgep31415 added a commit that referenced this pull request May 29, 2024
## The Operator
`nn.Module` invocations on the embedding returned by [`torch.nn.Embedding`](https://pytorch.org/docs/stable/generated/torch.nn.Embedding.html) get compiled to `aten.embedding.default` in the Edge Dialect, which carries the following signature.
```
- func: embedding(Tensor weight, Tensor indices, SymInt padding_idx=-1, bool scale_grad_by_freq=False, bool sparse=False) -> Tensor
```

## Implementation
This is a C-packing-only implementation.

Interestingly, the 1D-`indices` case is equivalent to the `dim=0` case of the preceding `aten.index_select`: #3744
```
- func: index_select(Tensor self, int dim, Tensor index) -> Tensor
```
I naïvely thought the rest of the operator would be similarly easy but it wasn't. The 2D and 3D-`indices` cases are more involved to the extent that we require a standalone `cpp`/`glsl` file.

## Codegen
We add support for making 2D and 3D index tensors. This requires new generation functions as well as renaming of the `case_name` string to recursively handle list `pylist`s.
```
// 1D
Test(weight=[10, 9], indices=[0, 2]),
// 2D
Test(weight=[10, 9], indices=[[0, 2], [1, 4], [7, 7]]),
// 3D
Test(weight=[10, 9], indices=[[[3, 1, 4], [1, 5, 9]], [[2, 6, 5], [3, 5, 8]]]),
```

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

[ghstack-poisoned]
jorgep31415 added a commit that referenced this pull request May 29, 2024
## The Operator
`nn.Module` invocations on the embedding returned by [`torch.nn.Embedding`](https://pytorch.org/docs/stable/generated/torch.nn.Embedding.html) get compiled to `aten.embedding.default` in the Edge Dialect, which carries the following signature.
```
- func: embedding(Tensor weight, Tensor indices, SymInt padding_idx=-1, bool scale_grad_by_freq=False, bool sparse=False) -> Tensor
```

## Implementation
This is a C-packing-only implementation.

Interestingly, the 1D-`indices` case is equivalent to the `dim=0` case of the preceding `aten.index_select`: #3744
```
- func: index_select(Tensor self, int dim, Tensor index) -> Tensor
```
I naïvely thought the rest of the operator would be similarly easy but it wasn't. The 2D and 3D-`indices` cases are more involved to the extent that we require a standalone `cpp`/`glsl` file.

## Codegen
We add support for making 2D and 3D index tensors. This requires new generation functions as well as renaming of the `case_name` string to recursively handle list `pylist`s.
```
// 1D
Test(weight=[10, 9], indices=[0, 2]),
// 2D
Test(weight=[10, 9], indices=[[0, 2], [1, 4], [7, 7]]),
// 3D
Test(weight=[10, 9], indices=[[[3, 1, 4], [1, 5, 9]], [[2, 6, 5], [3, 5, 8]]]),
```

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

[ghstack-poisoned]
jorgep31415 added a commit that referenced this pull request May 29, 2024
## The Operator
`nn.Module` invocations on the embedding returned by [`torch.nn.Embedding`](https://pytorch.org/docs/stable/generated/torch.nn.Embedding.html) get compiled to `aten.embedding.default` in the Edge Dialect, which carries the following signature.
```
- func: embedding(Tensor weight, Tensor indices, SymInt padding_idx=-1, bool scale_grad_by_freq=False, bool sparse=False) -> Tensor
```

## Implementation
This is a C-packing-only implementation.

Interestingly, the 1D-`indices` case is equivalent to the `dim=0` case of the preceding `aten.index_select`: #3744
```
- func: index_select(Tensor self, int dim, Tensor index) -> Tensor
```
I naïvely thought the rest of the operator would be similarly easy but it wasn't. The 2D and 3D-`indices` cases are more involved to the extent that we require a standalone `cpp`/`glsl` file.

## Codegen
We add support for making 2D and 3D index tensors. This requires new generation functions as well as renaming of the `case_name` string to recursively handle list `pylist`s.
```
// 1D
Test(weight=[10, 9], indices=[0, 2]),
// 2D
Test(weight=[10, 9], indices=[[0, 2], [1, 4], [7, 7]]),
// 3D
Test(weight=[10, 9], indices=[[[3, 1, 4], [1, 5, 9]], [[2, 6, 5], [3, 5, 8]]]),
```

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

[ghstack-poisoned]
jorgep31415 added a commit that referenced this pull request May 29, 2024
## The Operator
`nn.Module` invocations on the embedding returned by [`torch.nn.Embedding`](https://pytorch.org/docs/stable/generated/torch.nn.Embedding.html) get compiled to `aten.embedding.default` in the Edge Dialect, which carries the following signature.
```
- func: embedding(Tensor weight, Tensor indices, SymInt padding_idx=-1, bool scale_grad_by_freq=False, bool sparse=False) -> Tensor
```

## Implementation
This is a C-packing-only implementation.

Interestingly, the 1D-`indices` case is equivalent to the `dim=0` case of the preceding `aten.index_select`: #3744
```
- func: index_select(Tensor self, int dim, Tensor index) -> Tensor
```
I naïvely thought the rest of the operator would be similarly easy but it wasn't. The 2D and 3D-`indices` cases are more involved to the extent that we require a standalone `cpp`/`glsl` file.

## Codegen
We add support for making 2D and 3D index tensors. This requires new generation functions as well as renaming of the `case_name` string to recursively handle list `pylist`s.
```
// 1D
Test(weight=[10, 9], indices=[0, 2]),
// 2D
Test(weight=[10, 9], indices=[[0, 2], [1, 4], [7, 7]]),
// 3D
Test(weight=[10, 9], indices=[[[3, 1, 4], [1, 5, 9]], [[2, 6, 5], [3, 5, 8]]]),
```

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

[ghstack-poisoned]
jorgep31415 added a commit that referenced this pull request May 29, 2024
## The Operator
`nn.Module` invocations on the embedding returned by [`torch.nn.Embedding`](https://pytorch.org/docs/stable/generated/torch.nn.Embedding.html) get compiled to `aten.embedding.default` in the Edge Dialect, which carries the following signature.
```
- func: embedding(Tensor weight, Tensor indices, SymInt padding_idx=-1, bool scale_grad_by_freq=False, bool sparse=False) -> Tensor
```

## Implementation
This is a C-packing-only implementation.

Interestingly, the 1D-`indices` case is equivalent to the `dim=0` case of the preceding `aten.index_select`: #3744
```
- func: index_select(Tensor self, int dim, Tensor index) -> Tensor
```
I naïvely thought the rest of the operator would be similarly easy but it wasn't. The 2D and 3D-`indices` cases are more involved to the extent that we require a standalone `cpp`/`glsl` file.

## Codegen
We add support for making 2D and 3D index tensors. This requires new generation functions as well as renaming of the `case_name` string to recursively handle list `pylist`s.
```
// 1D
Test(weight=[10, 9], indices=[0, 2]),
// 2D
Test(weight=[10, 9], indices=[[0, 2], [1, 4], [7, 7]]),
// 3D
Test(weight=[10, 9], indices=[[[3, 1, 4], [1, 5, 9]], [[2, 6, 5], [3, 5, 8]]]),
```

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

[ghstack-poisoned]
facebook-github-bot pushed a commit that referenced this pull request May 30, 2024
Summary:
Pull Request resolved: #3762

## The Operator
`nn.Module` invocations on the embedding returned by [`torch.nn.Embedding`](https://pytorch.org/docs/stable/generated/torch.nn.Embedding.html) get compiled to `aten.embedding.default` in the Edge Dialect, which carries the following signature.
```
- func: embedding(Tensor weight, Tensor indices, SymInt padding_idx=-1, bool scale_grad_by_freq=False, bool sparse=False) -> Tensor
```

## Implementation
This is a C-packing-only implementation.

Interestingly, the 1D-`indices` case is equivalent to the `dim=0` case of the preceding `aten.index_select`: #3744
```
- func: index_select(Tensor self, int dim, Tensor index) -> Tensor
```
I naïvely thought the rest of the operator would be similarly easy but it wasn't. The 2D and 3D-`indices` cases are more involved to the extent that we require a standalone `cpp`/`glsl` file.

## Codegen
We add support for making 2D and 3D index tensors. This requires new generation functions as well as renaming of the `case_name` string to recursively handle list `pylist`s.
```
// 1D
Test(weight=[10, 9], indices=[0, 2]),
// 2D
Test(weight=[10, 9], indices=[[0, 2], [1, 4], [7, 7]]),
// 3D
Test(weight=[10, 9], indices=[[[3, 1, 4], [1, 5, 9]], [[2, 6, 5], [3, 5, 8]]]),
```
ghstack-source-id: 228201965

Reviewed By: copyrightly

Differential Revision: D57880520

fbshipit-source-id: 67da04bcbb2b36ce2c1ec2c8f7ccf59ed512547c
kedarnath03 pushed a commit to kedarnath03/executorch that referenced this pull request Jun 25, 2025
Pull Request resolved: pytorch/executorch#3762

## The Operator
`nn.Module` invocations on the embedding returned by [`torch.nn.Embedding`](https://pytorch.org/docs/stable/generated/torch.nn.Embedding.html) get compiled to `aten.embedding.default` in the Edge Dialect, which carries the following signature.
```
- func: embedding(Tensor weight, Tensor indices, SymInt padding_idx=-1, bool scale_grad_by_freq=False, bool sparse=False) -> Tensor
```

## Implementation
This is a C-packing-only implementation.

Interestingly, the 1D-`indices` case is equivalent to the `dim=0` case of the preceding `aten.index_select`: pytorch/executorch#3744
```
- func: index_select(Tensor self, int dim, Tensor index) -> Tensor
```
I naïvely thought the rest of the operator would be similarly easy but it wasn't. The 2D and 3D-`indices` cases are more involved to the extent that we require a standalone `cpp`/`glsl` file.

## Codegen
We add support for making 2D and 3D index tensors. This requires new generation functions as well as renaming of the `case_name` string to recursively handle list `pylist`s.
```
// 1D
Test(weight=[10, 9], indices=[0, 2]),
// 2D
Test(weight=[10, 9], indices=[[0, 2], [1, 4], [7, 7]]),
// 3D
Test(weight=[10, 9], indices=[[[3, 1, 4], [1, 5, 9]], [[2, 6, 5], [3, 5, 8]]]),
```
ghstack-source-id: 228201965

Differential Revision: [D57880520](https://our.internmc.facebook.com/intern/diff/D57880520/)
kedarnath03 pushed a commit to kedarnath03/executorch that referenced this pull request Jun 25, 2025
Pull Request resolved: pytorch/executorch#3744

## The Operator
`nn.Module` invocations of [`torch.index_select`](https://pytorch.org/docs/stable/generated/torch.index_select.html) get compiled to `aten.index_select.default` in the Edge Dialect, which carries the following signature.
```
- func: index_select(Tensor self, int dim, Tensor index) -> Tensor
```

## Implementation
This is a C-packing-only implementation. It is very similar to `aten.slice`: pytorch/executorch#3171
```
- func: slice.Tensor(Tensor(a) self, int dim=0, SymInt? start=None, SymInt? end=None, SymInt step=1) -> Tensor(a)
```

It features a similar split between a shader for N,H,W and a shader for C, because copying from the C-dimension is more difficult due to C-packing.

Both `index_select` and `slice` copy specific indices across 1 dimension. The difference is in the way these indices are specified.
- `slice` uses `start=1`/`end=5`/`step=2` as three scalars for indices `1,3`.
- `index_select` lists the exact indices inside a tensor e.g. `index=torch.tensor([1,3])`.

Hence, `slice` uses a `offset=1` and `step=2` to compute input position. In `index_select`, we read the index tensor to compute input position.

Differential Revision: [D57745489](https://our.internmc.facebook.com/intern/diff/D57745489/)
ghstack-source-id: 227954599
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. fb-exported Merged
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants