示例学习
基本变量和概念
// 使用Halide,我们只需要包含Halide.h这个头文件就可以了
#include "Halide.h"
#include <stdio.h>
int main(int argc, char **argv) {
// Halide::Func代表了一个计算图,代表了每一个像素值需要进行的计算操作
Halide::Func gradient;
// Halide::Var代表了一个变量名,需要跟Func配合使用才有意义
Halide::Var x, y;
// Halide::Expr代表一个表达式,可由变量的数学表达式组合成
Halide::Expr e = x + y;
// 现在使用左值等式接口,再计算图上添加表达式
gradient(x, y) = e;
// 上述写法等同如下
//
// gradient(x, y) = x + y;
//
// 上述只是在定义计算图,没有进行实际的运算
// 以下的语句在实际运行计算图,同事得到结果保存在output中
Halide::Buffer<int32_t> output = gradient.realize({800, 600});
// 以下是检查代码
for (int j = 0; j < output.height(); j++) {
for (int i = 0; i < output.width(); i++) {
if (output(i, j) != i + j) {
printf("Something went wrong!\n"
"Pixel %d, %d was supposed to be %d, but instead it's %d\n",
i, j, i + j, output(i, j));
return -1;
}
}
}
printf("Success!\n");
return 0;
}
# 运行结果如下所示:
Success!
操控图片操作
#include "Halide.h"
// 为了能够加载png图片而引入的库
#include "halide_image_io.h"
using namespace Halide::Tools;
int main(int argc, char **argv) {
// 该程序主要是进行图像的过曝操作,提高亮度
// 加载图像
Halide::Buffer<uint8_t> input = load_image("../../images/rgb.png");
Halide::Func brighter;
Halide::Var x, y, c; // 多维度的图像
// 第一个表达式
Halide::Expr value = input(x, y, c);
// char--->fp32
value = Halide::cast<float>(value);
// 乘以1.5进行提高亮度
value = value * 1.5f;
// 然后截断在255以内
value = Halide::min(value, 255.0f);
// 最后fp32--->char
value = Halide::cast<uint8_t>(value);
// 最后组成计算图
brighter(x, y, c) = value;
// 以上操作也跟下面的语句同样的效果
//
// brighter(x, y, c) = Halide::cast<uint8_t>(min(input(x, y, c) * 1.5f, 255));
//
// 下述命令进行计算图的计算
Halide::Buffer<uint8_t> output =
brighter.realize({input.width(), input.height(), input.channels()});
// 最后进行output的操作
save_image(output, "../../result/lesson_02_brighter.png");
printf("Success!\n");
return 0;
}
输入图片如下所示:
输出图片如下所示:
debug操作1
#include "Halide.h"
#include <stdio.h>
using namespace Halide;
int main(int argc, char **argv) {
// 为了能够进行更清晰的说明,这里使用string赋值给函数和变量
Func gradient("gradient");
Var x("x"), y("y");
gradient(x, y) = x + y;
Buffer<int> output = gradient.realize({8, 8});
// 把计算图的编译过程使用了html来进行展示
gradient.compile_to_lowered_stmt("../../result/gradient.html", {}, HTML);
printf("Success!\n");
return 0;
}
module name=gradient, target=x86-64-linux-avx-avx2-avx512-avx512_skylake-f16c-fma-sse41 {
func gradient(gradient) {
// 判断不是空buffer
assert((reinterpret(gradient.buffer) != (uint64)0), halide_error_buffer_argument_is_null("gradient"))
// 获取主机buffer
let gradient = _halide_buffer_get_host(gradient.buffer)
// 获取buffer类型
let gradient.type = _halide_buffer_get_type(gradient.buffer)
// 获取设备buffer
let gradient.device_dirty = _halide_buffer_get_device_dirty(gradient.buffer)
// 获取buffer维度
let gradient.dimensions = _halide_buffer_get_dimensions(gradient.buffer)
// 获取buffer第0维度的起点
let gradient.min.0 = _halide_buffer_get_min(gradient.buffer, 0)
// 获取buffer第0维度的终点
let gradient.extent.0 = _halide_buffer_get_extent(gradient.buffer, 0)
// 获取buffer第0维度的步长
let gradient.stride.0 = _halide_buffer_get_stride(gradient.buffer, 0)
let gradient.min.1 = _halide_buffer_get_min(gradient.buffer, 1)
let gradient.extent.1 = _halide_buffer_get_extent(gradient.buffer, 1)
let gradient.stride.1 = _halide_buffer_get_stride(gradient.buffer, 1)
// 查看是否在边界
if (_halide_buffer_is_bounds_query(gradient.buffer)) {
_halide_buffer_init(gradient.buffer, _halide_buffer_get_shape(gradient.buffer), reinterpret((uint64)0), (uint64)0, reinterpret((uint64)0), 0, 32, 2, make_struct(gradient.min.0, gradient.extent.0, 1, 0, gradient.min.1, gradient.extent.1, gradient.extent.0, 0), (uint64)0)
}
if (!_halide_buffer_is_bounds_query(gradient.buffer)) {
assert((gradient.type == (uint32)73728), halide_error_bad_type("Output buffer gradient", gradient.type, (uint32)73728))
assert((gradient.dimensions == 2), halide_error_bad_dimensions("Output buffer gradient", gradient.dimensions, 2))
assert((0 <= gradient.extent.0), halide_error_buffer_extents_negative("Output buffer gradient", 0, gradient.extent.0))
assert((0 <= gradient.extent.1), halide_error_buffer_extents_negative("Output buffer gradient", 1, gradient.extent.1))
assert((gradient.stride.0 == 1), halide_error_constraint_violated("gradient.stride.0", gradient.stride.0, "1", 1))
let gradient.total_extent.1 = (int64(gradient.extent.1) * int64(gradient.extent.0))
assert((uint64(gradient.extent.0) <= (uint64)2147483647), halide_error_buffer_allocation_too_large("gradient", uint64(gradient.extent.0), (uint64)2147483647))
assert((abs((int64(gradient.extent.1) * int64(gradient.stride.1))) <= (uint64)2147483647), halide_error_buffer_allocation_too_large("gradient", abs((int64(gradient.extent.1) * int64(gradient.stride.1))), (uint64)2147483647))
assert((gradient.total_extent.1 <= (int64)2147483647), halide_error_buffer_extents_too_large("gradient", gradient.total_extent.1, (int64)2147483647))
assert(!gradient.device_dirty, halide_error_device_dirty_with_no_device_support("Output buffer gradient"))
assert((gradient != reinterpret((uint64)0)), halide_error_host_is_null("Output buffer gradient"))
produce gradient {
// greadient(x,y)=x+y的计算图的代码构成如下所示
let t7 = (0 - (gradient.min.1 * gradient.stride.1))
let t6 = (gradient.min.0 + gradient.min.1)
for (gradient.s0.y.rebased, 0, gradient.extent.1) {
let t9 = (((gradient.min.1 + gradient.s0.y.rebased) * gradient.stride.1) + t7)
let t8 = (gradient.s0.y.rebased + t6)
for (gradient.s0.x.rebased, 0, gradient.extent.0) {
gradient[(gradient.s0.x.rebased + t9)] = (gradient.s0.x.rebased + t8)
}
}
//假设是C++代码,那么可以描述如下所示
/*
int x_len = 100;
int y_len = 44;
int gradient[x_len*y_len] = {};
int t7 = 0 - 0 * 1;
int t6 = 0 + 0;
for(int y_rebased = 0; y_rebased < y_len; y_rebased++){
int t9 = (0+y_rebased)*1 + t7;//y_rebased
int t8 = (y_rebased + t6);//y_rebased
for(int x_rebased = 0; x_rebased < x_len; x_rebased++){
gradient[x_rebased + t9] = x_rebased + t8;//gradient[x_rebased+y_rebased] = x_rebased+y_rebased
}
}
*/
}
}
}
}