Halide代码优化思想简述

本文简要介绍了Halide编程语言,一种基于C++的DSL,用于图像处理和矩阵计算的高效优化。文章重点讨论了高性能代码的特征,包括并行性、局部性和调度,并详细阐述了Halide的优化方法,如Reorder、Split、Fuse、Tile、向量化、展开和整合。此外,还提到了自动搜索的Auto-Scheduler在优化过程中的作用。Halide的优化思想对图像处理和深度学习领域的代码加速具有重要借鉴价值。
摘要由CSDN通过智能技术生成

1.Halide介绍

Halide是一种编程语言,主要在图片处理和矩阵计算时具有方便快捷高性能的特点。它不是一种独立语言,而是基于C++的DSL(Domain Specified Language),主要应用在算法的底层加速,并且此优化与算法本身设计无关。Halide思想在传统的图像处理(OpenvCV)和深度学习(TVM)优化加速方面具有较强的借鉴意义。支持的目标如下:

  • CPU 架构: X86, ARM, MIPS, Hexagon, PowerPC, RISC-V

  • OS: Linux, Windows, macOS, Android, iOS, Qualcomm QuRT

  • GPU APIs: CUDA, OpenCL, OpenGL Compute Shaders, Apple Metal, Microsoft Direct X 12

作为一种嵌入在C++上的语言,用户可以使用C++API创建Halide的内存中间表示,共两种编译方式JIT(just-in-time)和AOT(ahead-of-time),JIT方式在代码运行阶段被映射为Halide内存对象,AOT方式可以生成编译文件,在使用时进行链接,主要应用于嵌入式和交叉编译环境。

下面代码是使用Halide定义的3*3的图片过滤函数示例:

Func blur_3x3(Func input) {
  Func blur_x, blur_y;
  Var x, y, xi, yi;

  blur_x(x, y) = (input(x-1, y) + input(x, y) + input(x+1, y))/3;
  blur_y(x, y) = (blur_x(x, y-1) + blur_x(x, y) + blur_x(x, y+1))/3;

  blur_y.tile(x, y, xi, yi, 256, 32)
        .vectorize(xi, 8).parallel(y);
  blur_x.compute_at(blur_y, x).vectorize(x, 8);

  return blur_y;
}

2.高性能代码的特征

高性能代码需要开发者在并行、局部性、额外开销(如下图)三个方面进行平衡。通过多核并行或SIMD同时对多路数据计算可以缩短计算时间,但是此过程中会存在多进程或线程开销。为了获取程序内存的局部性,可能需要对内存进行合并、划分、拷贝等操作,从而产生额外工作。因此获取高性能代码的过程需要对并行、局部性、额外开销三个方面进行平衡。 

2.1 并行性(parallelizing)

实现并行的方式主要为mutlticore和SIMD,其中multicore的方式比较容易理解,使用多个物理核进行计算,这样就可以比单核计算的速度快。SIMD即Single Instruction Multiple Data,一条指令操作多个数据。是CPU基本指令集的扩展,主要用于小碎数据的并行操作。在图像处理过程中,一个像素点的一个分量总是用小于等于8bit的数据表示的。如果使用传统的处理器做计算,虽然处理器的寄存器是32位或是64位的,处理这些数据却只能用于他们的低8位,如果把64位寄存器拆成8个8位寄存器就能同时完成8个操作,计算效率提升了8倍。

2.2 局部性(loclaity)

在CPU访问存储设备时,无论是存取数据抑或存取指令,都趋于聚集在一片连续的区域中,这就被称为局部性原理。时间局部性(Temporal Locality),如果一个信息项正在被访问,那么在近期它很可能还会被再次访问。比如循环、递归、方法的反复调用等。空间局部性(Spatial Locality),如果一个存储器的位置被引用,那么将来他附近的位置也会被引用。比如顺序执行的代码、连续创建的两个对象、数组等。下面是Halide中的经典模糊化(blurred)图像的例子,首先在x轴上对每个像素点以及周围的两个点进行求和平均,然后再到y轴上进行同样的操作,这样相当于一个3×3平均卷积核对整个图像进行操作。

void box_filter_3x3(const Mat ∈, Mat &blury){
    Mat blurx(in.size(), in.type());

    for(int x = 1; x < in.cols-1; x ++)
        for(int y = 0 ; y < in.rows; y ++)
            blurx.at<uint8_t >(y, x) = static_cast<uint8_t>(
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Linux基金会AI&Data基金会

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值