这种类型的代码有效的单线程调度是什么? 我正在尝试定义模糊,但在AOT中使用可变内核大小。我尝试了https://github.com/halide/Halide/issues/180解决方案,但是我无法想出一个好的方法来安排它,这会让我获得与使用GeneratorParam并使用不同值编译内核大小相同的性能。
以下是GeneratorParam的代码段:
// GeneratorParam<int32_t> kernelSize{"kernelOffset", 1};
int32_t kernelSize = 2*kernelOffset + 1;
{
Halide::Expr sum = input(x, y);
for (int i=1;i<kernelSize;i++) {
sum = sum + Halide::cast<uint16_t>(input(x, y+i));
}
blur_y(x, y) = sum/kernelSize;
}
{
Halide::Expr sum = blur_y(x, y);
for (int i=1;i<kernelSize;i++) {
sum = sum + blur_y(x+i, y);
}
blur_x(x, y) = sum/kernelSize;
}
...
// And the schedule
blur_x.compute_root();
blur_y.compute_at(blur_x, y);
output.vectorize(x, 16);
并使用https://github.com/halide/Halide/issues/180解决方案
Halide::RDom box (0, kernelSize, "box");
blur_y(x, y) = Halide::undef<uint16_t>();
{
Halide::RDom ry (yMin+1, yMax-yMin, "ry");
blur_y(x, yMin) = Halide::cast<uint16_t>(0);
blur_y(x, yMin) += Halide::cast<uint16_t>(input(x, yMin+box))/kernelSize;
blur_y(x, ry) = blur_y(x, ry-1) + input_uint16(x, ry+kernelOffset-1)/kernelSize - input_uint16(x, ry-1-kernelOffset)/kernelSize;
}
blur_x(x, y) = Halide::undef<uint16_t>();
{
Halide::RDom rx (xMin+1, xMax-xMin, "rx");
blur_x(xMin, y) = Halide::cast<uint16_t>(0);
blur_x(xMin, y) += blur_y(xMin+box, y)/kernelSize;
blur_x(rx, y) = blur_x(rx-1, y) + blur_y(rx+kernelOffset, y)/kernelSize - blur_y(rx-1-kernelOffset, y)/kernelSize;
}
答案 0 :(得分:2)
在固定半径和可变半径之间获得相同速度的唯一方法是使用specialize调度指令为特定半径生成固定代码。如果你可以JIT并且在相同的半径上模糊很多像素,那么对于给定半径的JIT特定滤波器可能是有利可图的。
通常非常快,任意半径,模糊使用自适应方法,其中大半径由迭代盒滤波处理,中间级别使用可分离卷积和非常小的半径可以使用不可分离卷积。模糊通常在结合多种方法的多次通过中完成。