【问题标题】:Halide external function call from generator来自生成器的卤化物外部函数调用
【发布时间】:2019-08-28 10:05:43
【问题描述】:

我想实现与自动级别非常相似的简单图像处理例程,因此需要预先计算阈值,制作 LUT,然后应用 LUT 进行直方图拉伸/归一化。

但我的问题不是关于算法方面,而是关于使用外部定义的函数,因为我需要几个 while 循环来计算 LUT,我认为使用外部对它有好处。

我尝试了以下来自 Halide 来源的示例并检查了 this question

我使用AOT编译,目前在PC(winx64)上测试,未来瞄准arm,生成器代码如下:

    Var x("x"), y("y");
    Func make_a_root{ "make_a_root" };

    Buffer<bitType>  Lut{256, "lut"};

    make_a_root(x, y) = inputY(x, y);
    ExternFuncArgument arg = make_a_root;

    Func g;
    g.define_extern("generateAutoLevelsLut", { arg }, UInt(8), 2, Halide::NameMangling::CPlusPlus);

    g.compute_root();

inputY 有Input&lt;Buffer&lt;uint8_t&gt;&gt; inputY{ "input_y", 2 }; 类型

首先我只想让它运行调用,所以函数体除了打印什么都不做(我可以在同一个 cpp 文件中定义函数作为生成器吗?)

int generateAutoLevelsLut(halide_buffer_t * input, halide_buffer_t * out)
{
    printf("\nextern call\n");
    return 0;
}

我也尝试使用 extern "C" 进行默认修改。

虽然从未成功获得打印消息,所以我的问题是,为什么会发生这种情况。只是对某些语法有误解,还是从生成器代码调用 extern 函数有什么问题?

编辑:

添加了extern like 'out(x,y) = g(x,y)' (lvalue 应该是实际使用的!) 的用法,它开始调用。现在在主机 == NULL 上苦苦挣扎。深入研究边界推理的东西。

编辑 2:

我添加了基本的边界推断检查,现在它不会崩溃。我现在遇到的下一个问题是:是否可以调用外部函数,而不会直接影响输出结果?

让我具体说明一下我的意思。

生成器代码如下所示:

    Buffer<bitType> lut{256, "lut"};

    args[0] = inputY;
    args[1] = lut;

    g.define_extern("generateAutoLevelsLut", args, { UInt(8) }, 2, Halide::NameMangling::C);

    outputY(x, y) = g(x, y); // Call line

    g.compute_root();
    outputY.compute_root();

外部函数代码用一些虚拟 LUT 填充第二个输入“lut”:

    Halide::Runtime::Buffer<uint16_t> im2Buffer(*input2);
    Mat im2Mat(Size(im2Buffer.width(), im2Buffer.height()), CVC_8U, im2Buffer.data(), im2Buffer.stride(1));

    for (int i = 0; i < 256; i++)
        im2Mat.at<uchar>(i) = i;

如果我在生成器中评论“呼叫行”,它会完全优化对 extern 的调用。 我想做类似的东西:

    Func lutRoot;
    lutRoot(x) = lut(x); // to convert from Buffer
    outputY(x, y) = autoLevelsPrecalcLut(inputY, lutRoot)(x, y);

这里 lut 被隐式传递给 extern 并在那里填充。但它不起作用,以及其他忽略“输出”修改的变体......或者整个方法可能是错误的? 有什么建议么?谢谢

编辑 3:

解决了避免外部调用的任务,用 argminRDom 组合替换 while 循环,但关于外部的原始问题仍然存在

【问题讨论】:

    标签: halide


    【解决方案1】:

    这应该可以工作(或者如果不工作,则会因链接器错误而失败)。 Halide 管道可能认为它不需要调用您的 extern 函数。例如。有什么东西使用结果吗?

    或者,尝试使用 stderr,以防万一这是输出流缓冲问题。该 extern 函数定义可能会导致 Halide 出错(因为它不回复边界推理查询),并且默认情况下出错调用 abort,这会吞噬打印到 stdout 的内容。

    【讨论】:

    • “Halide 管道可能不认为它需要调用你的外部函数”>> 这个。我添加了实际使用函数结果的代码,现在它运行了!在我看来,compute_root 有点强迫事情按计划进行,但这显然是不正确的。想知道调试模式是否具有相同的行为?我现在有另一个问题,输出的主机指针为空..现在解决这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-17
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 2019-02-22
    相关资源
    最近更新 更多