在 Halide 中混合 int 和 float

Mixing int and float in Halide

我在 VS2013 中使用 Halide。我已经成功构建 运行 第一个教程。

我正在尝试实现我的一些代码,但不明白为什么它无法编译。代码如下:

int main(int argc, char **argv) {

ImageParam input(UInt(8), 3);

Func input_clamped = BoundaryConditions::repeat_edge(input);
Var x, y, c;

Func float_input_clamped;
float_input_clamped(x, y, c) = cast<float>(input_clamped(x, y, c)) / 255.0f;

Func input_lum;
input_lum(x, y) = cast<float>(0.299f * float_input_clamped(x, y, 0) + 0.587f * float_input_clamped(x, y, 1) + 0.114f * float_input_clamped(x, y, 2));

Func m45;
m45(x, y) = fabsf(input_lum(x - 1, y) - input_lum(x, y + 1)) + fabsf(input_lum(x, y + 1) - input_lum(x + 1, y + 2));

return 0;
}

错误发生在 m45(x, y) = ... 行。显然, input_lum 不被视为浮点值。错误信息是 "no suitable conversion from Halide::Expr to float exists."

显然所有的转换和浮点数学都被忽略了。

(我知道我还没有初始化输入——我正在尝试理解我在编写 Halide 代码时的思考方式,而类型推断正适合我。)

我做错了什么?

(如果不清楚,我只想获取 RGB 图像的亮度,并对亮度进行一些数学运算。如果可行,我很乐意保持整数 space。)

好的,我试验并尝试了这个:

ImageParam input(UInt(8), 3);

Func input_clamped = BoundaryConditions::repeat_edge(input);
Var x, y, c;

Func input_lum;
input_lum(x, y) = 0.299f * input_clamped(x, y, 0) + 0.587f * input_clamped(x, y, 1) + 0.114f * input_clamped(x, y, 2);

Func m45;
m45(x, y) = abs(input_lum(x - 1, y) - input_lum(x, y + 1)) + abs(input_lum(x, y + 1) - input_lum(x + 1, y + 2));

现在可以编译了,但我不知道它在做什么。为什么 input_lum() 的类型不是 float?

这里的混淆不是在你的 Halide 代码中混合 intfloat 表达式,而是将 Halide::Expr 与 C++ intfloat 函数混合. fabsf 是一个 C 函数,它接受 returns C 浮点值。您真正想要的是一个 Halide 内部函数,它采用浮点类型的 Halide 表达式的绝对值。在这种情况下,我相信这是 Halide::abs,正如您在第二个代码段中发现的那样。

Halide 程序的 compile/construction 时间 与此 C++ 代码的 运行- 时间之间的区别,以及 运行- Halide 程序的时间(当您调用 realize 或调用 compile_to_file 生成的函数时)是一个非常常见的早期绊脚石。如果目前你删除了任何 using namespace Halide ,那么你在显式使用像 Halide::abs 这样的 Halide 函数的地方应该会更清楚——像 ::fabsf 这样的实际标准 C 函数对 Halide::Exprs(编写 Halide 算法代码时使用的类型),因此您永远无法像在 Halide 程序中尝试的那样有意义地使用它们。为了方便起见,Halide 中的许多标准数学函数恰好与其对应的 math.h 具有相同的名称;但是,如果没有 using namespace Halide,您将被迫明确使用 Halide 函数(在这种情况下有意义),而不是 math.h 或其他函数(没有)。