Skip to content

Commit e3ccc41

Browse files
committed
Add some code to expand convolution to 3d (still work in progress).
1 parent f3a29ea commit e3ccc41

10 files changed

+365
-165
lines changed

lib/nnc/ccv_cnnp_model_addons.c

+13-8
Original file line numberDiff line numberDiff line change
@@ -1102,16 +1102,18 @@ static void _ccv_cnnp_convolution_build(ccv_cnnp_model_t* const super, ccv_nnc_s
11021102
assert(output_size == 1);
11031103
const ccv_nnc_tensor_param_t params = ccv_nnc_tensor_symbol_params(graph, inputs[0]);
11041104
int i;
1105-
const int nd = CCV_NNC_MAX_DIM + 2;
1105+
const int k_nd = ccv_nnc_tensor_nd(self->kdim);
1106+
const int nd = k_nd + 2;
11061107
ccv_nnc_tensor_param_t weights_params = params;
11071108
if (self->format)
11081109
weights_params.format = self->format;
11091110
ccv_nnc_tensor_set_n(&weights_params, self->filters);
1110-
assert(ccv_nnc_tensor_get_c(params) % self->groups == 0);
1111-
ccv_nnc_tensor_set_c(&weights_params, nd, ccv_nnc_tensor_get_c(params) / self->groups);
1111+
const int c = ccv_nnc_tensor_get_c(params);
1112+
assert(c % self->groups == 0);
1113+
ccv_nnc_tensor_set_c(&weights_params, nd, c / self->groups);
11121114
const int hw = ccv_nnc_tensor_hw(weights_params, nd);
11131115
assert(hw >= 0);
1114-
for (i = 0; i < CCV_NNC_MAX_DIM; i++)
1116+
for (i = 0; i < k_nd; i++)
11151117
weights_params.dim[i + hw] = self->kdim[i];
11161118
if (!self->weights.graph)
11171119
self->weights = ccv_nnc_tensor_symbol_new(graph, weights_params, "weights");
@@ -1122,12 +1124,13 @@ static void _ccv_cnnp_convolution_build(ccv_cnnp_model_t* const super, ccv_nnc_s
11221124
memset(bias_params.dim, 0, sizeof(bias_params.dim));
11231125
bias_params.dim[0] = self->filters;
11241126
ccv_nnc_cmd_t cmd = CMD_CONVOLUTION_FORWARD(self->groups, self->filters);
1125-
for (i = 0; i < CCV_NNC_MAX_DIM; i++)
1127+
for (i = 0; i < k_nd; i++)
11261128
cmd.info.size.dim[i] = self->kdim[i];
1129+
cmd.info.size.dim[k_nd] = c;
11271130
memcpy(cmd.info.convolution.dilation, self->dilation, sizeof(self->dilation));
11281131
ccv_nnc_tensor_param_t output_params;
11291132
// Dilate weight size based on the dilation factor.
1130-
for (i = 0; i < CCV_NNC_MAX_DIM; i++)
1133+
for (i = 0; i < k_nd; i++)
11311134
weights_params.dim[i + hw] = (self->kdim[i] - 1) * ccv_max(self->dilation[i], 1) + 1;
11321135
ccv_nnc_hint_tensor_auto(cmd, (ccv_nnc_tensor_param_t []){
11331136
params,
@@ -1235,8 +1238,9 @@ static void _ccv_cnnp_convolution_transpose_build(ccv_cnnp_model_t* const super,
12351238
ccv_nnc_tensor_param_t weights_params = params;
12361239
if (self->format)
12371240
weights_params.format = self->format;
1238-
ccv_nnc_tensor_set_n(&weights_params, ccv_nnc_tensor_get_c(params));
1239-
assert(ccv_nnc_tensor_get_c(params) % self->groups == 0);
1241+
const int c = ccv_nnc_tensor_get_c(params);
1242+
ccv_nnc_tensor_set_n(&weights_params, c);
1243+
assert(c % self->groups == 0);
12401244
ccv_nnc_tensor_set_c(&weights_params, nd, self->filters / self->groups);
12411245
const int hw = ccv_nnc_tensor_hw(weights_params, nd);
12421246
assert(hw >= 0);
@@ -1253,6 +1257,7 @@ static void _ccv_cnnp_convolution_transpose_build(ccv_cnnp_model_t* const super,
12531257
ccv_nnc_cmd_t cmd = CMD_CONVOLUTION_TRANSPOSE_FORWARD(self->groups, self->filters, self->output_padding);
12541258
for (i = 0; i < CCV_NNC_MAX_DIM; i++)
12551259
cmd.info.size.dim[i] = self->kdim[i];
1260+
cmd.info.size.dim[CCV_NNC_MAX_DIM] = c;
12561261
memcpy(cmd.info.convolution_transpose.dilation, self->dilation, sizeof(self->dilation));
12571262
ccv_nnc_tensor_param_t output_params;
12581263
// Dilate weight size based on the dilation factor.

lib/nnc/ccv_nnc_cmd.c

+16-12
Original file line numberDiff line numberDiff line change
@@ -155,19 +155,21 @@ int ccv_nnc_hint_verify(const ccv_nnc_hint_t hint, const ccv_nnc_cmd_param_t cmd
155155
int i;
156156
assert(a.format == b.format);
157157
const int nd = ccv_nnc_tensor_nd(a.dim);
158-
assert(nd == CCV_NNC_MAX_DIM + 1 || nd == CCV_NNC_MAX_DIM + 2);
158+
const int size_nd = ccv_max(2, ccv_nnc_tensor_nd(cmd.size.dim) - 1);
159+
assert(size_nd == 2 || size_nd == 3); // Support 3D convolution.
160+
assert(nd == size_nd + 1 || nd == size_nd + 2);
159161
int hw;
160162
if ((a.format == CCV_TENSOR_FORMAT_CHWN) ||
161-
(a.format == CCV_TENSOR_FORMAT_NHWC && nd == CCV_NNC_MAX_DIM + 1))
163+
(a.format == CCV_TENSOR_FORMAT_NHWC && nd == size_nd + 1))
162164
hw = 0;
163-
else if ((a.format == CCV_TENSOR_FORMAT_NHWC && nd == CCV_NNC_MAX_DIM + 2) ||
164-
(a.format == CCV_TENSOR_FORMAT_NCHW && nd == CCV_NNC_MAX_DIM + 1))
165+
else if ((a.format == CCV_TENSOR_FORMAT_NHWC && nd == size_nd + 2) ||
166+
(a.format == CCV_TENSOR_FORMAT_NCHW && nd == size_nd + 1))
165167
hw = 1;
166-
else if (a.format == CCV_TENSOR_FORMAT_NCHW && nd == CCV_NNC_MAX_DIM + 2)
168+
else if (a.format == CCV_TENSOR_FORMAT_NCHW && nd == size_nd + 2)
167169
hw = 2;
168170
else
169171
assert(0 && "unknown format");
170-
for (i = 0; i < CCV_NNC_MAX_DIM; i++)
172+
for (i = 0; i < size_nd; i++)
171173
{
172174
if ((hint.border.begin[i] + hint.border.end[i] + a.dim[i + hw] - cmd.size.dim[i]) % hint.stride.dim[i] != 0)
173175
return -1;
@@ -186,23 +188,25 @@ ccv_nnc_hint_t ccv_nnc_hint_auto(const ccv_nnc_cmd_param_t cmd, const ccv_nnc_te
186188
assert(a.format == b.format);
187189
const int a_nd = ccv_nnc_tensor_nd(a.dim);
188190
const int b_nd = ccv_nnc_tensor_nd(b.dim);
191+
const int size_nd = ccv_max(2, ccv_nnc_tensor_nd(cmd.size.dim) - 1);
192+
assert(size_nd == 2 || size_nd == 3); // Support 3D convolution.
189193
// Is not auto hint deducible dimensions.
190-
if (a_nd != b_nd || (a_nd != CCV_NNC_MAX_DIM + 1 && a_nd != CCV_NNC_MAX_DIM + 2))
194+
if (a_nd != b_nd || (a_nd != size_nd + 1 && a_nd != size_nd + 2))
191195
return ccv_nnc_no_hint;
192196
int hw;
193197
if ((a.format == CCV_TENSOR_FORMAT_CHWN) ||
194-
(a.format == CCV_TENSOR_FORMAT_NHWC && a_nd == CCV_NNC_MAX_DIM + 1))
198+
(a.format == CCV_TENSOR_FORMAT_NHWC && a_nd == size_nd + 1))
195199
hw = 0;
196-
else if ((a.format == CCV_TENSOR_FORMAT_NHWC && a_nd == CCV_NNC_MAX_DIM + 2) ||
197-
(a.format == CCV_TENSOR_FORMAT_NCHW && a_nd == CCV_NNC_MAX_DIM + 1))
200+
else if ((a.format == CCV_TENSOR_FORMAT_NHWC && a_nd == size_nd + 2) ||
201+
(a.format == CCV_TENSOR_FORMAT_NCHW && a_nd == size_nd + 1))
198202
hw = 1;
199-
else if (a.format == CCV_TENSOR_FORMAT_NCHW && a_nd == CCV_NNC_MAX_DIM + 2)
203+
else if (a.format == CCV_TENSOR_FORMAT_NCHW && a_nd == size_nd + 2)
200204
hw = 2;
201205
else
202206
assert(0 && "unknown format");
203207
ccv_nnc_hint_t hint_auto = {};
204208
// 0-dim is reserved for channels
205-
for (i = 0; i < CCV_NNC_MAX_DIM; i++)
209+
for (i = 0; i < size_nd; i++)
206210
{
207211
// Cannot have one of the dim is zero, we cannot auto the hint, return no hint.
208212
assert(a.dim[i + hw] && b.dim[i + hw]);

lib/nnc/ccv_nnc_easy.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -317,16 +317,16 @@ static inline void ccv_nnc_tensor_view_get_stride(const ccv_nnc_tensor_view_t* c
317317
int x;
318318
const int nd = ccv_nnc_tensor_nd(tv->info.dim);
319319
const int offset = ccv_max(CCV_NNC_MAX_DIM + 2 - nd, 0);
320-
stride[CCV_NNC_MAX_DIM + 2] = 0;
320+
stride[ccv_max(nd, CCV_NNC_MAX_DIM + 2)] = 0;
321321
if (CCV_IS_TENSOR_VIEW(tv))
322322
{
323-
for (x = offset; x < CCV_NNC_MAX_DIM + 2; x++)
323+
for (x = offset; x < ccv_max(nd, CCV_NNC_MAX_DIM + 2); x++)
324324
stride[x] = tv->stride[x - offset];
325325
for (x = 0; x < offset; x++)
326326
stride[x] = stride[offset];
327327
} else {
328328
int cstride = 1;
329-
for (x = CCV_NNC_MAX_DIM + 1; x >= offset; x--)
329+
for (x = ccv_max(CCV_NNC_MAX_DIM + 1, nd - 1); x >= offset; x--)
330330
{
331331
stride[x] = cstride;
332332
cstride *= tv->info.dim[x - offset];

lib/nnc/ccv_nnc_internal.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@ static inline void ccv_nnc_hint_tensor_forward(const ccv_nnc_cmd_param_t cmd, co
6262
assert(nd == CCV_NNC_MAX_DIM + 1 || nd == CCV_NNC_MAX_DIM + 2);
6363
int hw = ccv_nnc_tensor_hw(a, nd);
6464
assert(hw >= 0);
65-
for (i = 0; i < CCV_NNC_MAX_DIM; i++)
65+
const int size_nd = ccv_nnc_tensor_nd(cmd.size.dim) - 1;
66+
assert(size_nd == 2 || size_nd == 3); // Support 3D convolution.
67+
for (i = 0; i < size_nd; i++)
6668
{
6769
int stride = ccv_max(1, hint.stride.dim[i]);
6870
b->dim[i + hw] = (a.dim[i + hw] + hint.border.begin[i] + hint.border.end[i] - cmd.size.dim[i]) / stride + 1;
@@ -77,7 +79,9 @@ static inline void ccv_nnc_hint_tensor_backward(const ccv_nnc_cmd_param_t cmd, c
7779
assert(nd == CCV_NNC_MAX_DIM + 1 || nd == CCV_NNC_MAX_DIM + 2);
7880
int hw = ccv_nnc_tensor_hw(a, nd);
7981
assert(hw >= 0);
80-
for (i = 0; i < CCV_NNC_MAX_DIM; i++)
82+
const int size_nd = ccv_nnc_tensor_nd(cmd.size.dim) - 1;
83+
assert(size_nd == 2 || size_nd == 3); // Support 3D convolution.
84+
for (i = 0; i < size_nd; i++)
8185
{
8286
int stride = ccv_max(1, hint.stride.dim[i]);
8387
b->dim[i + hw] = (a.dim[i + hw] - 1) * stride - hint.border.begin[i] - hint.border.end[i] + cmd.size.dim[i];

0 commit comments

Comments
 (0)