AOT(超前编译)实例分析

news2025/1/23 6:23:05

文章目录

  • 一、背景
  • 二、具体实施
    • 2.1 tfcomfile 是什么?
    • 2.2 tfcompile 的功能是什么?
    • 2.3使用tfcompile
  • 三、总结

一、背景

前边已经了解了JIT和AOT的基本概念,AOT(提前编译)方式就是在代码执行阶段之前全部编译成目标指令,进入执行阶段后,不再有编译过程发生。通过TensorFlow自带的实例来加深对AOT的理解,使用AOT编译。

note: JIT相对好理解,可以自动实现操作,但是AOT不是很理解具体实现过程。

二、具体实施

AOT的核心工具是tfcomfil。 示例: tensorflow\compiler\aot\tests。我们先深入了解一下tfcomfile的功能,看看它是干啥的。

2.1 tfcomfile 是什么?

tfcompile 是一个可将 TensorFlow 计算图提前 (AOT) 编译为可执行代码的独立工具。它可以缩减二进制文件的总大小,也可以避免一些运行时开销。tfcompile 的典型用例是将推断计算图编译为适用于移动设备的可执行代码。

TensorFlow 计算图通常由 TensorFlow 运行时执行。在执行计算图中的每个节点时,均会产生一定的运行时开销。这也会导致二进制文件更大,因为除了计算图本身以外,还需包含 TensorFlow 运行时(runtime)代码。由 tfcompile 生成的可执行代码不会使用 TensorFlow 运行时(runtime),而仅仅依赖于计算实际使用的内核。

2.2 tfcompile 的功能是什么?

tfcompile 接受由 TensorFlow 的 feed 和 fetch 概念标识的子计算图,并生成实现该子计算图的函数。feeds 为函数的输入参数,fetches 为函数的输出参数。生成的函数将打包为 cc_library,其中带有导出函数签名的头文件和包含实现的对象文件。用户编写代码以适当调用生成的函数。

2.3使用tfcompile

在TensorFlow中,tensorflow\compiler\aot\tests中有实例,我们利用给出的实例进行AOT编译。
在这里插入图片描述函数tfmatmul构建了一个简单的网络,定义两个节点分别是x,y,然后进行相乘。

我们将使用XLA的AOT方式将这计算图编译成可执行文件,需要四步。

第一步:编写配置

配置网络的输入和输出节点,对应生成函数的输入输出参数。(也可以通过运行 tensorflow\compiler\aot\tests\make_test_graphs.py自动生成。) .\tensorflow\compiler\aot\tests\test_graph_tfmatmul.config.pbtxt

# Text form of tensorflow.tf2xla.Config proto.
#每个feed都是生成函数的位置输入参数。 每个条目的顺序与每个输入参数的顺序匹配。 这里的“x_hold”和“y_hold”是指图中定义的占位符节点的名称。
feed {
  id { node_name: "x_hold" }
  shape {
    dim { size: 2 }
    dim { size: 3 }
  }
}
feed {
  id { node_name: "y_hold" }
  shape {
    dim { size: 3 }
    dim { size: 2 }
  }
}
#每个fetch都是生成函数的位置输出参数。 每个条目的顺序与每个输出参数的顺序匹配。 这里的“x_y_prod”是指图中定义的矩阵节点的名称。
fetch {
  id { node_name: "x_y_prod" }
}

第二步:使用tf_library构建宏来编译子图为静态链接库

在BUILD中添加脚本,生成C++头文件

.tensorflow\compiler\aot\tests\BUILD

load("//tensorflow/compiler/aot:tfcompile.bzl", "tf_library")
 
# Use the tf_library macro to compile your graph into executable code.
tf_library(
    name = "test_graph_tfmatmul",
    testonly = 1,
    config = "test_graph_tfmatmul.config.pbtxt",
    cpp_class = "foo::bar::MatMulComp",
    graph = "test_graph_tfmatmul.pb",
    mlir_components = "None",
    tags = [
        "manual",
    ],
)
/*
# Use the tf_library macro to compile your graph into executable code.
tf_library(
#name用于生成以下基础构建规则:<name>:cc_library包装生成的标头和对象文件<name> _test:cc_test包含一个简单
的测试和基准测试<name> _benchmark:cc_binary包含具有最小deps的独立基准;可以在移动设备上运行
    name = "test_graph_tfmatmul",
#CPP_CLASS指定生成的C ++类的名称,并允许使用名称空间。该类将在给定的名称空间中生成,
或者如果没有名称空间给出,在全局名称空间内。
    cpp_class = "foo::bar::MatMulComp",
# 图是GraphDef Proto的输入,默认情况下以二进制格式预期。至改用文本格式,只需使用“ .pbtxt”后缀。
子图将是由此输入图创建,并将输入作为输入和获取作为输出。
    # config is the input Config proto, by default expected in binary format.  To use the text format instead, use the ‘.pbtxt’ suffix. 
This is where the feeds and fetches were specified above, in the previous step.配置是Config proto的输入,默认情况下,
以二进制格式预期。要使用文本格式,请使用“ .pbtxt”后缀。这是上面在上面的步骤中指定的提要和提取的地方。
    config = "test_graph_tfmatmul.config.pbtxt",
)
*/

然后编译

bazel build :test_graph_tfmatmul
在这里插入图片描述
在bazel-bin中会生成对应的头文件和object 文件。 (D:\work\work_code\bazel_2.7_1\tensorflow-r2.7\bazel-bin\tensorflow\compiler\aot\tests)
在这里插入图片描述
test_graph_tfmatmul.h部分文代码,全部文件:test_graph_tfmatmul.h

生成的 C++ 类在 foo::bar 命名空间中称为 MatMulComp,因为它是在 tf_library 宏中指定的 cpp_class。所有生成的类都有相似的 API,唯一区别在于处理参数和结果缓冲区的方法。这些方法因缓冲区的数量和类型而异,缓冲区的数量和类型通过 feed 和 fetch 参数对 tf_library 宏指定。

#include "tensorflow/compiler/tf2xla/xla_compiled_cpu_function.h"
#include "tensorflow/core/platform/types.h"
 
namespace Eigen { struct ThreadPoolDevice; }
namespace xla { class ExecutableRunOptions; }
 
// (Implementation detail) Entry point to the function in the object file.
extern "C" void __xla_tensorflow_compiler_aot_tests__test_graph_tfmatmul(
    void* result, const ::xla::ExecutableRunOptions* run_options,
    const void** args, void** temps, int64_t* profile_counters);
 
 
 
namespace foo {
namespace bar {
 
// MatMulComp represents a computation previously specified in a
// TensorFlow graph, now compiled into executable code. This extends the generic
// XlaCompiledCpuFunction class with statically type-safe arg and result
// methods. Usage example:
//
//   MatMulComp computation;
//   // ...set args using computation.argN methods
//   CHECK(computation.Run());
//   // ...inspect results using computation.resultN methods
//
// The Run method invokes the actual computation, with inputs read from arg
// buffers, and outputs written to result buffers. Each Run call may also use
// a set of temporary buffers for the computation.
//
// By default each instance of this class manages its own arg, result and temp
// buffers. The AllocMode constructor parameter may be used to modify the
// buffer allocation strategy.
//
// Under the default allocation strategy, this class is thread-compatible:
// o Calls to non-const methods require exclusive access to the object.
// o Concurrent calls to const methods are OK, if those calls are made while it
//   is guaranteed that no thread may call a non-const method.
//
// The logical function signature is:
//   (arg0: f32[2,3], arg1: f32[3,2]) -> (f32[2,2])
//
// Memory stats:
//   arg bytes total:    48
//   arg bytes aligned:  128
//   temp bytes total:   24
//   temp bytes aligned: 128
class MatMulComp final : public tensorflow::XlaCompiledCpuFunction {
 public:
  // Number of input arguments for the compiled computation.
  static constexpr size_t kNumArgs = 2;
 
  // Number of variables for the compiled computation.
  static constexpr size_t kNumVariables = 0;
 
  // Byte size of each argument buffer. There are kNumArgs entries.
  static const ::int64_t ArgSize(::tensorflow::int32 index) {
    return BufferInfos()[ArgIndexToBufferIndex()[index]].size();
  }
 
  // Returns static data used to create an XlaCompiledCpuFunction.
  static const tensorflow::XlaCompiledCpuFunction::StaticData& StaticData() {
    static XlaCompiledCpuFunction::StaticData* kStaticData = [](){
      XlaCompiledCpuFunction::StaticData* data =
        new XlaCompiledCpuFunction::StaticData;
      set_static_data_raw_function(data, __xla_tensorflow_compiler_aot_tests__test_graph_tfmatmul);
      set_static_data_buffer_infos(data, BufferInfos());
      set_static_data_num_buffers(data, kNumBuffers);
      set_static_data_arg_index_table(data, ArgIndexToBufferIndex());
      set_static_data_num_args(data, kNumArgs);
      set_static_data_num_variables(data, kNumVariables);
      set_static_data_result_index(data, kResultIndex);
      set_static_data_arg_names(data, StaticArgNames());
      set_static_data_variable_names(data, StaticVariableNames());
      set_static_data_result_names(data, StaticResultNames());
      set_static_data_program_shape(data, StaticProgramShape());
      set_static_data_hlo_profile_printer_data(
          data, StaticHloProfilePrinterData());
 
      return data;
    }();
    return *kStaticData;
  }

第三步:编写代码调用子计算图(测试)

在tensorflow\compiler\aot\tests写代码,引用头文件,编写使用端代码 my_code.cc。

#define EIGEN_USE_THREADS
#define EIGEN_USE_CUSTOM_THREAD_POOL
 
#include <iostream>
#include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor"
#include "tensorflow/compiler/aot/tests/test_graph_tfmatmul.h" // generated
 
int main(int argc, char** argv) {
  Eigen::ThreadPool tp(2);  // Size the thread pool as appropriate.
  Eigen::ThreadPoolDevice device(&tp, tp.NumThreads());
 
  foo::bar::MatMulComp matmul;
  matmul.set_thread_pool(&device);
 
  // Set up args and run the computation.
  const float args[12] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
  std::copy(args + 0, args + 6, matmul.arg0_data());
  std::copy(args + 6, args + 12, matmul.arg1_data());
  matmul.Run();
 
  // Check result
  if (matmul.result0(0, 0) == 58) {
    std::cout << "Success" << std::endl;
  } else {
    std::cout << "Failed. Expected value 58 at 0,0. Got:"
              << matmul.result0(0, 0) << std::endl;
  }
 
  return 0;
}

第 4 步:创建最终的二进制文件

在此步骤中,将对由 tf_library 生成的库以及第 3 步中编写的代码进行结合,从而创建最终的二进制文件。以下为示例 bazel BUILD 文件。
在这里插入图片描述


# 添加cc_binary,#TF_Library生成的可执行代码然后可以链接到您的代码中。
cc_binary(
    name = "my_binary",
    testonly=1,
    srcs = [
        "my_code.cc",  # include test_graph_tfmatmul.h to access the generated header
    ],
    deps = [
        ":test_graph_tfmatmul",  # link in the generated object file
        "//third_party/eigen3"
    ],
    linkopts = [
          "-lpthread"
    ]
)

然后进行编译, bazel build :my_binary 生成二进制可执行文件 my_binary.exe。

在这里插入图片描述
在这里插入图片描述
第五步: 运行 my_binary.exe

输出 Seccess代表成功

bazel run my_binary

在这里插入图片描述

三、总结

以上就是AOT编译的全过程。和前边调研的AOT流程一样,第一步的配置写好。然后交给tfcompile,经过一系列的编译得到可执行的二进制文件。

编译过程错误百出还耗时,保持耐心。耐心。耐心。。。。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/105403.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自动网络搜索NAS之FBNetV1

1. 摘要 为移动设备设计卷积网络挑战巨大&#xff0c;因为设计空间巨大&#xff0c;现有NAS方法在计算上是昂贵的。另外&#xff0c;之前的工作关注降低FLOPs&#xff0c;但是FLOPs并不总是反应真实的延迟。因此基于differentiable neural architecture search&#xff08;DNA…

sd卡怎么格式化?5个步骤轻松教会你

随着SD卡的广泛使用&#xff0c;总会有各种情况导致SD卡必须要格式化才行。但是格式化有没有办法执行&#xff0c;sd卡怎么格式化&#xff1f;还有人会因为误操作导致的数据丢失。现在&#xff0c;小编就给大家介绍一下怎么格式化SD卡&#xff1f;以及格式化后SD卡数据的恢复方…

VUE3-模板语法《二》

首先看到这张图&#xff0c;左边的结构就不分析了&#xff0c;上一章有说明顺序。 中间红色的部分&#xff0c;分为3块&#xff0c;第一块是模板&#xff0c;里面写html&#xff1b;第二块是脚本语言&#xff0c;里面写js或者ts语言&#xff0c;lang"ts"就是ts语法…

GreatSQL MGR 使用 IPv6 连接

GreatSQL社区原创内容未经授权不得随意使用&#xff0c;转载请联系小编并注明来源。GreatSQL是MySQL的国产分支版本&#xff0c;使用上与MySQL一致。作者&#xff1a;王权富贵文章来源&#xff1a;社区原创 1.概述 本文基于 GreatSQL 8.0.25-16 &#xff0c;以下测试均使用此版…

嵌入式:Load/Store之单寄存器的存取指令

文章目录Load/Store指令分类单寄存器的存取指令1、单字和无符号字节的数据传送指令指令说明指令汇编格式2、半字和有符号字节的数据传送指令指令汇编格式ARM处理器是Load/Store型的&#xff0c;即它对数据的操作是通过将数据从存储器加载到片内寄存器中进行处理&#xff0c;处理…

SuperMap iPortal 对接postgis业务数据库(二):大屏使用接口数据更新图表和地图

本文是SuperMap iPortal 对接postgis业务数据库的第二个步骤&#xff1a;大屏使用接口数据更新图表和地图。 这个步骤可以有两种方式去实现数据的展示和更新如下&#xff1a; 一、使用数据上图构建地图并在大屏中使用 1. 数据上图构建地图 打开iPortal 应用中心的数据上图&a…

教你如何轻松搞定云上打印管理

摘要&#xff1a;加快自主创新&#xff0c;满足数字化用户多场景文印需求。本文分享自华为云社区《有了司印云打印&#xff0c;云上打印管理轻松搞定&#xff01;》&#xff0c;作者&#xff1a;云商店 。 作为与职场和个人办公息息相关的工作场景&#xff0c;打印长期以来都是…

uniapp-uView在离线状态下无法显示icon图标的问题

1、修改uview-ui下的u-icon.vue配置文件&#xff0c;一般目录在 uni_modules\uview-ui\components\u-icon\u-icon.vue 2、源文件引入的是阿里巴巴的icon https://at.alicdn.com/t/font_2225171_8kdcwk4po24.ttf font-face {font-family: uicon-iconfont;src: url(https://at.…

restful风格快速入门

restful风格入门 概述 简介&#xff1a;REST(Representational State Transfer),表现形式状态转换。 传统风格 http://localhost/users/getById?id1 http://localhost/users/saveUser REST风格 http://localhost/users/1 http://localhost/users 对比&#xff1a; 对比可…

spring-boot sentry 不触发事件

按照官网的提示https://docs.sentry.io/platforms/java/guides/spring-boot/performance/ 一步一步的确认&#xff0c;但是最终就是不触发事件 解决过程&#xff1a; 1.开启debug 在properties文件增加一行 sentry.debugtrue2.运行&#xff0c;查看日志输出。 dsn什么的配…

Android代码保护与反调试方案

1、代码保护方案 1.1、Proguard代码混淆 ProGuard是一个开源的Java代码收缩器&#xff0c;优化器&#xff0c;混淆器和预校验器&#xff0c;ProGuard的作用如下&#xff1a; &#xff08;1&#xff09;压缩(Shrink):检查并移除代码中无用的类、字段、方法&#xff1b; &#…

一键回复聊天软件

不论是何种行业&#xff0c;高效工作都是企业一直在追求的&#xff0c;如果在为客户提供服务的过程中&#xff0c;有一个趁手的好工具是可以带来事半功倍的效果的。 前言 随着互联网的发展&#xff0c;越来越多的工作开始转向线上化&#xff0c;通过网络可以满足客户的多种需求…

手写Srping10(实现容器事件监听)

文章目录目标设计项目结构一、实现1、定义事件接口--ApplicationEvent1、定义通用应用上下文事件--ApplicationContextEvent2、定义刷新和关闭事件--ContextClosedEvent、ContextRefreshedEvent2、定义事件监听--ApplicationListener3、定义事件广播器--ApplicationEventMultic…

audio_open函数分析

audio_open() 的作用&#xff0c;就如同它的名字那样&#xff0c;就是打开音频设备。流程图如下&#xff1a; SDL 库播放音频数据有两种方式。 1&#xff0c;调用层定时往 SDL 接口塞数据。 2&#xff0c;设置SDL回调函数&#xff0c;让 SDL 来主动执行回调函数来取数据。 第…

ABAP 字符处理

场景1:是否只包含数字 str1 CO 0123456789 涉及关键字&#xff1a;CO&#xff0c;使用公式 str1 CO str2 。表示 str1 中 的每个字符 在 str2 中都能找到 类比&#xff1a;无 场景2&#xff1a;字符串1 是否 包含 字符串2 DATA str1 TYPE STRING VALUE hello world. DATA …

Pytest测试框架搭建需求及实现方案

目录 框架需求及实现方案 框架需求 实现方案 支持接口自动化、Web UI自动化及App自动化 可以批量运行用例并生成测试报告 测试完成发送邮件 提供灵活的运行方式&#xff0c;如按功能模块运行、按脚本运行、按用例等级运行等等 提供运行日志方便定位问题 支持切换环境 …

李沐精读论文:MAE 《Masked Autoencoders Are Scalable Vision Learners》

论文&#xff1a;Masked Autoencoders Are Scalable Vision Learners 别再无聊地吹捧了&#xff0c;一起来动手实现 MAE(Masked Autoencoders Are Scalable Vision Learners) 玩玩吧&#xff01; - 知乎 参考博文&#xff1a;MAE 论文逐段精读【论文精读】 - 哔哩哔哩 神洛华…

QT 学习笔记(十)

文章目录一、绘图1. 理论知识储备2. 画背景图3. 简单绘图4. 手动刷新窗口二、绘图实现代码1. 主窗口头文件 widget.h2. 主窗口头文件 widget.cpp由于每次代码都是在原有程序上修改&#xff0c;因此除了新建项目&#xff0c;不然一般会在学完后统一展示代码。 提示&#xff1a;具…

【Python机器学习】卷积神经网络卷积层、池化层、Flatten层、批标准化层的讲解(图文解释)

卷积神经网络 卷积神经网络&#xff08;convolutional neural network, CNN&#xff09;在提出之初被成功应用于手写字符图像识别&#xff0c;2012年的AlexNet网络在图像分类任务中取得成功&#xff0c;此后&#xff0c;卷积神经网络发展迅速&#xff0c;现在已经被广泛应用于…

怎样在Odoo 16中启用完整的财务功能

Odoo是目前市场上最好的ERP软件之一。Odoo提供两种类型的版本&#xff0c;社区版和企业版。Odoo社区版是由开源软件支持的免费基本版。Odoo社区版本中没有一些模块和功能。但企业版付费版&#xff0c;升级版更适合更高的价值。Odoo企业版具有无限的功能支持和完整的功能。性能和…