3
3
#pragma once
4
4
5
5
#include < algorithm>
6
+ #include < cstdint>
6
7
7
8
#include < executorch/runtime/core/exec_aten/exec_aten.h>
9
+ #include < executorch/runtime/core/exec_aten/util/dim_order_util.h>
8
10
#include < executorch/runtime/core/exec_aten/util/scalar_type_util.h>
9
11
#include < executorch/runtime/core/tensor_shape_dynamism.h>
10
12
#include < executorch/runtime/platform/assert.h>
@@ -54,7 +56,7 @@ inline size_t sizes_to_numel(const std::vector<int32_t>& sizes) {
54
56
55
57
inline bool check_strides (
56
58
const std::vector<int32_t > sizes,
57
- const std::vector<int32_t > strides) {
59
+ const std::vector<exec_aten::StridesType > strides) {
58
60
if (sizes.size () != strides.size ()) {
59
61
// The length of stride vector shall equal to size vector.
60
62
return false ;
@@ -147,14 +149,14 @@ inline bool check_dim_order(
147
149
return true ;
148
150
}
149
151
150
- inline std::vector<int32_t > strides_from_dim_order (
152
+ inline std::vector<exec_aten::StridesType > strides_from_dim_order (
151
153
const std::vector<int32_t >& sizes,
152
154
const std::vector<uint8_t >& dim_order) {
153
155
bool legal = check_dim_order (sizes, dim_order);
154
156
ET_CHECK_MSG (legal, " The input dim_order variable is illegal." );
155
157
156
158
size_t ndim = sizes.size ();
157
- std::vector<int32_t > strides (ndim);
159
+ std::vector<exec_aten::StridesType > strides (ndim);
158
160
strides[dim_order[ndim - 1 ]] = 1 ;
159
161
for (int i = ndim - 2 ; i >= 0 ; --i) {
160
162
uint8_t cur_dim = dim_order[i];
@@ -258,7 +260,7 @@ class TensorFactory {
258
260
at::Tensor make (
259
261
const std::vector<int32_t >& sizes,
260
262
const std::vector<ctype>& data,
261
- const std::vector<int32_t > strides = {},
263
+ const std::vector<exec_aten::StridesType > strides = {},
262
264
__ET_UNUSED TensorShapeDynamism dynamism =
263
265
TensorShapeDynamism::DYNAMIC_UNBOUND) {
264
266
auto expected_numel = internal::sizes_to_numel (sizes);
@@ -344,6 +346,71 @@ class TensorFactory {
344
346
sizes, data, internal::channels_last_dim_order (sizes.size ()), dynamism);
345
347
}
346
348
349
+ /* *
350
+ * Given data in contiguous memory format, returns a new Tensor with the
351
+ * specified shape and the same data but in channels last memory format.
352
+ *
353
+ * @param[in] sizes The sizes of the dimensions of the Tensor.
354
+ * @param[in] data The data in contiguous memory format that the Tensor should
355
+ * be initialized with. The size of this vector must be equal to the product
356
+ * of the elements of `sizes`.
357
+ *
358
+ * @return A new Tensor with the specified shape and data in channls last
359
+ * memory format.
360
+ */
361
+ at::Tensor channels_last_like (
362
+ const Tensor& input,
363
+ TensorShapeDynamism dynamism = TensorShapeDynamism::STATIC) {
364
+ ET_CHECK_MSG (input.sizes ().size () == 4 , " Only 4D tensors can be channels last" );
365
+
366
+ const std::vector<int32_t > sizes (
367
+ input.sizes ().begin (), input.sizes ().end ());
368
+
369
+ std::vector<uint8_t > contiguous_dim_order (sizes.size ());
370
+ for (uint8_t i = 0 ; i < sizes.size (); i++) {
371
+ contiguous_dim_order[i] = i;
372
+ }
373
+ std::vector<exec_aten::StridesType> contiguous_strides =
374
+ internal::strides_from_dim_order (sizes, contiguous_dim_order);
375
+
376
+ for (int32_t i = 0 ; i < input.dim (); i++) {
377
+ ET_CHECK_MSG (
378
+ input.strides ()[i] == contiguous_strides[i],
379
+ " Input tensor is not contiguous" );
380
+ }
381
+
382
+ int32_t N = sizes[0 ];
383
+ int32_t C = sizes[1 ];
384
+ int32_t H = sizes[2 ];
385
+ int32_t W = sizes[3 ];
386
+
387
+ std::vector<ctype> contiguous_data (
388
+ input.data_ptr <ctype>(), input.data_ptr <ctype>() + input.numel ());
389
+ std::vector<ctype> channels_last_data (
390
+ N * C * H * W); // Create a new blob with the same total size to contain
391
+ // channels_last data
392
+ for (int32_t n = 0 ; n < N; ++n) {
393
+ for (int32_t c = 0 ; c < C; ++c) {
394
+ for (int32_t h = 0 ; h < H; ++h) {
395
+ for (int32_t w = 0 ; w < W; ++w) {
396
+ // Calculate the index in the original blob
397
+ int32_t old_index = ((n * C + c) * H + h) * W + w;
398
+ // Calculate the index in the new blob
399
+ int32_t new_index = ((n * H + h) * W + w) * C + c;
400
+ // Copy the data
401
+ channels_last_data[new_index] = contiguous_data[old_index];
402
+ }
403
+ }
404
+ }
405
+ }
406
+
407
+ return make_with_dimorder (
408
+ sizes,
409
+ channels_last_data,
410
+ internal::channels_last_dim_order (sizes.size ()),
411
+ dynamism);
412
+ }
413
+
347
414
/* *
348
415
* Returns a new Tensor with the specified shape, containing contiguous
349
416
* data will all elements set to `value`.
@@ -459,14 +526,13 @@ class TensorFactory {
459
526
*/
460
527
at::Tensor empty_strided (
461
528
const std::vector<int32_t >& sizes,
462
- const std::vector<int32_t >& strides,
529
+ const std::vector<exec_aten::StridesType >& strides,
463
530
__ET_UNUSED TensorShapeDynamism dynamism =
464
531
TensorShapeDynamism::DYNAMIC_UNBOUND) {
465
532
auto sizes64 = vec_32_to_64 (sizes);
466
- auto strides64 = vec_32_to_64 (strides);
467
533
return at::empty_strided (
468
534
sizes64,
469
- strides64 ,
535
+ strides ,
470
536
DTYPE,
471
537
/* layout_opt=*/ at::Layout::Strided,
472
538
/* device_opt=*/ at::Device (at::DeviceType::CPU),
@@ -665,7 +731,7 @@ class TensorFactory {
665
731
torch::executor::Tensor make (
666
732
const std::vector<int32_t >& sizes,
667
733
const std::vector<ctype>& data,
668
- const std::vector<int32_t > strides = {},
734
+ const std::vector<exec_aten::StridesType > strides = {},
669
735
TensorShapeDynamism dynamism = TensorShapeDynamism::STATIC) {
670
736
std::vector<int32_t > default_strides;
671
737
// Generate strides from the tensor dimensions, assuming contiguous data if
@@ -745,7 +811,7 @@ class TensorFactory {
745
811
746
812
/* *
747
813
* Returns a new Tensor with the specified shape and data in channels last
748
- * memory layout .
814
+ * memory format .
749
815
*
750
816
* @param[in] sizes The sizes of the dimensions of the Tensor.
751
817
* @param[in] data The data that the Tensor should be initialized with. The
@@ -763,6 +829,60 @@ class TensorFactory {
763
829
sizes, data, internal::channels_last_dim_order (sizes.size ()), dynamism);
764
830
}
765
831
832
+ /* *
833
+ * Given data in contiguous memory format, returns a new Tensor with the
834
+ * specified shape and the same data but in channels last memory format.
835
+ *
836
+ * @param[in] sizes The sizes of the dimensions of the Tensor.
837
+ * @param[in] data The data in contiguous memory format that the Tensor should
838
+ * be initialized with. The size of this vector must be equal to the product
839
+ * of the elements of `sizes`.
840
+ *
841
+ * @return A new Tensor with the specified shape and data in channls last
842
+ * memory format.
843
+ */
844
+ torch::executor::Tensor channels_last_like (
845
+ const Tensor& input,
846
+ TensorShapeDynamism dynamism = TensorShapeDynamism::STATIC) {
847
+ const std::vector<int32_t > sizes (
848
+ input.sizes ().begin (), input.sizes ().end ());
849
+
850
+ ET_CHECK_MSG (sizes.size () == 4 , " Only 4D tensors can be channels last" );
851
+ ET_CHECK_MSG (
852
+ is_contiguous_dim_order (input.dim_order ().data (), input.dim ()) == true ,
853
+ " Input tensor is not contiguous" );
854
+ int32_t N = sizes[0 ];
855
+ int32_t C = sizes[1 ];
856
+ int32_t H = sizes[2 ];
857
+ int32_t W = sizes[3 ];
858
+
859
+ std::vector<ctype> contiguous_data (
860
+ input.data_ptr <ctype>(), input.data_ptr <ctype>() + input.numel ());
861
+ std::vector<ctype> channels_last_data (
862
+ N * C * H * W); // Create a new blob with the same total size to contain
863
+ // channels_last data
864
+ for (int32_t n = 0 ; n < N; ++n) {
865
+ for (int32_t c = 0 ; c < C; ++c) {
866
+ for (int32_t h = 0 ; h < H; ++h) {
867
+ for (int32_t w = 0 ; w < W; ++w) {
868
+ // Calculate the index in the original blob
869
+ int32_t old_index = ((n * C + c) * H + h) * W + w;
870
+ // Calculate the index in the new blob
871
+ int32_t new_index = ((n * H + h) * W + w) * C + c;
872
+ // Copy the data
873
+ channels_last_data[new_index] = contiguous_data[old_index];
874
+ }
875
+ }
876
+ }
877
+ }
878
+
879
+ return make_with_dimorder (
880
+ sizes,
881
+ channels_last_data,
882
+ internal::channels_last_dim_order (sizes.size ()),
883
+ dynamism);
884
+ }
885
+
766
886
/* *
767
887
* Returns a new Tensor with the specified shape, containing contiguous data
768
888
* will all elements set to `value`.
@@ -798,7 +918,20 @@ class TensorFactory {
798
918
799
919
/* *
800
920
* Returns a new Tensor with the specified shape, containing contiguous data
801
- * with all `0` elements.
921
+ * in channels last memory format with all `0` elements.
922
+ *
923
+ * @param[in] sizes The sizes of the dimensions of the Tensor.
924
+ * @return A new Tensor with the specified shape.
925
+ */
926
+ torch::executor::Tensor zeros_channels_last (
927
+ const std::vector<int32_t >& sizes,
928
+ TensorShapeDynamism dynamism = TensorShapeDynamism::STATIC) {
929
+ return full_channels_last (sizes, 0 , dynamism);
930
+ }
931
+
932
+ /* *
933
+ * Returns a new Tensor with the specified shape, containing contiguous data
934
+ * in contiguous memory format with all `0` elements.
802
935
*
803
936
* @param[in] sizes The sizes of the dimensions of the Tensor.
804
937
* @return A new Tensor with the specified shape.
@@ -877,7 +1010,7 @@ class TensorFactory {
877
1010
std::vector<int32_t > sizes_;
878
1011
std::vector<ctype> data_;
879
1012
std::vector<uint8_t > dim_order_;
880
- std::vector<int32_t > strides_;
1013
+ std::vector<exec_aten::StridesType > strides_;
881
1014
TensorImpl impl_;
882
1015
};
883
1016
0 commit comments