Halide教程Part01:build、语法、调度、流水线

Halide是一个将算法与执行解耦的图像处理库。本文详细介绍了如何构建Halide,其基本语法,包括定义函数、表达式、变量等。接着探讨了调度策略,如默认顺序、变量分割、合并、循环展开、向量化和多级流水线调度。通过不同的调度示例,展示了如何根据目标机器优化执行效率。
摘要由CSDN通过智能技术生成

About Halide

Halide的核心思路不在于其能够自动优化代码,而是将 算法的内容 和 算法的执行 解耦,编写时分开编写。程序猿可以很轻松的根据具体的目标机器,设计并尝试不同的优化策略,从中选择一个最优的策略。
Halide GitHub Repo

How to build Halide

  1. 安装llvm4.0以上版本,并配置环境变量

    可以在对应系统的包管理工具下安装llvm4.0以上版本:

    $ brew search llvm
    ==> Searching local taps...
    llvm@4
    ==> Searching taps on GitHub...
    ==> Searching blacklisted, migrated and deleted formulae...

    这里macOS选择使用brew作为包管理工具。

  2. 配置环境变量

    shell工具读取的配置目录文件中添加环境变量以下两条:

    export LLVM_CONFIG="/usr/local/opt/llvm@4/bin/llvm-config"
    export CLANG="/usr/local/opt/llvm@4/bin/clang"
  3. 直接make生成库在${workpath}/bin下,头文件在${workpath}/include以及${workpath}/tools目录下。

Halide 基本语法

  • Halide 关键字

    Algorithm部分:

    • Halide::func 对应图像流水线处理中的一个步骤。这个func定义了一个图像中每一个像素应该是什么值。这里只是一个定义。
    • Halide::Var 用于定义func的变量。
    • Halide::Expr 用于定义一个表达式。
    • Halide::cast 强制类型转换。
    • Halide::min
    • Halide::Buffer<T>用于定义缓存

    Schedule部分:Vectorizeparallelizeunroll

  • Halide在定义func的时候没有真正计算每个像素点的值,只有在调用funcrealize方法时才会真正执行。

  • Halide Debug手段

    • _.compile_to_lowered_stmt("_.html", {}, HTML)可以将中间结果生成html预览。
    • trace_stores用于跟踪执行过程。
    • func中直接print部分内容。
    • cout可以打印Expr的具体表达式内容。
    • _.print_loop_nest()可以将调度的伪代码打印出来。

Halide Schedule

Default ordering

没有添加任何调度代码的时候,也就是default ordering的调度时,所有的调度均是串行执行的:

Pseudo-code for the schedule:
produce gradient:
  for y:
    for x:
      gradient(...) = ...

示意图如下所示:

Reorder

func调用_.reorder(_,_);后,可以更改调度的顺序。

调度的伪代码如下:

Pseudo-code for the schedule:
produce gradient_col_major:
  for x:
    for y:
      gradient_col_major(...) = ...

Split a variable 分割变量

func调用

Var x_outer, x_inner;
gradient.split(x, x_outer, x_inner, 2);

后,会将第一个参数分为x_outerx_inner部分,然后再分别执行。最后一个参数是factor,该factor代表着inner的块的大小。见下面代码的x_inner in [0, 1]

Pseudo-code for the schedule:
produce gradient_split:
  for y:
    for x.x_outer:
      for x.x_inner in [0, 1]:
        gradient_split(...) = ...

Splitting by factors that don’t divide the extent

当不能整数分割的时候,会在临界的地方部分点重复计算(保证不越界)。

Store gradient_split_7x2.0(0, 0) = 0
Store gradient_split_7x2.0(1, 0) = 1
Store gradient_split_7x2.0(2, 0) = 2
Store gradient_split_7x2.0(3, 0) = 3
Store gradient_split_7x2.0(4, 0) = 4
Store gradient_split_7x2.0(5, 0) = 5
Store gradient_split_7x2.0(4, 0) = 4
Store gradient_split_7x2.0(5, 0) = 5
Store gradient_split_7x2.0(6, 0) = 6

Fuse two variables into one 合并变量

func调用

Var fused;
gradient.fuse(x, y, fused);

可以将原来的多个合并成一个进行处理。下面的伪代码中原来的两次循环变成了一次循环。

Pseudo-code for the schedule:
produce gradient_fused:
  for x.fused:
    gradient_fused(...) = ...

Evaluating in tiles 分成一块块执行

将原来的图分割成不同的tiles,然后一块一块进行执行:

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Halide 是一个开源的图像处理和计算机视觉 DSL(领域特定语言),其目的是让程序员更加轻松地编写高性能的图像处理代码。Halide 的特点是具有易于使用的语法、高性能的代码生成以及可移植性。 本系列文章将介绍 Halide 的基本语法和使用方法,并通过一些实例来演示如何使用 Halide 进行图像处理和计算机视觉任务。 第一篇文章将介绍 Halide 的基本概念和安装方法。 ## 什么是 Halide? Halide 是由丹尼尔·瑞德福(Daniel R. Johnson)和 Jonathan Ragan-Kelley 在 MIT 开发的一个开源项目。它是一个用于编写高性能图像处理和计算机视觉代码的 DSL。 Halide 的主要目标是使程序员能够使用一种简单易懂的语法编写高性能的代码,而无需了解 CPU 或 GPU 的细节。Halide 支持多种平台,包括 x86、ARM、MIPS 和 PowerPC 等 CPU,以及 NVIDIA、AMD 和 ARM 等 GPU。 Halide 的核心概念是“函数”。函数可以看作是一组描述了如何对输入数据进行处理的指令集合。这些指令可以被 Halide 编译成高效的 CPU 或 GPU 代码,并在运行时执行。 ## Halide 的安装方法 Halide 可以在 Linux、macOS 和 Windows 等操作系统上运行,并且支持多种编译器,包括 GCC、Clang 和 MSVC 等。下面是在 Ubuntu 20.04 上安装 Halide 的步骤: 1. 添加 Halide 的 PPA: ``` sudo add-apt-repository ppa:halide/ppa ``` 2. 更新软件包列表: ``` sudo apt-get update ``` 3. 安装 Halide: ``` sudo apt-get install libhalide-dev ``` 安装完成后,可以使用以下命令检查 Halide 是否已经安装成功: ``` pkg-config --cflags --libs Halide ``` 如果输出了一些 Halide 相关的信息,则表示 Halide 安装成功。 ## 总结 本篇文章介绍了 Halide 的基本概念和安装方法。下一篇文章将介绍 Halide 的基本语法和使用方法。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值