| 105 | |
| 106 | template <typename T> |
| 107 | void run_permute(const Window &window, const ITensor *src, const ITensor *dst, const PermutationVector &perm) |
| 108 | { |
| 109 | // Source window |
| 110 | Window window_src = window; |
| 111 | |
| 112 | // we only support these two configs in src/core/NEON/kernels/convolution/common/shims.hpp, for all others |
| 113 | // we have to fall back to C++ |
| 114 | if (perm == PermutationVector{2U, 0U, 1U} || perm == PermutationVector{1U, 2U, 0U}) |
| 115 | { |
| 116 | window_src.set(Window::DimX, |
| 117 | Window::Dimension(window.x().start(), window.x().end(), window.x().end() - window.x().start())); |
| 118 | window_src.set(Window::DimY, |
| 119 | Window::Dimension(window.y().start(), window.y().end(), window.y().end() - window.y().start())); |
| 120 | window_src.set(Window::DimZ, |
| 121 | Window::Dimension(window.z().start(), window.z().end(), window.z().end() - window.z().start())); |
| 122 | window_src.set(3, Window::Dimension(window[3].start(), window[3].end(), window[3].end() - window[3].start())); |
| 123 | } |
| 124 | |
| 125 | // Destination window |
| 126 | Window window_dst(window); |
| 127 | const Window::Dimension zero_window = Window::Dimension(0, 0, 0); |
| 128 | for (size_t d = 0; d <= dst->info()->num_dimensions(); ++d) |
| 129 | { |
| 130 | window_dst.set(d, zero_window); |
| 131 | } |
| 132 | |
| 133 | // Create iterators |
| 134 | Iterator src_it(src, window_src); |
| 135 | Iterator dst_it(dst, window_dst); |
| 136 | |
| 137 | // CHW -> HWC |
| 138 | if (perm == PermutationVector{2U, 0U, 1U}) |
| 139 | { |
| 140 | const int in_row_stride = src->info()->strides_in_bytes().y() / sizeof(T); |
| 141 | const int in_channel_stride = src->info()->strides_in_bytes().z() / sizeof(T); |
| 142 | const int in_batch_stride = src->info()->strides_in_bytes()[3] / sizeof(T); |
| 143 | const int n_cols = src->info()->tensor_shape().x(); |
| 144 | const int n_rows = window_src.y().step(); |
| 145 | const int n_channels = src->info()->tensor_shape().z(); |
| 146 | const int n_batches = src->info()->tensor_shape()[3]; |
| 147 | const int out_channel_stride = dst->info()->strides_in_bytes().x() / sizeof(T); |
| 148 | const int out_col_stride = dst->info()->strides_in_bytes().y() / sizeof(T); |
| 149 | const int out_row_stride = dst->info()->strides_in_bytes().z() / sizeof(T); |
| 150 | const int out_batch_stride = dst->info()->strides_in_bytes()[3] / sizeof(T); |
| 151 | execute_window_loop( |
| 152 | window_src, |
| 153 | [&](const Coordinates &id) |
| 154 | { |
| 155 | const int idx = id[0] * out_col_stride + id[1] * out_row_stride + id[2] * out_channel_stride; |
| 156 | reorder::nchw_to_nhwc(reinterpret_cast<const T *>(src_it.ptr()), |
| 157 | reinterpret_cast<T *>(dst_it.ptr()) + idx, n_batches, n_channels, n_rows, n_cols, |
| 158 | in_batch_stride, in_channel_stride, in_row_stride, out_batch_stride, |
| 159 | out_row_stride, out_col_stride); |
| 160 | }, |
| 161 | src_it, dst_it); |
| 162 | } |
| 163 | // HWC -> CHW |
| 164 | else if (perm == PermutationVector{1U, 2U, 0U}) |
nothing calls this directly
no test coverage detected