C ++数组到Halide Image(和返回)

时间:2015-06-26 00:37:31

标签: c++ halide

我开始使用Halide,虽然我已经掌握了其设计的基本原则,但我仍然在努力处理(读取:魔术)所需的细节有效地安排计算。

我已经发布了一个使用Halide将阵列从一个位置复制到另一个位置的MWE。我原以为这会编译成只有少数几个指令,运行时间不到一微秒。相反,它产生4000行装配,运行时间为40ms!因此,显然,我的理解存在重大漏洞。

  1. Halide::Image
  2. 中包装现有数组的规范方法是什么?
  3. 如何安排函数copy以有效执行复制?
  4. 最小工作示例

    #include <Halide.h>
    
    using namespace Halide;
    
    void _copy(uint8_t* in_ptr, uint8_t* out_ptr, const int M, const int N) {
    
        Image<uint8_t> in(Buffer(UInt(8), N, M, 0, 0, in_ptr));
        Image<uint8_t> out(Buffer(UInt(8), N, M, 0, 0, out_ptr));
    
        Var x,y;
        Func copy;
        copy(x,y) = in(x,y);
        copy.realize(out);
    }
    
    int main(void) {
        uint8_t in[10000], out[10000];
        _copy(in, out, 100, 100);
    }
    

    编译标志

    clang++ -O3 -march=native -std=c++11 -Iinclude -Lbin -lHalide copy.cpp
    

2 个答案:

答案 0 :(得分:2)

让我从第二个问题开始:_copy需要很长时间,因为它需要将Halide代码编译为x86机器代码。 IIRC,Func缓存机器代码,但由于copy_copy本地的,因此缓存无法重用。无论如何,调度copy非常简单,因为它是一个逐点操作:首先,对它进行矢量化可能是有意义的。其次,并行化它可能是有意义的(取决于有多少数据)。例如:

  

copy.vectorize(x,32).parallel(y);

将沿着x向量化,向量大小为32,并沿y并行化。 (我是从记忆中做出来的,可能会对正确的名称产生一些混淆。)当然,做这一切也可能会增加编译时间......

没有良好调度的方法。我通过查看compile_to_lowered_stmt的输出并分析代码来实现。我还使用Halide::Generator提供的AOT编译,这确保我只测量代码的运行时而不是编译时。

您的另一个问题是,如何在Halide::Image中包装现有数组。我不这样做,主要是因为我使用AOT编译。但是,内部Halide使用名为buffer_t的类型来处理与图像相关的所有内容。还有一个名为Halide::Buffer的C ++包装器使buffer_t更容易使用,我认为它也可以在Func::realize而不是Halide::Image中使用。重点是:如果你理解buffer_t,你几乎可以将所有东西都包裹在Halide可以消化的东西中。

答案 1 :(得分:1)

要强调弗洛里安提到的第一件事,我认为这是误解的关键点:你似乎正在计算copy操作的编制时间(“管道”,常见的Halide术语),而不仅仅是它的执行。你的代码大小估计大概也是由copy.cpp产生的整个二进制文件,而不仅仅是Halide生成的copy函数中的代码(实际上它甚至不会出现在你正在编译的二进制文件中) clang,因为它只是在运行时通过JITing构建的。)

您可以在copy.compile_jit()之前调用realize来观察您的管道的实际费用(realize在第一次运行时隐式调用compile_jit,所以它不是必要的,但将运行时与编译开销分开是很有价值的。然后,您可以将计时器专门置于realize

如果你真的想预先编译这个(或任何其他)管道以便静态链接到你的终极程序,这可能是你期望的,你真正想要做的就是使用Func::compile_to_file一个编译和发出代码的程序(如copy.hcopy.o),然后在另一个程序中链接和调用它们。查看教程第10课以更详细地了解这一点:

https://github.com/halide/Halide/blob/master/tutorial/lesson_10_aot_compilation_generate.cpp https://github.com/halide/Halide/blob/master/tutorial/lesson_10_aot_compilation_run.cpp