【问题标题】:Is there any way to combine Funcs into a Func has one more dimension?有没有办法将 Func 组合成一个具有更多维度的 Func?
【发布时间】:2017-04-02 13:27:43
【问题描述】:

我从上个月开始学习卤化物。 终于遇到了大问题。

我正在尝试在 Halide 中实现类似 C 类代码的功能。

for( int y = 0; y < 3; ++y ){
    for( int x = 0; x < 3; ++x ){
        out(x, y) = out(x-1, y-1) + 1;
    }
}

所以假设初始图像如下。

0 0 0
0 0 0
0 0 0

输出图像将是……(0 超出范围)

1 1 1
1 2 2
1 2 3

所以我想到了两种可能的解决方案。

・解决方案1

将上述算法定义为这样的递归函数。

Func algorithm1(Func input, int n)
{
    Func src, clamped, dst;
    Var x, y;

    if(n == 1){
            src = input;
    }else{
            src = algorithm1(input, n-1);
            src.compute_root();
    }

    clamped = BoundaryConditions::constant_exterior(src, 0, 0, SIZE, 0, SIZE);
    dst(x, y) = clamped(x-1, y-1) + 1;

    return dst;
}

并像下面的代码一样使用上面的函数。

Func input, output;
input(x, y) = src(x, y);
output = algorithm1(input, SIZE);
output.realize(src);

这个实现几乎没有用。但显然是退票。 因为每个阶段(Func)的大部分计算结果都与最终结果不匹配,尽管每个 Func 都在整个图像上进行计算。 我需要处理更多的大(正常)图像。 所以我想到了另一种可能的解决方案。

・解决方案2

第二个解决方案的第一个。
声明一个函数来定义一列和另一列之间的关系。

Func algorithm2(Func src)
{
    Func clamped, dst;
    Var x;

    clamped = BoundaryConditions::constant_exterior(src, 0, 0, SIZE);
    dst(x) = clamped(x-1) + 1;

    return dst;
}

那么,让我们把这个结合起来吧。

Func output[3];
output[0](x) = cast<uint32_t>(0);
for(int i = 1; i < SIZE; ++i){
    output[i] = algorithm2(output[i-1]);
}

好吧...问题来了。如何将这组 Func 组合成一个 Func?

当然,如果我在每个函数中实现这个函数数组指向列头的指针,我可以获得一个图像。但是如果我想将它传递给下一个 Func 怎么办?

这些天,我查看了整个 Halide 示例(测试、应用程序)。但我认为没有类似的例子。 你可能已经注意到我对英语的不适,实际上我是日本人。所以如果有这个问题的有用例子,我很抱歉提前。如果是这样,请告诉我它在哪里。如果还有其他好的实现思路,请教我。无论如何,我需要别人的帮助!

感谢您的阅读。

[编辑 2]

edit 1 是我的愚蠢问题。我可以安排它compute_root()。 我决定把它们留在这里,虽然真的很尴尬。 我希望这对另一个愚蠢的人有所帮助。

[编辑 1]

衷心感谢您快速而详细的回复!

很抱歉回复晚了,我想在成功实现我的算法后回复你。但是,我的 Halide 代码仍然无法正常工作,并且需要确认一些事情。

首先,我想告诉你,感谢你,我意识到我对 Halide 的误解。在我的算法实现步骤的第一步,我只使用纯“Var”来编写定义。 所以我得到了以下错误。

All of a functions recursive references to itself must contain the same pure variables in the same places as on the left-hand-side.

我认为发生此错误是因为日程安排的灵活性。如果允许这样的定义并且调度它分裂,这意味着调度改变算法。这种理解正确吗?从这样的理解来看,虽然我已经阅读了教程和模糊示例的缩减部分,但我误解了我无法访问所有 Func 定义中的相邻像素。我不知道为什么。

由于同样的原因,无法拆分归约域。我想我现在明白了。

这是您的代码的另一个问题。感谢您的 Halide 实施示例,我几乎成功地实施了我想做的事而不加考虑。但是,尽管我正在处理 20x20 的裁剪图像以便于调试,但这个实现速度非常慢。

我认为这种缓慢是由缩减域引起的。在您的示例中,例如在计算值 g(10, 10) 时,卤化物计算被安排从 f(0, 0) 到 f(0, 0) 并最终获得该值。另一方面,C 实现只是加载 g(9, 9) 处的值并增加它。我们可以通过打印循环嵌套来确认这样的计算。

produce g:
  for y:
    for x:
      produce f:
        for y:
          for x:
            f(...) = ...
        for range:
          for range:
            f(...) = ...
      consume f:
        g(...) = ...

我想确认避免这种重新计算是不可能的?所以你建议的?

我想问你另一个简单的问题。如果有这样的反向依赖,

for( int y = 2; y > 0; --y ){
    for( int x = 2; x > 0; --x ){
        out(x, y) = out(x+1, y+1) + 1;
    }
}

Halide 能表达这个代码吗?

【问题讨论】:

    标签: halide


    【解决方案1】:

    这里的 algorithm1 和 algorithm2 部分对我来说不是很清楚。我理解最初的问题陈述并且英语似乎很好,所以我会努力提供一些帮助来回答我认为你所问的问题。我将通过说明一些您可能不知道或在这里使用不明显的卤化物机制来做到这一点。希望这会有所帮助。

    首先,要将 Halide Func 的维度映射到不同的表达式,您几乎必须使用 select 语句:

    Var x, y, n;
    Func f_0, f_1, f_both;
    f_0(x, y) = ...;
    f_1(x, y) = ...;
    f_both(x, y, n) = select(n == 0, f_zero, f_one);
    

    这可以通过向select 添加参数扩展到更多情况。这对于分段计算比递归结构更有用,但似乎是对标题中问题的最直接答案。

    第二种机制是Tuple。这允许 Func 具有多个值,可以使用编译时常量对其进行索引。我认为这不是您正在寻找的答案,但我已在 tutorial/lesson_13_tuples.cpp 中找到答案。

    最后,Halide 支持归约,旨在处理第一个代码示例中的情况。看起来像这样:

    Var x, y;
    Func f, g;
    RDom range(0, 3, 0, 3); // Form is min/extent, not start/end
    
    f(x, y) = 0; // Initial condition
    f(range.x, range.y) = f(range.x - 1, range.y - 1) + 1;
    
    g(x, y) = f(x, y);
    
    Buffer<int32t> result = g.realize(3, 3);
    

    这应该会产生第一个示例的输出。 tutorial/lesson_09_update_definitions.cpp 中介绍了减少或“更新定义”。

    【讨论】:

    • 我在另一个答案上给你写了一个回复,因为它太长了。我在等你的回复:D
    • 我刚刚意识到我可以编辑初始帖子。回复在 [edit1]
    • 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊。我很抱歉。无论如何,由于您的实施想法,我终于成功实施了我想做的事情。非常感谢你。卤化物太棒了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-09
    • 2019-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-02
    相关资源
    最近更新 更多