1

In the filter I am implementing there is a step doing some reduction over the boundary of square domain

RDom r(0, filter_size, 0, filter_size);
r.where( (r.x == 0 || r.x == filter_size - 1) 
       || (r.y == 0 || r.y == filter_size - 1));

However this makes domain traversal O(filter_size^2) while useful reduction domain is only O(filter_size). Now my reduction operation is a bit involved, so repeating if for each side of the filter window makes quite a mess. Is there an elegant && efficient way of doing this in Halide?

Slava
  • 1,528
  • 1
  • 15
  • 23

2 Answers2

0

The code I end up using is neither very elegant nor super-efficient, so contributions are welcome...

RDom rl(0, filter_size, 0, 2, 0, 2);
Expr rlx = rl.y*rl.x + rl.z*(1 - rl.y)*filter_size;
Expr rly = (1 - rl.y)*rl.x + rl.z*rl.y*filter_size;
Expr x_on_rl = x + rlx - (filter_size+1)/2;
Expr y_on_rl = y + rly - (filter_size+1)/2;

and usage is like

range_min(x, y) = Halide::minimum(range_clamped(x_on_rl, y_on_rl));
Slava
  • 1,528
  • 1
  • 15
  • 23
0

I haven't tested this, but the general idea is to only use one dimension of the RDom at a time as needed, that way you don't have to bother traversing the interior.

RDom r(0, filter_size, 1, filter_size-1);// the y part is different because we don't want to double count the corners
output(x,y,c) = 
Binary_Reduction(Halide::<desired_reduction>(clamped_input(x + r.x, y, c)), 
Binary_Reduction(Halide::<desired_reduction>(clamped_input(x + r.x, y + filter_size -1, c)), 
Binary_Reduction(Halide::<desired_reduction>(clamped_input(x, y + r.y, c)),
                 Halide::<desired_reduction>(clamped_input(x + filter_size - 1, y + r.y, c)))));

Binary reduction is a stand-in for a reduction on a pair of expressions, like Halide::min or just any binary operation.

is a stand-in for something like Halide::minimum or Halide::sum.

Gotta double check the parentheses.