@@ -219,11 +219,37 @@ class ReductionCreator : public OpenCLBackend::Creator {
219219 return NULL ;
220220 }
221221 auto axis = reduct->dim ()->data ()[0 ];
222+ if (axis < 0 ) {
223+ axis += inputs[0 ]->buffer ().dimensions ;
224+ }
222225 int dim = inputs[0 ]->length (axis);
223226 std::vector<int > inputShape = tensorShapeFormat (inputs[0 ]);
224227 if (dim == inputShape.at (3 ) && outputs[0 ]->buffer ().dimensions == 1 ){
225228 return NULL ;
226229 }
230+ // Mirror the kernel-selection conditions in onEncode; if none matches,
231+ // no kernel computes this shape correctly, so fall back (return NULL).
232+ int inside = 1 , outside = 1 ;
233+ for (int i = 0 ; i < axis; ++i) {
234+ outside *= inputs[0 ]->length (i);
235+ }
236+ for (int i = axis + 1 ; i < inputs[0 ]->dimensions (); ++i) {
237+ inside *= inputs[0 ]->length (i);
238+ }
239+ int batch = inputShape.at (0 );
240+ int inputHeight = inputShape.at (1 );
241+ int inputWidth = inputShape.at (2 );
242+ int inputChannels = inputShape.at (3 );
243+ bool supported = (batch * inputHeight * inputChannels == outside && 1 == inside && dim == inputWidth) ||
244+ (batch * inputChannels == outside && inputWidth == inside && dim == inputHeight) ||
245+ (batch == outside && inputWidth * inputHeight == inside && dim == inputChannels);
246+ // Batch reduce is only valid when the output keeps the input rank:
247+ // dropping a dimension reinterprets the image layout and corrupts results.
248+ bool batchSupported = (1 == outside && inputWidth * inputHeight * inputChannels == inside && dim == batch) &&
249+ outputs[0 ]->buffer ().dimensions == inputs[0 ]->buffer ().dimensions ;
250+ if (!supported && !batchSupported) {
251+ return NULL ;
252+ }
227253 switch (op->main_as_ReductionParam ()->operation ()) {
228254 case ReductionType_MEAN:
229255 break ;
0 commit comments