在Halide中使用split()时可以避免计算相同的元素吗?

在Halide中使用split()时可以避免计算相同的元素吗?,halide,Halide,我有一个关于split()在卤化物语言中的行为的问题 当我使用split()时,当计算区域不是分割因子的倍数时,它会在边缘计算元素两次。例如,当计算区域为10且分割因子为4时,Halide将计算元素[0,1,2,3]、[4,5,6,7]和[6,7,8,9],就像下面跟踪存储()的结果一样 在split()的内部循环的最后一步中,是否有方法只计算元素[8,9] 示例代码: #include "Halide.h" using namespace Halide; #define INPUT_SIZE

我有一个关于split()在卤化物语言中的行为的问题

当我使用split()时,当计算区域不是分割因子的倍数时,它会在边缘计算元素两次。例如,当计算区域为10且分割因子为4时,Halide将计算元素[0,1,2,3]、[4,5,6,7]和[6,7,8,9],就像下面跟踪存储()的结果一样

在split()的内部循环的最后一步中,是否有方法只计算元素[8,9]

示例代码:

#include "Halide.h"
using namespace Halide;

#define INPUT_SIZE 10
int main(int argc, char** argv) {
    Func f("f");
    Var x("x");
    f(x) = x;

    Var xi("xi");
    f.split(x, x, xi, 4); 

    f.trace_stores();
    Image<int32_t> out = f.realize(INPUT_SIZE);
    return 0;
}

这是可能的,但很难看。Halide通常假设它可以任意重新计算Func中的点,并且输入不会与输出混淆,因此在边缘附近重新计算一些值总是安全的

这一点很重要,这是一个坏迹象。也许还有其他方法可以实现你想要做的事情

无论如何,解决方法是使用显式RDOM精确地告诉Halide要迭代什么:

// No pure definition
f(x) = undef<int>(); 

// An update stage that does the vectorized part:
Expr w = (input.width()/4)*4;
RDom r(0, w);
f(r) = something;
f.update(0).vectorize(r, 4);

// An update stage that does the tail end:
RDom r2(input.width(), input.width() - w);
f(r2) = something;
f.update(1); // Don't vectorize the tail end
//没有纯粹的定义
f(x)=未定义();
//执行矢量化部分的更新阶段:
Expr w=(input.width()/4)*4;
rdomr(0,w);
f(r)=某物;
f、 更新(0)。矢量化(r,4);
//完成尾端的更新阶段:
RDom r2(input.width(),input.width()-w);
f(r2)=某物;
f、 更新(1);//不要矢量化尾端

您能说说为什么需要避免额外的存储集吗?我在想,当我使用单核CPU时,是否可以利用tile()时间表。当最佳分幅大小不是输入数据的除数时,我认为在这种情况下应该减少额外的计算。额外的工作只发生在边缘分幅中,目标是使非边缘分幅更快。对于矢量化,它甚至不一定是额外的工作,因为您无论如何都需要处理边值,而且矢量化方法通常与边缘的规模化具有相同或更低的成本。更大的担忧是,如果Halide无法证明平铺与正在处理的最小/范围对齐,它必须插入处理任何可能对齐的代码。一个简单的改进方法是断言最小值为0或最小值与平铺大小对齐。
// No pure definition
f(x) = undef<int>(); 

// An update stage that does the vectorized part:
Expr w = (input.width()/4)*4;
RDom r(0, w);
f(r) = something;
f.update(0).vectorize(r, 4);

// An update stage that does the tail end:
RDom r2(input.width(), input.width() - w);
f(r2) = something;
f.update(1); // Don't vectorize the tail end