1

我开始使用 Halide,虽然我已经掌握了它设计的基本原则,但我正在努力解决有效安排计算所需的细节(阅读:魔法) 。

我在使用 Halide 将数组从一个位置复制到另一个位置的 MWE 下方发布。我曾假设这将编译成只有少数指令,并且运行时间不到一微秒。相反,它产生了 4000 条装配线,运行时间为 40 毫秒!因此,很明显,我的理解存在重大漏洞。

  1. 将现有数组包装在 a 中的规范方法是Halide::Image什么?
  2. 应该如何安排函数copy以有效地执行复制?

最小的工作示例

#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
4

2 回答 2

2

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

复制.vectorize(x, 32).parallel(y);

x将与 32 的向量大小一起进行向量化并沿并行化y。(我是凭记忆编造的,可能对正确的名称有些混淆。)当然,这样做也可能会增加编译时间......

没有好的调度方法。我通过查看代码的输出compile_to_lowered_stmt和分析代码来做到这一点。我也使用 提供的 AOT 编译Halide::Generator,这确保我只测量代码的运行时间而不是编译时间。

您的另一个问题是,如何将现有数组包装在Halide::Image. 我不这样做,主要是因为我使用 AOT 编译。但是,在内部,Halide 使用了一种类型buffer_t,用于与图像相关的所有内容。还有一个叫做 C++ 包装器Halide::Buffer,它使使用buffer_t更容易一些,我认为它也可以用于Func::realize代替Halide::Image. 关键是:如果你理解的buffer_t话,你可以将几乎所有东西都包装成卤化物可以消化的东西。

于 2015-06-29T07:51:11.200 回答
1

强调弗洛里安提到的第一件事,我认为这是误解的关键点:您似乎是在计时copy操作的编译(“管道”,在常用的 Halide 术语中),而不仅仅是它的执行。您的代码大小估计可能也适用于由 生成的整个二进制文件copy.cpp,而不仅仅是 Halide 生成copy函数中的代码(实际上它甚至不会出现在您使用 clang 编译的二进制文件中,因为它仅由 JITing 在此程序中的运行时)。

您可以通过在此copy.compile_jit()之前先调用来观察管道的实际成本realize(在第一次运行时realize隐式调用compile_jit,因此没有必要,但将运行时与编译开销分开是很有价值的)。然后你会专门把你的计时器放在realize.

如果您确实想预编译此(或任何其他)管道以将静态链接到您的最终程序中,这似乎是您所期望的,那么您真正想要做的是Func::compile_to_file在一个程序中使用来编译和发出代码(as copy.hand copy.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

于 2015-07-02T01:40:45.107 回答