Halide
Halide 算是一种编程模式,主要用于在现代机器上来进行高性能的图像和数组处理。其寄生在C++编程语言中,作为DSL编程语言(特定域语言)来实现高性能计算。
目前Halide的支持情况如下所示:
- CPU架构:X86, ARM, MIPS, Hexagon, PowerPC, RISC-V
- 操作系统:Linux, Windows, macOS, Android, iOS, Qualcomm QuRT
- GPU并行编程支持:CUDA, OpenCL, OpenGL Compute Shaders, Apple Metal, Microsoft Direct X 12
支持的编译特性如下所示: - 能够使用Halide的C++接口在C++代码中在内存上构建Pipeline表达式
- 能够编译表达式,持久化编译好的表达式
- 能够运行时编译(JIT-Compile)
- 提供了Python接口
- 要求使用C++17标准
为何要源码编译?
理由千奇百怪,但是人类折腾不止。那么我所能够想到的理由如下所示:
- 不希望使用vcpkg包管理工具(尤其是不会用vcpkg的同志,比如我);
- 有开发工具洁癖的人,不想要使用到那么多的编译工具(比如我);
- 想要把Halide编译出可以随意搬动的第三库(尤其是在跨机器上开发的时候,更是如此);
- 官方发布编译好的Halide二进制包不符合自己的开发环境(比如Ubuntu18.04-x84_64就不存在);
实际上,可能大部分的人是因为没有适合自己机器环境的情况下,才会选择从源码开始编译
源码编译LLVM库
Halide要求比较新的LLVM库,所以我们可以遵循以下的操作来一步一步进行编译和环境设置:
# 1.下载LLVM源码文件,保存为llvm.zip
curl -o llvm.zip https://codeload.github.com/llvm/llvm-project/zip/refs/tags/llvmorg-13.0.0
# 2.解压
unzip llvm.zip
# 3.编译
cd llvm-project-llvmorg-13.0.0
# 3.1.创建安装和编译目录文件
if [ ! -d "./llvm-build" ]; then
mkdir llvm-build
fi
if [ ! -d "./llvm-install" ]; then
mkdir llvm-install
fi
# 3.2.进行编译
cmake -DCMAKE_BUILD_TYPE=Release \
-DLLVM_ENABLE_PROJECTS="clang;lld;clang-tools-extra" \
-DLLVM_TARGETS_TO_BUILD="X86;ARM;NVPTX;AArch64;Mips;Hexagon;WebAssembly" \
-DLLVM_ENABLE_TERMINFO=OFF -DLLVM_ENABLE_ASSERTIONS=ON \
-DLLVM_ENABLE_EH=ON -DLLVM_ENABLE_RTTI=ON -DLLVM_BUILD_32_BITS=OFF \
-S llvm -B llvm-build
cmake --build llvm-build -j32
cmake --install llvm-build --prefix llvm-install
# 4.环境配置
echo "export LLVM_ROOT=`pwd`/llvm-install" >> ~/.bashrc
echo 'export LLVM_CONFIG=$LLVM_ROOT/bin/llvm-config' >> ~/.bashrc
echo 'export PATH=$PATH:$LLVM_ROOT/bin' >> ~/.bashrc
源码编译Halide
Halide官网链接: https://github.com/halide/Halide.
上述链接中,虽然说明了如何进行安装,但是在实际操作的时候会发现非常多的问题,目前我所遇到的问题就是:
- pybing11无法git clone,而且因为是在cmake中进行设置,所以更难绕过这个步骤
- 后端中的opencl无法正确编译
而我对应的解决思路就是:
- 不编译Halide的python接口
- 不编译opencl这个后端
可能你遇到的问题同我一样,那么将会非常幸运,但是如果你遇到的不一样的问题,就需要自行根据CMakeLists.txt的内容去关闭或者打开某些开关,或者是去设置某些第三方库路径等操作了。
具体的编译命令如下所示:
# 1.下载Halide的源码
curl -o Halide.zip https://codeload.github.com/halide/Halide/zip/refs/heads/main
# 2.解压文件
unzip Halide.zip
# 3.编译
if [ ! -d "./build" ]; then
mkdir build
fi
cd build
# 关闭python_bindings和target_opencl开关
cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_DIR=$LLVM_ROOT/lib/cmake/llvm -DWITH_PYTHON_BINDINGS=OFF -DTARGET_OPENCL=OFF -S ..
cmake --build . -j32
# 4.默认安装在/usr/local下面
make install -j32
测试Halide是否编译成功
最好的办法就是运行教程示例,而因为Halide自带的教程需要使用到gcc编译命令,十分繁琐。因此我们可以直接从网上克隆一个可使用的教程示例,同时进行一键运行编译:
git clone https://github.com/pengzhikang/Halide-Learning.git
cd Halide-Learning/tutorial
chmod +x build.sh
如果没有问题,我们将会看到如下所示的内容:
<----------------------------------Begin Run Test------------------------------------->
Evaluating gradient
Begin pipeline gradient.0()
Tag gradient.0() tag = "func_type_and_dim: 1 0 32 1 2 0 8 0 8"
......省略.......
Evaluating sin(x) + cos(y), and printing cos(y) at a single pixel
-0.399985 <- this is cos(y) at x, y == (37, 42)
Evaluating sin(x) + cos(y), and printing whenever cos(y) < 0
-0.416147 cos(y) < 0 at y == 2
-0.416147 cos(y) < 0 at y == 2
-0.416147 cos(y) < 0 at y == 2
-0.416147 cos(y) < 0 at y == 2
-0.989992 cos(y) < 0 at y == 3
-0.989992 cos(y) < 0 at y == 3
-0.989992 cos(y) < 0 at y == 3
-0.989992 cos(y) < 0 at y == 3
Printing a complex Expr: ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((1 + 2) + fizz) + 4) + buzz) + fizz) + 7) + 8) + fizz) + buzz) + 11) + fizz) + 13) + 14) + (fizz*buzz)) + 16) + 17) + fizz) + 19) + buzz) + fizz) + 22) + 23) + fizz) + buzz) + 26) + fizz) + 28) + 29) + (fizz*buzz)) + 31) + 32) + fizz) + 34) + buzz) + fizz) + 37) + 38) + fizz) + buzz) + 41) + fizz) + 43) + 44) + (fizz*buzz)) + 46) + 47) + fizz) + 49) + buzz) + fizz) + 52) + 53) + fizz) + buzz) + 56) + fizz) + 58) + 59) + (fizz*buzz)) + 61) + 62) + fizz) + 64) + buzz) + fizz) + 67) + 68) + fizz) + buzz) + 71) + fizz) + 73) + 74) + (fizz*buzz)) + 76) + 77) + fizz) + 79) + buzz) + fizz) + 82) + 83) + fizz) + buzz) + 86) + fizz) + 88) + 89) + (fizz*buzz)) + 91) + 92) + fizz) + 94) + buzz) + fizz) + 97) + 98) + fizz)
Success!
<----------------------------------End Test------------------------------------->
至此,我们从源码编译Halide算是成功了。