2017-06-19 29 views
0

这种类型的代码将是一个有效的单线程调度? 我想定义模糊,但在AOT中的可变内核大小。我尝试了https://github.com/halide/Halide/issues/180解决方案,但我无法找到一个安排它的好方法,它可以让我获得与使内核大小为GeneratorParam并预编译不同值的性能相同的性能。如何使可变内核大小的高性能AOT模糊?

这里是与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

你能写出你试过的日程安排吗?与没有明确的日程安排相比,它的运行速度是多少? –

+0

具有固定内核大小的版本运行在6.56348e-05s,没有时间表和1.97556e-05s与指定的时间表。 可变内核版本在1.10882秒运行,没有时间表和0.0026933秒,与另一个时间表相同。 – Fran6co

回答

2

得到固定和可变半径之间的相同速度的唯一方法是使用在specialize调度指令为特定半径生成固定代码。如果您可以进行JIT并以相同的半径模糊大量像素,则可以为特定半径的JIT指定一个特定的滤镜。

一般来说,真正快速,任意的半径,模糊使用自适应方法,其中大半径由迭代框过滤等处理,中间级使用可分卷积,而非常小的半径可能使用不可分卷积。模糊通常是通过多次合并多种方法完成的。