【发布时间】: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<Buffer<uint8_t>> 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:
解决了避免外部调用的任务,用 argmin 和 RDom 组合替换 while 循环,但关于外部的原始问题仍然存在
【问题讨论】:
标签: halide