Skip to content

Commit 8d23621

Browse files
Schopenhauer-loves-Hegelfactnnclaude
authored
【KernelGen】Add index_copy_ operator (#1743)
* feat: add index_copy_ operator with tests and benchmark * chore: add index_copy and index_copy_ to operators.yaml * fix: address review comments - early return, try/except, remove unused wrapper, rename benchmark Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * ci: trigger CI rerun * fix: use IndexCopyBenchmark class consistently in benchmark Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: use explicit shapes in IndexCopyBenchmark instead of REDUCTION_SHAPES Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: use explicit INDEX_COPY_SHAPES instead of REDUCTION_SHAPES in tests Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: factnn <1050552884@qq.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Zang Peiyu <166481866+factnn@users.noreply.github.com>
1 parent e9a6cd0 commit 8d23621

6 files changed

Lines changed: 427 additions & 0 deletions

File tree

benchmark/test_index_copy.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import pytest
2+
import torch
3+
4+
from . import base, consts, utils
5+
6+
7+
class IndexCopyBenchmark(base.GenericBenchmark):
8+
def set_more_shapes(self):
9+
return [(1, 2), (4096, 256), (200, 40999, 3)]
10+
11+
def get_gbps(self, bench_fn_args, latency):
12+
index = bench_fn_args[2]
13+
src = bench_fn_args[3]
14+
io_amount = sum([utils.size_in_bytes(item) for item in [index, src, src]])
15+
return io_amount * 1e-9 / (latency * 1e-3)
16+
17+
18+
def _tensor_input_fn(shape, dtype, device):
19+
inp = torch.randn(shape, dtype=dtype, device=device)
20+
dim = 0 if len(shape) == 1 else 1
21+
src_shape = list(inp.shape)
22+
index_max = src_shape[dim]
23+
index_len = index_max // 2 if index_max >= 2 else 1
24+
index = torch.randperm(index_len, device=device)
25+
src_shape[dim] = index_len
26+
src = torch.randn(src_shape, dtype=dtype, device=device)
27+
yield inp, dim, index, src
28+
29+
30+
@pytest.mark.index_copy
31+
def test_index_copy():
32+
bench = IndexCopyBenchmark(
33+
input_fn=_tensor_input_fn,
34+
op_name="index_copy",
35+
torch_op=torch.index_copy,
36+
dtypes=consts.FLOAT_DTYPES,
37+
)
38+
bench.run()
39+
40+
41+
@pytest.mark.index_copy_
42+
def test_index_copy_():
43+
bench = IndexCopyBenchmark(
44+
input_fn=_tensor_input_fn,
45+
op_name="index_copy_",
46+
torch_op=torch.Tensor.index_copy_,
47+
dtypes=consts.FLOAT_DTYPES,
48+
inplace=True,
49+
)
50+
bench.run()

conf/operators.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2817,6 +2817,30 @@ ops:
28172817
- Tensor
28182818
stages:
28192819
- stable: '4.0'
2820+
- id: index_copy
2821+
description: |
2822+
Copies the elements from `source` into `input` at the positions specified by
2823+
`index` along the given `dim`.
2824+
for:
2825+
- index_copy
2826+
labels:
2827+
- aten
2828+
- KernelGen
2829+
kind:
2830+
- Tensor
2831+
stages:
2832+
- beta: '5.1'
2833+
- id: index_copy_
2834+
description: The in-place version of `index_copy()`.
2835+
for:
2836+
- index_copy_
2837+
labels:
2838+
- aten
2839+
- KernelGen
2840+
kind:
2841+
- Tensor
2842+
stages:
2843+
- beta: '5.1'
28202844
- id: index_put
28212845
description: |
28222846
Puts values from the tensor `values` into the tensor `input` using the indices specified

src/flag_gems/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,8 @@ def torch_ge(v):
277277
("index.Tensor", index),
278278
("index_add", index_add),
279279
("index_add_", index_add_),
280+
("index_copy", index_copy),
281+
("index_copy_", index_copy_),
280282
("index_put", index_put),
281283
("index_put_", index_put_),
282284
("index_select", index_select),

src/flag_gems/ops/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@
170170
from flag_gems.ops.i0_ import i0_
171171
from flag_gems.ops.index import index
172172
from flag_gems.ops.index_add import index_add, index_add_
173+
from flag_gems.ops.index_copy_ import index_copy, index_copy_
173174
from flag_gems.ops.index_put import _index_put_impl_, index_put, index_put_
174175
from flag_gems.ops.index_select import index_select
175176
from flag_gems.ops.isclose import allclose, isclose
@@ -593,6 +594,8 @@
593594
"index",
594595
"index_add",
595596
"index_add_",
597+
"index_copy",
598+
"index_copy_",
596599
"index_put",
597600
"index_put_",
598601
"index_select",

0 commit comments

Comments
 (0)