Halide::Generator生成器使用说明
我们之前已经能够使用Halide去调用OpenCL后端了,但是我们的代码总是在建立计算图和调度后使用realize实例化进行运行。
这很明显对于我们AI模型优化核函数、推理运行时这些操作造成不小的影响。而且也无法剥离出Halide这个庞大的依赖库,导致
最终的推理时依赖过多引起的接口过于复杂。
1、前言
本次的主要工作就是尝试了Halide::Generator生成器去进行核函数生成以及如何使用不同后端的试验。
关键信息如下所示:
- 多计算图
- 调度gpu约束
- 输入输出定义信息
- 自动调度操作
- 生成器调用示例
2、核心代码总览
#include <stdio.h>
#include "Halide.h"
#include "HalideBuffer.h"
#include "clock.h"
using namespace Halide;
using namespace Halide::Tools;
//尝试进行核函数生成操作。
class image_f4:public Halide::Generator<image_f4>{
public:
// 定义输入buffer,图片数据,三维数据
Input<Buffer<uint8_t>> input{"input", 3};
// 定义输出buffer,图片数据,三维数据,两者shape完全一致。
Output<Buffer<uint8_t>> output{"output", 3};
void generate()
{
Var x, y, c, i, ii, xo, yo, xi, yi;
Func lut;
Func curved;
Func padded;
lut(i) = cast<uint8_t>(clamp(pow(i / 255.0f, 1.2f) * 255.0f, 0, 255));
// Augment the input with a boundary condition.
padded(x, y, c) = input(clamp(x, 0, input.width() - 1),
clamp(y, 0, input.height() - 1), c);
// Cast it to 16-bit to do the math.
Func padded16;
padded16(x, y, c) = cast<uint16_t>(padded(x, y, c));
// Next we sharpen it with a five-tap filter.
Func sharpen;
sharpen(x, y, c) = (padded16(x, y, c) * 2 -
(padded16(x - 1, y, c) +
padded16(x, y - 1, c) +
padded16(x + 1, y, c) +
padded16(x, y + 1, c)) /
4);
curved(x, y, c) = lut(sharpen(x, y, c));
lut.compute_root();
Var block, thread;
lut.split(i, block, thread, 16);
lut.gpu_blocks(block)
.gpu_threads(thread);
output(x, y, c) = curved(x, y, c);
}
void schedule()
{
/* THE SCHEDULE */
// input.set_estimates({
{0, 1024}, {0, 1024}, {1, 3}});
// output.set_estimates({
{0, 1024}, {0, 1024}, {1, 3}});
}
};
HALIDE_REGISTER_GENERATOR(image_f4, image_f4)
int main(int argc, char **argv) {
return Halide::Internal::generate_filter_main(argc, argv, std::cerr);
}
3、具体说明和注意事项
3.1、生成器使用流程
- 1、建立基于父类Halide::Generator的核生成器
class image_f4:public Halide::Generator<image_f4>{}
- 2、声明输出输入buffer信息
// 定义输入buffer,图片数据,三维数据
Input<Buffer<uint8_t>> input{"input", 3};
// 定义输出buffer,图片数据,三维数据,两者shape完全一致。
Output<Buffer<uint8_t>> output{"output", 3};
- 3、声明核函数的halide计算图实现
void generate()
{
Var x, y, c, i, ii, xo, yo, xi, yi;
Func lut;
Func curved;
Func padded;
lut(i) = cast<uint8_t>(clamp(pow(i / 255.0f, 1.2f) * 255.0f, 0, 255));
// Augment the input with a boundary condition.
padded(x, y, c) = input(clamp(x, 0, input.width() - 1),
clamp(y, 0, input.height() - 1), c);
// Cast it to 16-bit to do the math.
Func padded16;
padded16(x, y, c) = cast<uint16_t>(padded(x, y, c));
// Next we sharpen it with a five-tap filter.
Func sharpen;
sharpen(x, y, c) = (padded16(x, y, c) * 2 -
(padded16(x - 1, y, c) +
padded16(x, y - 1, c) +
padded16(x + 1, y, c) +
padded16(x, y + 1, c)) /
4);
curved(x, y, c) = lut(sharpen(x, y, c));
/*-----------自定义调度-----------*/
lut.compute_root();
Var block, thread;
lut.split(i, block, thread, 16);
lut.gpu_blocks(block)
.gpu_threads(thread);
/*-----------自定义调度-----------*/
output(x, y, c) = curved(x, y, c);
}
- 4、自动调度设置(可选)
void schedule()
Halide::Generator 使用指南:优化AI核函数与OpenCL后端

本文档详细介绍了如何利用Halide::Generator生成器来创建和优化AI模型的核函数,以及如何指定GPU约束和自动调度。通过示例代码展示了从输入输出定义到核函数实现、调度设置的完整流程,并提供了OpenCL后端的生成代码片段。此外,还讨论了后续如何使用生成的核函数。
最低0.47元/天 解锁文章
2153





