blob: fc01b8965830ae27b6197e490b97ee26f98f920c [file] [log] [blame]
XNNPACK Teamb455b122019-09-27 18:10:33 -07001// Copyright (c) Facebook, Inc. and its affiliates.
2// All rights reserved.
3//
4// Copyright 2019 Google LLC
5//
6// This source code is licensed under the BSD-style license found in the
7// LICENSE file in the root directory of this source tree.
8
9#include <assert.h>
10#include <math.h>
11#include <stddef.h>
12#include <stdint.h>
13#include <stdlib.h>
14
15#include <xnnpack.h>
16#include <xnnpack/allocator.h>
17#include <xnnpack/operator.h>
18#include <xnnpack/log.h>
19#include <xnnpack/params.h>
20
21
22static enum xnn_status create_channel_shuffle_nc(
23 size_t groups,
24 size_t group_channels,
25 size_t input_stride,
26 size_t output_stride,
27 uint32_t flags,
28 enum xnn_operator_type operator_type,
29 xnn_operator_t* channel_shuffle_op_out)
30{
31 xnn_operator_t channel_shuffle_op = NULL;
32 enum xnn_status status = xnn_status_uninitialized;
33
34 if (!xnn_params.initialized) {
35 xnn_log_error("failed to create Channel Shuffle operator: XNNPACK is not initialized");
36 goto error;
37 }
38
39 status = xnn_status_invalid_parameter;
40
41 if (groups <= 1) {
42 xnn_log_error(
43 "failed to create Channel Shuffle operator with %zu groups: at least two groups required", groups);
44 goto error;
45 }
46
47 if (group_channels == 0) {
48 xnn_log_error(
49 "failed to create Channel Shuffle operator with %zu group channels: number of group channels must be non-zero",
50 group_channels);
51 goto error;
52 }
53
54 const size_t channels = groups * group_channels;
55 if (input_stride < channels) {
56 xnn_log_error(
57 "failed to create Channel Shuffle operator with input element stride of %zu: "
58 "stride must be at least as large as the number of channels (%zux%zu)",
59 input_stride, groups, group_channels);
60 goto error;
61 }
62
63 if (output_stride < channels) {
64 xnn_log_error(
65 "failed to create Channel Shuffle operator with output element stride of %zu: "
66 "stride must be at least as large as the number of channels (%zux%zu)",
67 output_stride, groups, group_channels);
68 goto error;
69 }
70
71 status = xnn_status_out_of_memory;
72
Marat Dukhan04f03be2019-11-19 12:36:47 -080073 channel_shuffle_op = xnn_allocate_zero_simd_memory(sizeof(struct xnn_operator));
XNNPACK Teamb455b122019-09-27 18:10:33 -070074 if (channel_shuffle_op == NULL) {
75 xnn_log_error("failed to allocate %zu bytes for Channel Shuffle operator descriptor", sizeof(struct xnn_operator));
76 goto error;
77 }
78
79 channel_shuffle_op->groups = groups;
80 channel_shuffle_op->group_channels = group_channels;
81 channel_shuffle_op->input_pixel_stride = input_stride;
82 channel_shuffle_op->output_pixel_stride = output_stride;
83
84 channel_shuffle_op->type = operator_type;
85 channel_shuffle_op->ukernel.type = xnn_ukernel_type_channel_shuffle;
86
87 channel_shuffle_op->state = xnn_run_state_invalid;
88
89 *channel_shuffle_op_out = channel_shuffle_op;
90 return xnn_status_success;
91
92error:
93 xnn_delete_operator(channel_shuffle_op);
94 return status;
95}
96
97
98enum xnn_status xnn_create_channel_shuffle_nc_x8(
99 size_t groups,
100 size_t group_channels,
101 size_t input_stride,
102 size_t output_stride,
103 uint32_t flags,
104 xnn_operator_t* channel_shuffle_op_out)
105{
106 return create_channel_shuffle_nc(
107 groups,
108 group_channels,
109 input_stride,
110 output_stride,
111 flags,
Marat Dukhanefc47b82019-11-18 09:25:38 -0800112 xnn_operator_type_channel_shuffle_nc_x8,
XNNPACK Teamb455b122019-09-27 18:10:33 -0700113 channel_shuffle_op_out);
114}
115
116enum xnn_status xnn_create_channel_shuffle_nc_x32(
117 size_t groups,
118 size_t group_channels,
119 size_t input_stride,
120 size_t output_stride,
121 uint32_t flags,
122 xnn_operator_t* channel_shuffle_op_out)
123{
124 return create_channel_shuffle_nc(
125 groups,
126 group_channels,
127 input_stride,
128 output_stride,
129 flags,
Marat Dukhanefc47b82019-11-18 09:25:38 -0800130 xnn_operator_type_channel_shuffle_nc_x32,
XNNPACK Teamb455b122019-09-27 18:10:33 -0700131 channel_shuffle_op_out);
132}
133
134static enum xnn_status setup_channel_shuffle_nc(
135 xnn_operator_t channel_shuffle_op,
136 size_t batch_size,
137 const void* input,
138 void* output,
139 uint32_t log2_element_size,
140 const struct zip_parameters zip[restrict static 1])
141{
142 channel_shuffle_op->state = xnn_run_state_invalid;
143
144 if (!xnn_params.initialized) {
145 xnn_log_error("failed to setup Channel Shuffle operator: XNNPACK is not initialized");
146 return xnn_status_uninitialized;
147 }
148
149 if (batch_size == 0) {
150 channel_shuffle_op->state = xnn_run_state_skip;
151 return xnn_status_success;
152 }
153
154 channel_shuffle_op->batch_size = batch_size;
155 channel_shuffle_op->input = input;
156 channel_shuffle_op->output = output;
157
158 const size_t groups = channel_shuffle_op->groups;
159 channel_shuffle_op->context.channel_shuffle = (struct channel_shuffle_context) {
160 .x = input,
161 .x_stride = channel_shuffle_op->input_pixel_stride << log2_element_size,
162 .y = output,
163 .y_stride = channel_shuffle_op->output_pixel_stride << log2_element_size,
164 .n = channel_shuffle_op->group_channels << log2_element_size,
165 .m = groups,
166 };
167 channel_shuffle_op->compute.type = xnn_parallelization_type_1d;
168 channel_shuffle_op->compute.range[0] = batch_size;
169 switch (groups) {
170 case 2:
171 channel_shuffle_op->compute.task_1d = (pthreadpool_task_1d_t) xnn_compute_channel_shuffle_fixed;
172 channel_shuffle_op->context.channel_shuffle.fixed_ukernel = zip->x2;
173 break;
174 case 3:
175 channel_shuffle_op->compute.task_1d = (pthreadpool_task_1d_t) xnn_compute_channel_shuffle_fixed;
176 channel_shuffle_op->context.channel_shuffle.fixed_ukernel = zip->x3;
177 break;
178 case 4:
179 channel_shuffle_op->compute.task_1d = (pthreadpool_task_1d_t) xnn_compute_channel_shuffle_fixed;
180 channel_shuffle_op->context.channel_shuffle.fixed_ukernel = zip->x4;
181 break;
182 default:
183 channel_shuffle_op->compute.task_1d = (pthreadpool_task_1d_t) xnn_compute_channel_shuffle_variable;
184 channel_shuffle_op->context.channel_shuffle.variable_ukernel = zip->xm;
185 break;
186 case 0:
187 case 1:
188 XNN_UNREACHABLE;
189 }
190 channel_shuffle_op->state = xnn_run_state_ready;
191
192 return xnn_status_success;
193}
194
195enum xnn_status xnn_setup_channel_shuffle_nc_x8(
196 xnn_operator_t channel_shuffle_op,
197 size_t batch_size,
198 const void* input,
199 void* output,
200 pthreadpool_t threadpool)
201{
Marat Dukhanefc47b82019-11-18 09:25:38 -0800202 if (channel_shuffle_op->type != xnn_operator_type_channel_shuffle_nc_x8) {
203 xnn_log_error("failed to setup Channel Shuffle (NC, X8) operator: operator type mismatch");
XNNPACK Teamb455b122019-09-27 18:10:33 -0700204 return xnn_status_invalid_parameter;
205 }
206
207 return setup_channel_shuffle_nc(
208 channel_shuffle_op,
209 batch_size,
210 input,
211 output,
212 0 /* log2(sizeof(element)) = log2(sizeof(uint8_t)) */,
213 &xnn_params.x8.zip);
214}
215
216enum xnn_status xnn_setup_channel_shuffle_nc_x32(
217 xnn_operator_t channel_shuffle_op,
218 size_t batch_size,
219 const void* input,
220 void* output,
221 pthreadpool_t threadpool)
222{
Marat Dukhanefc47b82019-11-18 09:25:38 -0800223 if (channel_shuffle_op->type != xnn_operator_type_channel_shuffle_nc_x32) {
224 xnn_log_error("failed to setup Channel Shuffle (NC, X32) operator: operator type mismatch");
XNNPACK Teamb455b122019-09-27 18:10:33 -0700225 return xnn_status_invalid_parameter;
226 }
227
228 return setup_channel_shuffle_nc(
229 channel_shuffle_op,
230 batch_size,
231 input,
232 output,
233 2 /* log2(sizeof(element)) = log2(sizeof(uint32_t)) */,
234 &xnn_params.x32.zip);
235}