当前位置:   article > 正文

tritonserver学习之五:backend实现机制_triton backend

triton backend

tritonserver学习之一:triton使用流程

tritonserver学习之二:tritonserver编译

tritonserver学习之三:tritonserver运行流程

tritonserver学习之四:命令行解析

tritonserver学习之六:自定义c++、python custom backend实践

tritonserver学习之七:cache管理器

 tritonserver学习之八:redis_caches实践

tritonserver学习之九:tritonserver grpc异步模式

1、预备知识

1.1 backend概念

     backend是triton中的核心部件,它负责处理来自客户端的推理请求,并将请求转发给相应的模型进行推理。每个backend都对应一个特定的深度学习框架,例如TensorFlow、PyTorch、ONNX、paddle等。当客户端发送推理请求时,Triton Server会根据请求的模型和版本信息,将请求路由到相应的backend进行处理。

1.2 模型配置

     大家知道,triton serve的每个模型都有个配置文件:config.pbtxt,这个配置中,明确了模型的meta信息,当然也包含了对应backend信息,例如代码中的官方模型simple的配置如下:

  1. name: "simple"
  2. platform: "tensorflow_graphdef"
  3. max_batch_size: 8
  4. input [
  5. {
  6. name: "INPUT0"
  7. data_type: TYPE_INT32
  8. dims: [ 16 ]
  9. },
  10. {
  11. name: "INPUT1"
  12. data_type: TYPE_INT32
  13. dims: [ 16 ]
  14. }
  15. ]
  16. output [
  17. {
  18. name: "OUTPUT0"
  19. data_type: TYPE_INT32
  20. dims: [ 16 ]
  21. },
  22. {
  23. name: "OUTPUT1"
  24. data_type: TYPE_INT32
  25. dims: [ 16 ]
  26. }
  27. ]

看到这个配置可能会有疑惑,配置中没有设置banckend的信息,哪triton是如何找到对应的backend的呢,答案是通过【platform】这个字段找到的,为什么是通过这个字段找到的,先不细讲,大概说一下,先看如下代码,位于core代码库,位于core/src/constants.h:

  1. constexpr char kTensorFlowGraphDefPlatform[] = "tensorflow_graphdef";
  2. constexpr char kTensorFlowSavedModelPlatform[] = "tensorflow_savedmodel";
  3. constexpr char kTensorFlowGraphDefFilename[] = "model.graphdef";
  4. constexpr char kTensorFlowSavedModelFilename[] = "model.savedmodel";
  5. constexpr char kTensorFlowBackend[] = "tensorflow";

【platform】这个字段的设置是要求的,对于TensorFlow模型,云端推理上线主要有两种格式,分别为:

  1. GraphDef
  2. SavedModel(推荐)

对应的【platform】字段是固定的,分别为:tensorflow_graphdef和tensorflow_savedmodel,triton就是通过这两个字符串来找到对应的backend的。

1.3 backend实现简介

triton所有backend的实现,包括pytorch_backend、paddle_backend等所有backend的实现,实现原理都是一样的,大家可以看一下源码,主要是实现7个api:

  1. TRITONBACKEND_Initialize:创建ModelState对象。
  2. TRITONBACKEND_ModelInitialize
  3. TRITONBACKEND_ModelInstanceInitialize:创建ModelInstanceState对象,可以通过这个对象调用LoadModel函数
  4. TRITONBACKEND_ModelInstanceExecute
  5. TRITONBACKEND_ModelInstanceFinalize
  6. TRITONBACKEND_ModelFinalize
  7. TRITONBACKEND_Finalize

架构如下:

1.4 dlopen系列函数

 linux系统提供一套api,实现了动态加载so,triton中,对各个backend库的加载使用的就是这种方式,api的原型如下:

  1. void *dlopen(const char *filename, int flag);
  2. char *dlerror(void);
  3. void *dlsym(void *handle, const char *symbol);
  4. int dlclose(void *handle);

使用上面函数之前,需要包含头文件:

#include <dlfcn.h>

dlopen:以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。

dlsym:在打开的动态库中查找符号的值,其不仅能够获取函数地址,也能够获取全局变量地址,非常之方便。

dlclose:关闭动态库。

dlerror:返回一个描述最后一次调用dlopen、dlsym,或dlclose的错误信息的字符串。

2、backend实现

tirton中,对banckend的管理,主要在core代码中,代码位于:core/src/backend_manager.cc中,主要是两个类:

  1. class TritonBackendManager {}
  2. class TritonBackend {}

这两个类,严格来说,只是banckend的一个proxy,这两个类最重要的就是获取到模型对应backend的7个api,获取api指针后,用于之后的推理。

2.1 TritonBackendManager类说明

TritonBackendManager类的定义如下:

  1. class TritonBackendManager {
  2. public:
  3. static Status Create(std::shared_ptr<TritonBackendManager>* manager);
  4. Status CreateBackend(
  5. const std::string& name, const std::string& dir,
  6. const std::string& libpath,
  7. const triton::common::BackendCmdlineConfig& backend_cmdline_config,
  8. bool is_python_based_backend, std::shared_ptr<TritonBackend>* backend);
  9. Status BackendState(
  10. std::unique_ptr<
  11. std::unordered_map<std::string, std::vector<std::string>>>*
  12. backend_state);
  13. private:
  14. DISALLOW_COPY_AND_ASSIGN(TritonBackendManager);
  15. TritonBackendManager() = default;
  16. std::unordered_map<std::string, std::shared_ptr<TritonBackend>> backend_map_;
  17. };

Create:这个函数比较好理解,静态函数,创建 TritonBackendManager类对象。

CreateBackend:根据backend名称、so路径、配置,创建对应的backend,如果TRITONBACKEND_Initialize函数指针不为空,则运行该函数。

BackendState获取backend配置信息,例如:

2.2 class TritonBackend类

这个类直接和各个backend进行交互,加载backend动态库,同时获取对应的7个api函数指针。

  1. class TritonBackend {
  2. public:
  3. struct Attribute {
  4. Attribute()
  5. : exec_policy_(TRITONBACKEND_EXECUTION_BLOCKING),
  6. parallel_instance_loading_(false)
  7. {
  8. }
  9. TRITONBACKEND_ExecutionPolicy exec_policy_;
  10. std::vector<inference::ModelInstanceGroup> preferred_groups_;
  11. // Whether the backend supports loading model instances in parallel
  12. bool parallel_instance_loading_;
  13. };
  14. typedef TRITONSERVER_Error* (*TritonModelInitFn_t)(
  15. TRITONBACKEND_Model* model);
  16. typedef TRITONSERVER_Error* (*TritonModelFiniFn_t)(
  17. TRITONBACKEND_Model* model);
  18. typedef TRITONSERVER_Error* (*TritonModelInstanceInitFn_t)(
  19. TRITONBACKEND_ModelInstance* instance);
  20. typedef TRITONSERVER_Error* (*TritonModelInstanceFiniFn_t)(
  21. TRITONBACKEND_ModelInstance* instance);
  22. typedef TRITONSERVER_Error* (*TritonModelInstanceExecFn_t)(
  23. TRITONBACKEND_ModelInstance* instance, TRITONBACKEND_Request** requests,
  24. const uint32_t request_cnt);
  25. static Status Create(
  26. const std::string& name, const std::string& dir,
  27. const std::string& libpath,
  28. const triton::common::BackendCmdlineConfig& backend_cmdline_config,
  29. std::shared_ptr<TritonBackend>* backend);
  30. ~TritonBackend();
  31. const std::string& Name() const { return name_; }
  32. const std::string& Directory() const { return dir_; }
  33. const std::string& LibPath() const { return libpath_; }
  34. const TritonServerMessage& BackendConfig() const { return backend_config_; }
  35. const Attribute& BackendAttributes() const { return attributes_; }
  36. TRITONBACKEND_ExecutionPolicy ExecutionPolicy() const
  37. {
  38. return attributes_.exec_policy_;
  39. }
  40. void SetExecutionPolicy(const TRITONBACKEND_ExecutionPolicy policy)
  41. {
  42. attributes_.exec_policy_ = policy;
  43. }
  44. void* State() { return state_; }
  45. void SetState(void* state) { state_ = state; }
  46. bool IsPythonBackendBased() { return is_python_based_backend_; }
  47. void SetPythonBasedBackendFlag(bool is_python_based_backend)
  48. {
  49. is_python_based_backend_ = is_python_based_backend;
  50. }
  51. TritonModelInitFn_t ModelInitFn() const { return model_init_fn_; }
  52. TritonModelFiniFn_t ModelFiniFn() const { return model_fini_fn_; }
  53. TritonModelInstanceInitFn_t ModelInstanceInitFn() const
  54. {
  55. return inst_init_fn_;
  56. }
  57. TritonModelInstanceFiniFn_t ModelInstanceFiniFn() const
  58. {
  59. return inst_fini_fn_;
  60. }
  61. TritonModelInstanceExecFn_t ModelInstanceExecFn() const
  62. {
  63. return inst_exec_fn_;
  64. }
  65. private:
  66. typedef TRITONSERVER_Error* (*TritonBackendInitFn_t)(
  67. TRITONBACKEND_Backend* backend);
  68. typedef TRITONSERVER_Error* (*TritonBackendFiniFn_t)(
  69. TRITONBACKEND_Backend* backend);
  70. typedef TRITONSERVER_Error* (*TritonBackendAttriFn_t)(
  71. TRITONBACKEND_Backend* backend,
  72. TRITONBACKEND_BackendAttribute* backend_attributes);
  73. TritonBackend(
  74. const std::string& name, const std::string& dir,
  75. const std::string& libpath, const TritonServerMessage& backend_config);
  76. void ClearHandles();
  77. Status LoadBackendLibrary();
  78. Status UpdateAttributes();
  79. // The name of the backend.
  80. const std::string name_;
  81. // Full path to the directory holding backend shared library and
  82. // other artifacts.
  83. const std::string dir_;
  84. // Full path to the backend shared library.
  85. const std::string libpath_;
  86. bool is_python_based_backend_;
  87. // Backend configuration as JSON
  88. TritonServerMessage backend_config_;
  89. // backend attributes
  90. Attribute attributes_;
  91. // dlopen / dlsym handles
  92. void* dlhandle_;
  93. TritonBackendInitFn_t backend_init_fn_;
  94. TritonBackendFiniFn_t backend_fini_fn_;
  95. TritonBackendAttriFn_t backend_attri_fn_;
  96. TritonModelInitFn_t model_init_fn_;
  97. TritonModelFiniFn_t model_fini_fn_;
  98. TritonModelInstanceInitFn_t inst_init_fn_;
  99. TritonModelInstanceFiniFn_t inst_fini_fn_;
  100. TritonModelInstanceExecFn_t inst_exec_fn_;
  101. // Opaque state associated with the backend.
  102. void* state_;
  103. }

create函数:静态函数,创建该类的对象。

其他函数基本都是围绕加载so,获取api函数指针相关。

以上就是backend相关的知识。

3、总结

      triton支持了目前市场上所有主流的深度学习框架,对于paddle,官方镜像只有21.10版本支持,其他版本都不支持,如果需要在新版本支持,则需要自己进行编译,可以参考前面编写的博客,编译部分:tritonserver学习之二:tritonserver编译-CSDN博客,博客中介绍的backend的类,主要还是一个proxy的作用,直接调用深度学习api的还是对应的backend,大家可以自己学习理解下,不清楚的,欢迎评论交流。欢迎各位同行关注一下公众号:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/351807
推荐阅读
相关标签
  

闽ICP备14008679号