【RUY】tensorflow int8量化推理代码学习

本文详细介绍了ruy库的编译过程,通过运行和分析不同示例代码,如ExampleMulFloat、ExampleMulFloatWithBiasAddAndClamp等,展示了int8量化计算的原理,包括零点处理和量化乘法的实现细节。文章还探讨了源码中的矩阵运算优化策略,以及如何处理不同类型的输入数据。

0、写在前面

在这里插入图片描述
本来想学习gemm的相关代码,看一看tensorflow是怎么高效的进行int8推理,然后在这里看到most of gemmlowp is superseded by ruy,于是研究了一会儿ruy。

1、工程编译

将源码clone下来进行编译

git clone https://github.com/google/ruy.git
cd ruy/

mkdir build
cd build/
cmake ..

期间遇到报错

CMake Error at CMakeLists.txt:76 (message):
  This file does not exist:

  xxx/ruy/third_party/cpuinfo/CMakeLists.txt

  That typically means that the git submodules of the ruy repository haven't
  been checked out. 

于是把git的submodule也下载下来

git submodule update --init
cmake ..
make -j8

编译成功

2、跑个demo

跑个例子看一下

./example/ruy_example_example 
Example Mul, float:
LHS:
1 2 
3 4 
RHS:
1 3 
2 4 
Result:
5 11 
11 25 

Example Mul, float with bias addition and clamp:
LHS:
1 2 
3 4 
RHS:
1 3 
2 4 
Result:
6 12 
11 15 

Example Mul, uint8 quantized with asymmetric zero points:
LHS:
124 125 
126 127 
RHS:
129 131 
130 132 
Result:
131 130 
126 129 

Example Mul, int8 quantized with per-channel multipliers
LHS:
1 2 
3 4 
RHS:
1 3 
2 4 
Result:
4 8 
2 4 

Example Mul, returning raw int32 accumulators:
LHS:
1 2 
3 4 
RHS:
1 3 
2 4 
Result:
5 11 
11 25 

Example Mul, int8 times int16 quantized with per-channel multipliers
LHS:
1 2 
3 4 
RHS:
1000 3000 
2000 4000 
Result:
3750 8250 
1719 3906 

3、Example分析

3.1 ExampleMulFloat

测试代码

const float lhs_data[] = {
   
   1, 2, 3, 4};
const float rhs_data[] = {
   
   1, 2, 3, 4};
float dst_data[4];
  
ruy::Matrix<float> lhs;
ruy::MakeSimpleLayout(2, 2, ruy::Order::kRowMajor, lhs.mutable_layout());
lhs.set_data(lhs_data);
ruy::Matrix<float> rhs;
ruy::MakeSimpleLayout(2, 2, ruy::Order::kColMajor, rhs.mutable_layout());
rhs.set_data(rhs_data);
ruy::Matrix<float> dst;
ruy::MakeSimpleLayout(2, 2, ruy::Order::kColMajor, dst.mutable_layout());
dst.set_data(dst_data);
  
ruy::MulParams<float, float> mul_params;
ruy::Mul(lhs, rhs, mul_params, context, &dst);
  
std::cout << "Example Mul, float:\n";
std::cout << "LHS:\n" << lhs;
std::cout << "RHS:\n" << rhs;
std::cout << "Result:\n" << dst << "\n";

运行结果

Example Mul, float:
LHS:
1 2 
3 4 
RHS:
1 3 
2 4 
Result:
5 11 
11 25 

分析

[ 1 2 3 4 ] [ 1 3 2 4 ] = [ 5 11 11 25 ] \left[ \begin{matrix} 1 & 2 \\ 3 & 4 \end{matrix} \right] \left[ \begin{matrix} 1 & 3 \\ 2 & 4 \end{matrix} \right] = \left[ \begin{matrix} 5 & 11 \\ 11 & 25 \end{matrix} \right] [1324][1234]=[5111125]

这个是浮点的计算,在我看来只要结果一直就可以,没什么我需要特别关注的。

3.2 ExampleMulFloatWithBiasAddAndClamp

测试代码

const float lhs_data[] = {
   
   1, 2, 3, 4};
const float rhs_data[] = {
   
   1, 2, 3, 4};
const float bias_data[] = {
   
   1, 0};
float dst_data[4];
  
ruy::Matrix<float> lhs;
ruy::MakeSimpleLayout(2, 2, ruy::Order::kRowMajor, lhs.mutable_layout());
lhs.set_data(lhs_data);
ruy::Matrix<float> rhs;
ruy::MakeSimpleLayout(2, 2, ruy::Order::kColMajor, rhs.mutable_layout());
rhs.set_data(rhs_data);
ruy::Matrix<float> dst;
ruy::MakeSimpleLayout(2, 2, ruy::Order::kColMajor, dst.mutable_layout());
dst.set_data(dst_data);
  
ruy::MulParams<float, float> mul_params;
mul_params.set_bias(bias_data);
mul_params.set_clamp_min(0);
mul_params.set_clamp_max(15);
ruy::Mul(lhs, rhs, mul_params, context, &dst);
  
std::cout << "Example Mul, float with bias addition and clamp:\n";
std::cout << "LHS:\n" << lhs;
std::cout << "RHS:\n" << rhs;
std::cout << "Result:\n" << dst << "\n";

运行结果

Example Mul, float with bias addition and clamp:
LHS:
1 2 
3 4 
RHS:
1 3 
2 4 
Result:
6 12 
11 15 

分析

[ 1 2 3 4 ] [ 1 3 2 4 ] + [ 1 0 ] = [ 6 12 11 25 ] \left[ \begin{matrix} 1 & 2 \\ 3 & 4 \end{matrix} \right] \left[ \begin{matrix} 1 & 3 \\ 2 & 4 \end{matrix} \right] + \left[ \begin{matrix} 1 \\ 0 \end{matrix} \right] = \left[ \begin{matrix} 6 & 12 \\ 11 & 25 \end{matrix} \right] [1324][1234]+[10]=[

### TensorFlow Lite 交叉编译指南 TensorFlow Lite 是一种轻量级的机器学习框架,专为移动设备和嵌入式系统设计。为了在 ARM 平台(如树莓派或其他基于 ARM 的硬件)上部署模型,通常需要进行交叉编译。以下是针对 TensorFlow Lite 交叉编译的相关说明: #### 1. 准备工作 确保开发环境中已安装必要的工具链和依赖项。这包括但不限于 CMake、Bazel 和目标平台的交叉编译器。对于 ARM 架构的目标设备,推荐使用 `aarch64-linux-gnu` 工具链。 - 安装基础依赖: ```bash sudo apt-get update && sudo apt-get install -y \ build-essential \ cmake \ git \ wget \ unzip \ python3-dev \ python3-pip ``` - 下载并配置交叉编译工具链[^4]: ```bash wget https://developer.arm.com/-/media/Files/downloads/gnu-a/9.2-2019.12/binrel/gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu.tar.xz tar xf gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu.tar.xz -C /opt/ export PATH=/opt/gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu/bin:$PATH ``` #### 2. 获取 TensorFlow 源码 克隆 TensorFlow Git 仓库,并切换至支持 TensorFlow Lite 的版本(例如 v2.3.1)。此操作可以通过以下命令完成: ```bash git clone https://github.com/tensorflow/tensorflow.git cd tensorflow git checkout tags/v2.3.1 ``` #### 3. 配置交叉编译环境 创建一个自定义工具链文件用于描述交叉编译器路径和其他必要参数。例如,可以命名为 `toolchain.cmake`: ```cmake set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR aarch64) set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc) set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) ``` 随后,在构建过程中传递该工具链文件给 CMake。 #### 4. 使用 Bazel 或 CMake 进行交叉编译 ##### 方法一:通过 Bazel 跨平台编译 如果选择使用 Bazel 来执行交叉编译,则需调整 `.bazelrc` 文件中的配置以适配目标架构。具体步骤如下: ```bash echo "build --crosstool_top=@local_config_arm_compiler//:toolchain" >> ~/.tf_configure_bazelrc echo "build --cpu=armeabi-v7a" >> ~/.tf_configure_bazelrc ``` 接着运行标准的 Bazel 命令来生成动态链接库或静态库[^3]: ```bash bazel build --config=opt //tensorflow/lite:libtensorflowlite.so ``` ##### 方法二:借助 CMake 实现更灵活控制 另一种方式是利用 CMake 执行手动配置与构建流程。这种方法允许开发者更加精细地定制化选项。示例脚本如下所示: ```bash mkdir -p tflite_build && cd tflite_build cmake .. \ -DCMAKE_TOOLCHAIN_FILE=../toolchain.cmake \ -DTFLITE_ENABLE_RUY=ON \ -DTFLITE_WITH_XNNPACK=OFF \ -DANDROID_ABI="arm64-v8a" make -j$(nproc) ``` 以上两种方法均可实现 TensorFlow Lite 对于 ARM 设备的支持,但实际应用中可能还需要额外考虑特定硬件加速单元(比如 GPU 或 NPU)所需的驱动程序及其集成问题[^1]。 --- ### 总结 综上所述,无论是采用 Bazel 自动化的解决方案还是依靠 CMake 提供的高度可配置能力,都可以顺利完成 TensorFlow Lite 向 ARM 架构迁移的任务。然而需要注意的是整个过程涉及较多细节处理,尤其是当引入第三方扩展组件时更是如此。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值