halide 入门实战(1)

简介

	MIT计算机科学和人工智能实验室(CSAIL)的研究人员开发了一门名为“ Hlaide”的新的编程语言,旨在更高效的编写高性能,
	可移植性强的图像或者向量处理语言。它是用C++作为宿主语言的一个图像处理相关的DSL(Domain Specified Language)语言,
	全程领域专用语言。Halide设计的核心思想是将算法的内容和算法的执行耦,这样程序员可以根据不同的设备设置不同的优化策略,
	获得更高质量的代码。
	[英文教程](https://halide-lang.org/tutorials/tutorial_introduction.html)
	[API查询](https://halide-lang.org/docs/)
	[源码编译](https://github.com/halide/Halide)

特性

1.运行模式

JIT模式

	JIT模式使用起来比较方便,可以直接将算法和Halide的代码生成generator封装成一个类,在程序的其他部分
	调用这个类即可。

AOT模式

	在嵌入式环境和交叉编译环境下一般使用AOT模式,此时需要调用compiler函数将算法代码和Halide的
	代码生成generator编译位目标机器的代码,生成一个.o目标文件和.h头文件。然后在独立的目标机器的
	应用的工程的源代码中通过头文件调用算法实现的计算函数,并在build的时候链接上.o文件,这样就得
	到一个可以在目标机器上运行的用Halide实现算法的程序了。

2. 支持平台

  1. CPU体系结构:X86,ARM,MIPS,Hexagon,PowerPC;
  2. 操作系统:Linux,Windows,macOS,Android,iOS,Qualcomm QuRT;
  3. GPU计算API:CUDA,OpenCL,OpenGL,OpenGL计算着色器,Apple Metal,Microsoft Direct X 12。

3. 功能实现

	Halide将代码分为Algorithm和Schedule两部分。
        1. Algorithm部分仅仅描述算法的功能;
		2. Schedule部分指定算法在何时何处以某种方式进行计算。

4.优化方法

	主要使用方法有Reorder(交换)、Split(拆分)、Fuse(融合)、Tile(平铺)、Vector(向量化)、展开(Unrolling)、并行(Parallelizing),
		集合这些方法可以实现缓存一致性强、并行度高、额外开销少的图像处理程序。

基本语法

Algorithm

Halide::Func 对应图像流水线处理中的一个步骤。这个func定义了一个图像中每一个像素应该是什么值。这里只是一个定义。eg. blur, brighten, harris.
Halide::Var 用于定义func的变量,该专用语言的抽象变量。eg. x, y, c.
Halide::Expr 用于定义一个算术表达式,可以包含Func和Var。包含标准的算术运算法和函数(+,-,*,/,**,sqrt, sin, cos,...)
Halide::cast 强制类型转换。
Halide::min
Halide::Buffer用于定义缓存

Schedule

 Reorder(交换)、Split(拆分)、Fuse(融合)、Tile(平铺)、Vector(向量化)、展开(Unrolling)、并行(Parallelizing)。

Debug方式

	_.compile_to_lowered_stmt("_.html", {}, HTML): 中间结果生成html预览;
	trace_stores: 跟踪执行过程;
	print, print_when:打印变量值;
	_.print_loop_nest(): 将调度的伪代码打印出来;
	[更多debug方式](https://halide-lang.org/tutorials/tutorial_lesson_04_debugging_2.html)

实战—示例

void blur3x3_with_halide(const std::string& src_path, const std::string& dst_path)
{
	//load
	Halide::Buffer<uint8_t> input = Halide::Tools::load_image(src_path);
	const int src_w = input.width();
	const int src_h = input.height();

	//check
	Halide::Func src_image;
	src_image = Halide::BoundaryConditions::repeat_edge(input);
	

	Func blur_x("blur_x"), blur_y("blur_y");
	Var x, y, xi, yi;

	Func src_image_16;
	src_image_16(x, y) = cast<uint16_t>(src_image(x, y));

	// The algorithm - no storage or order
	blur_x(x, y) = (src_image_16(x - 1, y) + src_image_16(x, y) + src_image_16(x + 1, y));
	blur_y(x, y) =  ((blur_x(x, y - 1) + blur_x(x, y) + blur_x(x, y + 1)) / 9);

	Func output("output");
	output(x, y) = cast<uint8_t>(blur_y(x, y));
	Halide::Buffer<uint8_t> result{ src_w, src_h};

	// The schedule - defines order, locality; implies storage
	//result.set_min(1, 1);
	blur_y.compute_root();
	blur_y.tile(x, y, xi, yi, 256, 32).vectorize(xi, 8).parallel(y);
	blur_x.compute_at(blur_y, x).vectorize(x, 8);

	for (int i = 0; i < 50; i++)
	{
		int64 start = cv::getTickCount();
		output.realize(result);
		std::cout << (cv::getTickCount() - start) * 1000 /(cv::getTickFrequency()) << "[ms]" << std::endl;
	}
	
	Halide::Tools::save(result, dst_path);
}


注意:1. Halide::Tools,要使用第三方库等。
      2. 使用JIT模式,第一次运行耗时较长。

参考文献:
1.https://halide-lang.org/
2.https://zhuanlan.zhihu.com/p/346468141
3.https://www.jianshu.com/p/295351839a2b
4.https://www.freesion.com/article/27311335364/

你可能感兴趣的:(halide,opencv,人工智能,深度学习)