tritonserver学习之二:tritonserver编译
tritonserver学习之三:tritonserver运行流程
? ? ?backend是triton中的核心部件,它负责处理来自客户端的推理请求,并将请求转发给相应的模型进行推理。每个backend都对应一个特定的深度学习框架,例如TensorFlow、PyTorch、ONNX、paddle等。当客户端发送推理请求时,Triton Server会根据请求的模型和版本信息,将请求路由到相应的backend进行处理。
? ? ?大家知道,triton serve的每个模型都有个配置文件:config.pbtxt,这个配置中,明确了模型的meta信息,当然也包含了对应backend信息,例如代码中的官方模型simple的配置如下:
name: "simple"
platform: "tensorflow_graphdef"
max_batch_size: 8
input [
{
name: "INPUT0"
data_type: TYPE_INT32
dims: [ 16 ]
},
{
name: "INPUT1"
data_type: TYPE_INT32
dims: [ 16 ]
}
]
output [
{
name: "OUTPUT0"
data_type: TYPE_INT32
dims: [ 16 ]
},
{
name: "OUTPUT1"
data_type: TYPE_INT32
dims: [ 16 ]
}
]
看到这个配置可能会有疑惑,配置中没有设置banckend的信息,哪triton是如何找到对应的backend的呢,答案是通过【platform】这个字段找到的,为什么是通过这个字段找到的,先不细讲,大概说一下,先看如下代码,位于core代码库,位于core/src/constants.h:
constexpr char kTensorFlowGraphDefPlatform[] = "tensorflow_graphdef";
constexpr char kTensorFlowSavedModelPlatform[] = "tensorflow_savedmodel";
constexpr char kTensorFlowGraphDefFilename[] = "model.graphdef";
constexpr char kTensorFlowSavedModelFilename[] = "model.savedmodel";
constexpr char kTensorFlowBackend[] = "tensorflow";
【platform】这个字段的设置是要求的,对于TensorFlow模型,云端推理上线主要有两种格式,分别为:
GraphDef
SavedModel(推荐)
对应的【platform】字段是固定的,分别为:tensorflow_graphdef和tensorflow_savedmodel,triton就是通过这两个字符串来找到对应的backend的。
triton所有backend的实现,包括pytorch_backend、paddle_backend等所有backend的实现,实现原理都是一样的,大家可以看一下源码,主要是实现7个api:
TRITONBACKEND_Initialize:创建ModelState对象。
TRITONBACKEND_ModelInitialize
TRITONBACKEND_ModelInstanceInitialize:创建ModelInstanceState对象,可以通过这个对象调用LoadModel函数
TRITONBACKEND_ModelInstanceExecute
TRITONBACKEND_ModelInstanceFinalize
TRITONBACKEND_ModelFinalize
TRITONBACKEND_Finalize
架构如下:
?linux系统提供一套api,实现了动态加载so,triton中,对各个backend库的加载使用的就是这种方式,api的原型如下:
void *dlopen(const char *filename, int flag);
char *dlerror(void);
void *dlsym(void *handle, const char *symbol);
int dlclose(void *handle);
使用上面函数之前,需要包含头文件:
#include <dlfcn.h>
dlopen:以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。
dlsym:在打开的动态库中查找符号的值,其不仅能够获取函数地址,也能够获取全局变量地址,非常之方便。
dlclose:关闭动态库。
dlerror:返回一个描述最后一次调用dlopen、dlsym,或dlclose的错误信息的字符串。
tirton中,对banckend的管理,主要在core代码中,代码位于:core/src/backend_manager.cc中,主要是两个类:
class TritonBackendManager {}
class TritonBackend {}
这两个类,严格来说,只是banckend的一个proxy,这两个类最重要的就是获取到模型对应backend的7个api,获取api指针后,用于之后的推理。
TritonBackendManager类的定义如下:
class TritonBackendManager {
public:
static Status Create(std::shared_ptr<TritonBackendManager>* manager);
Status CreateBackend(
const std::string& name, const std::string& dir,
const std::string& libpath,
const triton::common::BackendCmdlineConfig& backend_cmdline_config,
bool is_python_based_backend, std::shared_ptr<TritonBackend>* backend);
Status BackendState(
std::unique_ptr<
std::unordered_map<std::string, std::vector<std::string>>>*
backend_state);
private:
DISALLOW_COPY_AND_ASSIGN(TritonBackendManager);
TritonBackendManager() = default;
std::unordered_map<std::string, std::shared_ptr<TritonBackend>> backend_map_;
};
Create:这个函数比较好理解,静态函数,创建?TritonBackendManager类对象。
CreateBackend:根据backend名称、so路径、配置,创建对应的backend,如果TRITONBACKEND_Initialize函数指针不为空,则运行该函数。
BackendState获取backend配置信息,例如:
这个类直接和各个backend进行交互,加载backend动态库,同时获取对应的7个api函数指针。
class TritonBackend {
public:
struct Attribute {
Attribute()
: exec_policy_(TRITONBACKEND_EXECUTION_BLOCKING),
parallel_instance_loading_(false)
{
}
TRITONBACKEND_ExecutionPolicy exec_policy_;
std::vector<inference::ModelInstanceGroup> preferred_groups_;
// Whether the backend supports loading model instances in parallel
bool parallel_instance_loading_;
};
typedef TRITONSERVER_Error* (*TritonModelInitFn_t)(
TRITONBACKEND_Model* model);
typedef TRITONSERVER_Error* (*TritonModelFiniFn_t)(
TRITONBACKEND_Model* model);
typedef TRITONSERVER_Error* (*TritonModelInstanceInitFn_t)(
TRITONBACKEND_ModelInstance* instance);
typedef TRITONSERVER_Error* (*TritonModelInstanceFiniFn_t)(
TRITONBACKEND_ModelInstance* instance);
typedef TRITONSERVER_Error* (*TritonModelInstanceExecFn_t)(
TRITONBACKEND_ModelInstance* instance, TRITONBACKEND_Request** requests,
const uint32_t request_cnt);
static Status Create(
const std::string& name, const std::string& dir,
const std::string& libpath,
const triton::common::BackendCmdlineConfig& backend_cmdline_config,
std::shared_ptr<TritonBackend>* backend);
~TritonBackend();
const std::string& Name() const { return name_; }
const std::string& Directory() const { return dir_; }
const std::string& LibPath() const { return libpath_; }
const TritonServerMessage& BackendConfig() const { return backend_config_; }
const Attribute& BackendAttributes() const { return attributes_; }
TRITONBACKEND_ExecutionPolicy ExecutionPolicy() const
{
return attributes_.exec_policy_;
}
void SetExecutionPolicy(const TRITONBACKEND_ExecutionPolicy policy)
{
attributes_.exec_policy_ = policy;
}
void* State() { return state_; }
void SetState(void* state) { state_ = state; }
bool IsPythonBackendBased() { return is_python_based_backend_; }
void SetPythonBasedBackendFlag(bool is_python_based_backend)
{
is_python_based_backend_ = is_python_based_backend;
}
TritonModelInitFn_t ModelInitFn() const { return model_init_fn_; }
TritonModelFiniFn_t ModelFiniFn() const { return model_fini_fn_; }
TritonModelInstanceInitFn_t ModelInstanceInitFn() const
{
return inst_init_fn_;
}
TritonModelInstanceFiniFn_t ModelInstanceFiniFn() const
{
return inst_fini_fn_;
}
TritonModelInstanceExecFn_t ModelInstanceExecFn() const
{
return inst_exec_fn_;
}
private:
typedef TRITONSERVER_Error* (*TritonBackendInitFn_t)(
TRITONBACKEND_Backend* backend);
typedef TRITONSERVER_Error* (*TritonBackendFiniFn_t)(
TRITONBACKEND_Backend* backend);
typedef TRITONSERVER_Error* (*TritonBackendAttriFn_t)(
TRITONBACKEND_Backend* backend,
TRITONBACKEND_BackendAttribute* backend_attributes);
TritonBackend(
const std::string& name, const std::string& dir,
const std::string& libpath, const TritonServerMessage& backend_config);
void ClearHandles();
Status LoadBackendLibrary();
Status UpdateAttributes();
// The name of the backend.
const std::string name_;
// Full path to the directory holding backend shared library and
// other artifacts.
const std::string dir_;
// Full path to the backend shared library.
const std::string libpath_;
bool is_python_based_backend_;
// Backend configuration as JSON
TritonServerMessage backend_config_;
// backend attributes
Attribute attributes_;
// dlopen / dlsym handles
void* dlhandle_;
TritonBackendInitFn_t backend_init_fn_;
TritonBackendFiniFn_t backend_fini_fn_;
TritonBackendAttriFn_t backend_attri_fn_;
TritonModelInitFn_t model_init_fn_;
TritonModelFiniFn_t model_fini_fn_;
TritonModelInstanceInitFn_t inst_init_fn_;
TritonModelInstanceFiniFn_t inst_fini_fn_;
TritonModelInstanceExecFn_t inst_exec_fn_;
// Opaque state associated with the backend.
void* state_;
}
create函数:静态函数,创建该类的对象。
其他函数基本都是围绕加载so,获取api函数指针相关。
以上就是backend相关的知识。
? ? ? triton支持了目前市场上所有主流的深度学习框架,对于paddle,官方镜像只有21.10版本支持,其他版本都不支持,如果需要在新版本支持,则需要自己进行编译,可以参考前面编写的博客,编译部分:tritonserver学习之二:tritonserver编译-CSDN博客,博客中介绍的backend的类,主要还是一个proxy的作用,直接调用深度学习api的还是对应的backend,大家可以自己学习理解下,不清楚的,欢迎评论交流。欢迎各位同行关注一下公众号: