Skip to content

Commit d32bf99

Browse files
Add op: narrow_copy.out
Differential Revision: D62156680 Pull Request resolved: #5047
1 parent 0c78a9d commit d32bf99

16 files changed

+554
-161
lines changed

kernels/aten/functions.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,8 @@
259259

260260
- op: mul.Scalar_out
261261

262+
- op: narrow_copy.out
263+
262264
- op: native_batch_norm.out
263265

264266
- op: native_group_norm.out
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
#include <executorch/kernels/portable/cpu/util/slice_util.h>
10+
#include <executorch/runtime/kernel/kernel_includes.h>
11+
#include <cstring>
12+
13+
namespace torch {
14+
namespace executor {
15+
namespace native {
16+
17+
using Tensor = exec_aten::Tensor;
18+
19+
Tensor& narrow_copy_out(
20+
RuntimeContext& ctx,
21+
const Tensor& in,
22+
int64_t dim,
23+
int64_t start,
24+
int64_t length,
25+
Tensor& out) {
26+
(void)ctx;
27+
28+
ET_KERNEL_CHECK(
29+
ctx,
30+
check_narrow_copy_args(in, dim, start, length, out),
31+
InvalidArgument,
32+
out);
33+
34+
if (dim < 0) {
35+
dim += in.dim();
36+
}
37+
38+
// @lint-ignore CLANGTIDY facebook-hte-CArray
39+
Tensor::SizesType target_sizes[kTensorDimensionLimit];
40+
size_t target_ndim = 0;
41+
get_narrow_copy_out_target_size(in, dim, length, target_sizes, &target_ndim);
42+
ET_KERNEL_CHECK(
43+
ctx,
44+
resize_tensor(out, {target_sizes, target_ndim}) == Error::Ok,
45+
InvalidArgument,
46+
out);
47+
48+
if (length != 0) {
49+
compute_slice(in, dim, start, length, 1, out);
50+
}
51+
52+
return out;
53+
}
54+
55+
} // namespace native
56+
} // namespace executor
57+
} // namespace torch

kernels/portable/cpu/op_slice_copy.cpp

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
* LICENSE file in the root directory of this source tree.
77
*/
88

9-
#include <executorch/kernels/portable/cpu/util/copy_ops_util.h>
10-
#include <executorch/kernels/portable/cpu/util/index_util.h>
9+
#include <executorch/kernels/portable/cpu/util/slice_util.h>
1110
#include <executorch/runtime/kernel/kernel_includes.h>
1211
#include <cstring>
1312

@@ -41,40 +40,20 @@ Tensor& slice_copy_Tensor_out(
4140
// available)
4241
int64_t start = start_val.has_value() ? start_val.value() : 0;
4342

44-
int64_t num_values = adjust_slice_indices(in.size(dim), &start, &end, step);
43+
int64_t length = adjust_slice_indices(in.size(dim), &start, &end, step);
4544

45+
// @lint-ignore CLANGTIDY facebook-hte-CArray
4646
Tensor::SizesType target_sizes[kTensorDimensionLimit];
4747
size_t target_ndim = 0;
48-
get_slice_copy_out_target_size(
49-
in, dim, num_values, target_sizes, &target_ndim);
48+
get_slice_copy_out_target_size(in, dim, length, target_sizes, &target_ndim);
5049
ET_KERNEL_CHECK(
5150
ctx,
5251
resize_tensor(out, {target_sizes, target_ndim}) == Error::Ok,
5352
InvalidArgument,
5453
out);
5554

56-
size_t dim_length = in.size(dim);
55+
compute_slice(in, dim, start, length, step, out);
5756

58-
size_t leading_dims = getLeadingDims(in, dim);
59-
size_t trailing_dims = getTrailingDims(in, dim);
60-
61-
if (trailing_dims == 0) {
62-
return out;
63-
}
64-
65-
size_t length_per_step = trailing_dims * in.element_size();
66-
67-
const char* input_data = in.const_data_ptr<char>();
68-
char* dest = out.mutable_data_ptr<char>();
69-
70-
for (int i = 0; i < leading_dims; i++) {
71-
const char* src = input_data + (i * dim_length + start) * length_per_step;
72-
for (int j = 0; j < num_values; j++) {
73-
memcpy(dest, src, length_per_step);
74-
src += step * length_per_step;
75-
dest += length_per_step;
76-
}
77-
}
7857
return out;
7958
}
8059

kernels/portable/cpu/op_slice_scatter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#include <cstdint>
1010
#include <cstring>
1111

12-
#include <executorch/kernels/portable/cpu/util/index_util.h>
12+
#include <executorch/kernels/portable/cpu/util/slice_util.h>
1313
#include <executorch/runtime/kernel/kernel_includes.h>
1414

1515
namespace torch {

kernels/portable/cpu/util/copy_ops_util.cpp

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -411,33 +411,6 @@ void get_select_copy_out_target_size(
411411
}
412412
}
413413

414-
bool check_slice_copy_args(
415-
const Tensor& in,
416-
int64_t dim,
417-
int64_t step,
418-
Tensor& out) {
419-
ET_LOG_AND_RETURN_IF_FALSE(in.dim() > 0);
420-
ET_LOG_AND_RETURN_IF_FALSE(tensors_have_same_dtype(in, out));
421-
ET_LOG_AND_RETURN_IF_FALSE(tensor_has_dim(in, dim));
422-
ET_LOG_MSG_AND_RETURN_IF_FALSE(
423-
step > 0, "slice step must be greater than zero");
424-
return true;
425-
}
426-
427-
void get_slice_copy_out_target_size(
428-
const Tensor& in,
429-
int64_t dim,
430-
int64_t num_values,
431-
exec_aten::SizesType* out_sizes,
432-
size_t* out_ndim) {
433-
*out_ndim = in.dim();
434-
435-
for (size_t d = 0; d < in.dim(); ++d) {
436-
out_sizes[d] = in.size(d);
437-
}
438-
out_sizes[dim] = num_values;
439-
}
440-
441414
bool check_split_with_sizes_copy_args(
442415
const Tensor& in,
443416
exec_aten::ArrayRef<int64_t> split_sizes,

kernels/portable/cpu/util/copy_ops_util.h

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -136,19 +136,6 @@ void get_select_copy_out_target_size(
136136
exec_aten::SizesType* out_sizes,
137137
size_t* out_ndim);
138138

139-
bool check_slice_copy_args(
140-
const Tensor& in,
141-
int64_t dim,
142-
int64_t step,
143-
Tensor& out);
144-
145-
void get_slice_copy_out_target_size(
146-
const Tensor& in,
147-
int64_t dim,
148-
int64_t num_values,
149-
exec_aten::SizesType* out_sizes,
150-
size_t* out_ndim);
151-
152139
bool check_split_with_sizes_copy_args(
153140
const Tensor& in,
154141
exec_aten::ArrayRef<int64_t> split_sizes,

kernels/portable/cpu/util/index_util.cpp

Lines changed: 0 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -261,82 +261,5 @@ bool check_select_scatter_args(
261261
return true;
262262
}
263263

264-
bool check_slice_scatter_args(
265-
const Tensor& input,
266-
const Tensor& src,
267-
int64_t dim,
268-
int64_t num_values,
269-
int64_t step,
270-
Tensor output) {
271-
ET_LOG_AND_RETURN_IF_FALSE(input.dim() > 0);
272-
273-
// Check dim. The dim planed to be selected on shall exist in input
274-
ET_LOG_AND_RETURN_IF_FALSE(dim_is_valid(dim, input.dim()));
275-
276-
// Input and output tensors should be the same shape and dtype
277-
ET_LOG_AND_RETURN_IF_FALSE(tensors_have_same_shape_and_dtype(input, output));
278-
279-
// The input.dim() shall equal to src.dim()
280-
ET_LOG_AND_RETURN_IF_FALSE(tensors_have_same_rank(input, src));
281-
282-
// Check step. Step must be greater than zero
283-
ET_LOG_MSG_AND_RETURN_IF_FALSE(
284-
step > 0, "slice step must be greater than zero");
285-
286-
// The size of src tensor should follow these rules:
287-
// - src.size(i) shall equal to input.size(i) if i != dim,
288-
// - src.size(dim) shall equal to num_values
289-
for (size_t d = 0; d < input.dim() - 1; d++) {
290-
if (d != dim) {
291-
ET_LOG_AND_RETURN_IF_FALSE(
292-
tensors_have_same_size_at_dims(input, d, src, d));
293-
} else {
294-
ET_LOG_MSG_AND_RETURN_IF_FALSE(
295-
src.size(d) == num_values,
296-
"input.size(%zu) %zd != num_values %" PRId64 " | dim = %" PRId64 ")",
297-
d,
298-
input.size(d),
299-
num_values,
300-
dim);
301-
}
302-
}
303-
304-
return true;
305-
}
306-
307-
int64_t adjust_slice_indices(
308-
int64_t dim_length,
309-
int64_t* start,
310-
int64_t* end,
311-
int64_t step) {
312-
int64_t num_values = 0;
313-
314-
// Update start and end index
315-
// First convert it to c++ style from python style if needed.
316-
// The start index is using python style E.g., for the shape {2, 3, 4},
317-
// dim = -1 would refer to dim[2], dim = -2 would refer to dim[1], and so on.
318-
*start = *start < 0 ? *start + dim_length : *start;
319-
*end = *end < 0 ? *end + dim_length : *end;
320-
// Second, if start or end still negative, which means user want to start or
321-
// end slicing from very beginning, so set it to zero
322-
*start = *start < 0 ? 0 : *start;
323-
*end = *end < 0 ? 0 : *end;
324-
// Last, if start or end larger than maximum value (dim_length - 1), indicates
325-
// user want to start slicing after end or slicing until the end, so update it
326-
// to dim_length
327-
*start = *start > dim_length ? dim_length : *start;
328-
*end = *end > dim_length ? dim_length : *end;
329-
330-
if (*start >= dim_length || *end <= 0 || *start >= *end) {
331-
// Set num_values to 0 if interval [start, end) is non-exist or do not
332-
// overlap with [0, dim_length)
333-
num_values = 0;
334-
} else {
335-
// Update num_values to min(max_num_values, num_values)
336-
num_values = (*end - 1 - *start) / step + 1;
337-
}
338-
return num_values;
339-
}
340-
341264
} // namespace executor
342265
} // namespace torch

kernels/portable/cpu/util/index_util.h

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -64,19 +64,5 @@ bool check_select_scatter_args(
6464
int64_t index,
6565
Tensor& output);
6666

67-
bool check_slice_scatter_args(
68-
const Tensor& input,
69-
const Tensor& src,
70-
int64_t dim,
71-
int64_t num_values,
72-
int64_t step,
73-
Tensor output);
74-
75-
int64_t adjust_slice_indices(
76-
int64_t dim_length,
77-
int64_t* start,
78-
int64_t* end,
79-
int64_t step);
80-
8167
} // namespace executor
8268
} // namespace torch

0 commit comments

Comments
 (0)