Halide::Generator生成器使用说明
Halide::Generator生成器使用说明
- 1、前言
- 2、核心代码总览
- 3、具体说明和注意事项
- 3.1、生成器使用流程
- 3.2、生成代码内容总览
- 4、后续计划与安排
我们之前已经能够使用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(){/* THE SCHEDULE */// input.set_estimates({{0, 1024}, {0, 1024}, {1, 3}});// output.set_estimates({{0, 1024}, {0, 1024}, {1, 3}});}
- 5、注册生成代码操作
HALIDE_REGISTER_GENERATOR(image_f4, image_f4)//后续通过argv传参去生成image_f4核实现
int main(int argc, char **argv) {return Halide::Internal::generate_filter_main(argc, argv, std::cerr);
}
- 6、命令行操作
if [ ! -d "./halide_generate_file" ]; thenmkdir halide_generate_file
elserm -rf halide_generate_file/*
fi
# 假设总览代码被编译成了test可执行程序
# target=x86-64-linux-opencl -r GPU这些参数的设置决定了目标平台必然会使用opencl实现
./test -g image_f4 -e c_header,c_source -o halide_generate_file target=x86-64-linux-opencl -r GPU
# 那么将在halide_generate_file文件夹下生成相关代码
3.2、生成代码内容总览
- opencl核函数代码如下所示:
/* OpenCL C x86-64-linux-opencl*/
#pragma OPENCL FP_CONTRACT ON
inline float float_from_bits(unsigned int x) {return as_float(x);}
inline float nan_f32() { return NAN; }
inline float neg_inf_f32() { return -INFINITY; }
inline float inf_f32() { return INFINITY; }
inline bool is_nan_f32(float x) {return isnan(x); }
inline bool is_inf_f32(float x) {return isinf(x); }
inline bool is_finite_f32(float x) {return isfinite(x); }
#define sqrt_f32 sqrt
#define sin_f32 sin
#define cos_f32 cos
#define exp_f32 exp
#define log_f32 log
#define abs_f32 fabs
#define floor_f32 floor
#define ceil_f32 ceil
#define round_f32 round
#define trunc_f32 trunc
#define pow_f32 pow
#define asin_f32 asin
#define acos_f32 acos
#define tan_f32 tan
#define atan_f32 atan
#define atan2_f32 atan2
#define sinh_f32 sinh
#define asinh_f32 asinh
#define cosh_f32 cosh
#define acosh_f32 acosh
#define tanh_f32 tanh
#define atanh_f32 atanh
#define fast_inverse_f32 native_recip
#define fast_inverse_sqrt_f32 native_rsqrt
#define halide_unused(x)__kernel void _at_least_one_kernel(int x) { }
// Address spaces for _kernel_f0_s0_v3_v9___block_id_x
#define __address_space__f0 __global
__kernel void _kernel_f0_s0_v3_v9___block_id_x(__address_space__f0 uchar *restrict _f0,__local int16* __shared)
{int _f0_s0_v3_v9___block_id_x = get_group_id(0);int ___thread_id_x = get_local_id(0);int _0 = _f0_s0_v3_v9___block_id_x * 16;int _1 = _0 + ___thread_id_x;float _2 = (float)(_1);float _3 = float_from_bits(998277249 /* 0.00392157 */);float _4 = _2 * _3;float _5 = float_from_bits(1067030938 /* 1.2 */);float _6 = pow_f32(_4, _5);float _7 = float_from_bits(1065353216 /* 1 */);float _8 = min(_6, _7);float _9 = float_from_bits(0 /* 0 */);float _10 = max(_8, _9);float _11 = float_from_bits(1132396544 /* 255 */);float _12 = _10 * _11;uchar _13 = (uchar)(_12);_f0[_1] = _13;
} // kernel _kernel_f0_s0_v3_v9___block_id_x
#undef __address_space__f0
4、后续计划与安排
到了这一步,我们已经可以使用halide继续核函数的生成,但是还需要进行如何使用核函数的过程。
Halide::Generator生成器使用说明相关推荐
- MyBatis Generator 生成器把其他数据库的同名表生成下来的问题
MyBatis Generator 生成器把其他数据库的同名表生成下来的问题 2018年10月23日 20:47:48 莫弹弹 阅读数:603 MyBatis Generator : Table Co ...
- python生成器yield原理_Python generator生成器和yield表达式详解
前言 Python生成器(generator)并不是一个晦涩难懂的概念.相比于MetaClass和Closure等概念,其较为容易理解和掌握.但相对于程序结构:顺序.循环和分支而言其又不是特别的直观. ...
- python学习笔记-day6-函数的延续【汉字转拼音模块,函数返回多个值,匿名函数,列表生成式,generator生成器,三元运算符】...
继续来说函数的后续知识点,主要是函数返回多个值,匿名函数,三元运算符,算是比较小的知识点. 一.汉字转拼音模的使用 1.安装模块 #install xpinyin 2.如果使用 结果: 二.函数返回多 ...
- 理解Generator生成器对象
Generator 对象(理解为生成器函数更好) 注意,Generator函数,不可当作构造函数 首先声明一个Generator 函数,以下均以 gen 为例 function* gen(){yiel ...
- 3-4 第三天 Generator生成器
Generator是ES6里面的新增规范,ES6其实就是ES2015.ES5.ES6.ES7这些术语大家上网一查就都明白了.JavaScript是一个范程,就是我们说的JS.ES就是ECMA Scri ...
- python generator输出_python 高级特性:Generator(生成器)
格式对比: List Imprehensions 格式:[ 语句 for .. in ..] Generator 格式:(语句 for .. in ..) 区别:List存储的是具体内容,每个元素都占 ...
- Generator(生成器),入门初基,Coroutine(原生协程),登峰造极,Python3.10并发异步编程async底层实现
普遍意义上讲,生成器是一种特殊的迭代器,它可以在执行过程中暂停并在恢复执行时保留它的状态.而协程,则可以让一个函数在执行过程中暂停并在恢复执行时保留它的状态,在Python3.10中,原生协程的实现手 ...
- Python中生成器generator和迭代器Iterator的使用方法
一.生成器 1. 生成器的定义 把所需要值得计算方法储存起来,不会先直接生成数值,而是等到什么时候使用什么时候生成,每次生成一个,减少计算机占用内存空间 2. 生成器的创建方式 第一种只要把一个列表生 ...
- python生成器generator和迭代器Iterator测试
为什么需要使用生成器? ''' generator生成器 通过列表推导式,我们可以创建一个新的列表,但是,受内存限制,列表的容量是有限的. 而且,创建一个包含100万个元素的列表,不仅占用很大存储空间 ...
最新文章
- 非托管资源在虚拟机中的管理
- xtrabackup 使用说明(续)
- 项目创建venv、_都2020年了,居然还有人没有在数据科学项目中使用Docker?
- 厦门大学和福州大学计算机专业哪个好,福州大学和厦门大学的土木工程哪个好...
- C++ 静态线性表的顺序存储结构(数组实现)
- Sql Server 2005中的快照隔离
- Beginning SDL 2.0(4) YUV加载及渲染
- 最全三大框架整合(使用映射)——applicationContext.xml里面的配置
- T-Sql备份还原数据库
- java周志第二周_第二周JAVA学习日志
- CVPR 2021 | 用于动作识别,即插即用、混合注意力机制的 ACTION 模块
- ehcache常用API整理
- oracle里的字符串类型,Oracle中的字符串類型及相關函數詳解
- rocketmq下单支付场景
- echarts 实现晶体球面投影
- python实现不重复排列组合_python 实现排列组合
- [编程题]雀魂启动!(java实现)
- 网络攻击更难预料,IoT到底是福是祸?
- 项目实训(树莓派)(十四)树莓派4B下的ubuntu系统下的vim的使用
- ubuntu16.04掉显卡驱动解决方法