C++数组到Halide Image(和背面)
C++ array to Halide Image (and back)
我刚开始使用Halide,虽然我已经掌握了它设计的基本原理,但我正在努力解决高效调度计算所需的细节(读作:魔术)。
我在下面发布了一个使用Halide将数组从一个位置复制到另一个位置的MWE。我曾以为这只会编译成少数指令,运行时间不到一微秒。相反,它生产了4000条装配线,运行需要40毫秒!因此,很明显,我的理解有一个很大的漏洞。
- 在
Halide::Image
中包装现有数组的规范方式是什么 - 应该如何安排函数
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
让我从您的第二个问题开始:_copy
需要很长时间,因为它需要将Halide代码编译为x86机器代码。IIRC,Func
缓存机器代码,但由于copy
是_copy
的本地缓存,因此无法重用该缓存。无论如何,调度copy
是非常简单的,因为它是一个逐点操作:首先,将其矢量化可能是有意义的。其次,将其并行化可能有意义(取决于数据量)。例如:
copy。vectorize(x,32)。parallel(y);
将以32的向量大小沿CCD_ 8进行矢量化并沿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可以消化的东西。
为了强调Florian提到的第一件事,我认为这是这里误解的关键点:您似乎在为copy
操作(常见的Halide术语中的"管道")的编译计时,而不仅仅是它的执行。您的代码大小估计可能也是针对copy.cpp
产生的整个二进制文件,而不仅仅是Halide生成的copy
函数中的代码(它实际上甚至不会出现在您使用clang编译的二进制文件中,因为它只是由JITing在该程序的运行时构建的)。
通过在realize
之前先调用copy.compile_jit()
,可以观察到管道的实际成本(realize
在第一次运行时隐式调用compile_jit
,因此没有必要,但将运行时与编译开销分开是很有价值的)。然后,您可以将计时器完全设置在realize
附近。
如果你真的想预编译这个(或任何其他)管道,以便静态链接到你的最终程序中,这似乎是你所期望的,那么你真正想做的是在一个程序中使用Func::compile_to_file
来编译和发出代码(如copy.h
和copy.o
),然后在另一个程序中将它们链接和调用。查看教程第10课,了解更多详细信息:
https://github.com/halide/Halide/blob/master/tutorial/lesson_10_aot_compilation_generate.cpphttps://github.com/halide/Halide/blob/master/tutorial/lesson_10_aot_compilation_run.cpp
- 以线程安全的方式调用"QQuickPaintedItem::updateImage(const QImage&image)"(no QThread)
- Inference pytorch C++ with alexnet and cv::imread image
- 如何在QTextEdit中添加URL或IMAGE-URL
- JNA 将 HICON 转换为 Java Image
- 如何在c++中将image.jpg转换为image.ppm
- Magick++ Blob to Image Error
- 将带有零的 Mat 内核填充到 Image 的大小
- 运行"OpenPose C++ API Tutorial - Example 3 - Body from image"失败
- magick 对magick :: image :: columns的未定义引用
- 通过QT WebSocket将OpenCV Mat Image发送到HTML客户端
- OpenCV Image Mat to 1D CHW(RR...R, GG..G, BB..B) vector
- 如何使用由 PNG 数据构建的 blob 初始化 Magick::Image obj(PNG 由 cv::imencod
- C++ 我的函数在我的 Image 类中工作,但不在主例程中工作
- 从标准::basic_string撰写cv::Mat <char>Image
- (gtk:4783): gtk-关键**: gtk_image_set_from_pixbuf: 断言'GTK_IS_IMAGE (image)'失败
- "The image cannot be displayed error"通过套接字发送图像时C++
- 容器正面和背面行为
- PE 中的"Isolated Image"属性是什么?
- rosserial publish sensor_msgs/Image from windows
- C++数组到Halide Image(和背面)