tritonserver学习之四:命令行解析

tritonserver学习之一:triton使用流程

tritonserver学习之二:tritonserver编译

tritonserver学习之三:tritonserver运行流程

tritonserver学习之五:backend实现机制

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

tritonserver学习之七:cache管理器

tritonserver学习之八:redis_caches实践

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

1、命令行解析的两个函数

1.1 getopt

int getopt(intargc, char * const argv[], const char *optstring);

getopt用来解析命令行参数,但是只能解析短选项,例如:-b 100,不能解析长选项--prefix。

参数说明:

argc:main()函数传递过来的参数的个数
argv:main()函数传递过来的参数的字符串指针数组
optstring:选项字符串,告知 getopt()可以处理哪个选项以及哪个选项需要参数

重点说明optstring字段:

char *optstring = “ab:c::”;
单个字符a         表示选项a没有参数            格式:-a即可,不加参数
单字符加冒号b:     表示选项b有且必须加参数      格式:-b 100或-b100, -b=100这种格式是错误的
单字符加2个冒号c::   表示选项c可以有,也可以无     格式:-c200,其它格式错误

函数返回值:

如果选项成功找到,返回选项字母;
如果所有命令行选项都解析完毕,返回 -1;
如果遇到选项字符不在 optstring 中,返回字符 '?';
如果遇到丢失参数,那么返回值依赖于 optstring 中第一个字符,如果第一个字符是 ':' 则返回':',
否则返回'?'并提示出错误信息。

几个重要的全局变量:

optarg —— 指向当前选项参数(如果有)的指针。
optind —— 再次调用 getopt() 时的下一个 argv指针的索引。
optopt —— 最后一个未知选项。
opterr ­—— 如果不希望getopt()打印出错信息,则只要将全域变量opterr设为0即可。

示例:

#include <iostream>
#include <thread>
#include<getopt.h>
 
int main(int argc, char *argv[]) 
{
    unsigned int n = std::thread::hardware_concurrency();
    std::cout << " concurrent threads are supported = " << n << std::endl;
    int opt;
    std::string str = "a::b:c:d";
    while ((opt = getopt(argc, argv, str.data()))!= -1)
    {  
        printf("opt = %c\t\t", opt);
        printf("optarg = %s\t\t",optarg);
        printf("optind = %d\t\t",optind);
        printf("argv[optind] = %s\n",argv[optind]);
    }
}

运行结果:

liupeng@liupengdeMacBook-Pro Downloads % ./a.out -a100 -b 200 -c200 -d
 concurrent threads are supported = 8
opt = a        optarg = 100        optind = 2        argv[optind] = -b
opt = b        optarg = 200        optind = 4        argv[optind] = -c200
opt = c        optarg = 200        optind = 5        argv[optind] = -d
opt = d        optarg = (null)        optind = 6        argv[optind] = (null)

选项a是可选参数,可以不带参数。

1.2 getopt_long

triton中使用的是该函数,getopt_long包含了getopt函数的所有功能,并且可以指定长选项。

int getopt_long(int argc, char * const argv[], const char *optstring,
                          const struct option *longopts, int*longindex);

参数说明:

longopts    指明了长参数的名称和属性
longindex   如果longindex非空,它指向的变量将记录当前找到参数符合longopts里的第几个元素的描述,即是longopts的下标值

struct option结构体:

struct option {
    const char  *name;       /* 参数名称 */
    int          has_arg;    /* 指明是否带有参数 */
    int          *flag;      /* flag=NULL时,返回val;不为空时,*flag=val,返回0 */
    int          val;        /* 用于指定函数找到选项的返回值或flag非空时指定*flag的值 */
};

函数返回值:

对于短选项,返回值同getopt函数;对于长选项,如果flag是NULL,返回val,否则返回0;
对于错误情况返回值同getopt函数

has_arg参数说明: 

has_arg  指明是否带参数值,其数值可选:
no_argument         表明长选项不带参数,如:--name, --help
required_argument  表明长选项必须带参数,如:--prefix /root或 --prefix=/root
optional_argument  表明长选项的参数是可选的,如:--help或 –prefix=/root,其它都是错误

代码示例:

#include <iostream>
#include <thread>
#include <getopt.h>
 
int main(int argc, char *argv[]) 
{
    unsigned int n = std::thread::hardware_concurrency();
    std::cout << " concurrent threads are supported = " << n << std::endl;
    int opt;
    std::string str = "a::b:c:d";
    static struct option long_options[] =
    {  
        {"reqarg", required_argument,NULL, 'r'},
        {"optarg", optional_argument,NULL, 'o'},
        {"noarg",  no_argument,         NULL,'n'},
        {NULL,     0,                      NULL, 0},
    }; 
    int option_index;
    while((opt =getopt_long(argc,argv,str.data(),long_options,&option_index))!= -1)
    {  
        printf("opt = %c\t\t", opt);
        printf("optarg = %s\t\t",optarg);
        printf("optind = %d\t\t",optind);
        printf("argv[optind] =%s\t\t", argv[optind]);
        printf("option_index = %d\n",option_index);
    }  
}

运行结果:

liupeng@liupengdeMacBook-Pro Downloads % ./a.out -b 200 -d --reqarg 100 --optarg 200
 concurrent threads are supported = 8
opt = b        optarg = 200        optind = 3        argv[optind] =-d        option_index = 1
opt = d        optarg = (null)        optind = 4        argv[optind] =--reqarg        option_index = 1
opt = r        optarg = 100        optind = 6        argv[optind] =--optarg        option_index = 0
opt = o        optarg = (null)        optind = 7        argv[optind] =200        option_index = 1
liupeng@liupengdeMacBook-Pro Downloads %

2、triton命令行处理

tritonserver版本为当前最新:2.36.0

2.1 TritonParser类-命令注册

TritonParser类的构造函数,实现了支持的命令行的注册。

构造函数位于:command_line_parser.cc文件的L814,构造函数调用了SetupOptionGroups()函数。

void
TritonParser::SetupOptionGroups()
{
  SetupOptions();
  option_groups_.emplace_back(GLOBAL_OPTION_GROUP, global_options_);
  option_groups_.emplace_back("Server", server_options_);
  option_groups_.emplace_back("Logging", logging_options_);
  option_groups_.emplace_back("Model Repository", model_repo_options_);
  option_groups_.emplace_back("HTTP", http_options_);
  option_groups_.emplace_back("GRPC", grpc_options_);
  option_groups_.emplace_back("Sagemaker", sagemaker_options_);
  option_groups_.emplace_back("Vertex", vertex_options_);
  option_groups_.emplace_back("Metrics", metric_options_);
  option_groups_.emplace_back("Tracing", tracing_options_);
  option_groups_.emplace_back("Backend", backend_options_);
  option_groups_.emplace_back("Repository Agent", repo_agent_options_);
  option_groups_.emplace_back("Response Cache", cache_options_);
  option_groups_.emplace_back("Rate Limiter", rate_limiter_options_);
  option_groups_.emplace_back(
      "Memory/Device Management", memory_device_options_);
  option_groups_.emplace_back("DEPRECATED", deprecated_options_);
}

具体实现:

void
TritonParser::SetupOptions()
{
  global_options_.push_back(
      {OPTION_HELP, "help", Option::ArgNone, "Print usage"});

  server_options_.push_back(
      {OPTION_ID, "id", Option::ArgStr, "Identifier for this server."});
  server_options_.push_back(
      {OPTION_EXIT_TIMEOUT_SECS, "exit-timeout-secs", Option::ArgInt,
       "Timeout (in seconds) when exiting to wait for in-flight inferences to "
       "finish. After the timeout expires the server exits even if inferences "
       "are still in flight."});

}

global_options_、server_options_的定义如下:

std::vector<Option> global_options_;
std::vector<Option> server_options_;

其中,Option为命令行的结构体:

// Command-line options
struct Option {
  static constexpr const char* ArgNone = "";
  static constexpr const char* ArgBool = "boolean";
  static constexpr const char* ArgFloat = "float";
  static constexpr const char* ArgInt = "integer";
  static constexpr const char* ArgStr = "string";

  Option(int id, std::string flag, std::string arg_desc, std::string desc)
      : id_(id), flag_(flag), arg_desc_(arg_desc), desc_(desc)
  {
  }

  struct option GetLongOption() const
  {
    struct option lo {
      flag_.c_str(), (!arg_desc_.empty()) ? required_argument : no_argument,
          nullptr, id_
    };
    return lo;
  }

  const int id_;
  const std::string flag_;
  const std::string arg_desc_;
  const std::string desc_;
};

该结构共4个字段,用于对命令行进行描述,GetLongOption函数完成triton Option到系统struct option结构的转换,到此,命令行完成注册,所有支持的命令行全部保存到了option_groups_,这个vector中。

2.2 TritonParser类-命令解析

命令行解析函数:

std::pair<TritonServerParameters, std::vector<char*>>
TritonParser::Parse(int argc, char** argv)

triton中解析命令行设计的方案就是使用getopt_long函数,因此第一步是将支持的命令行完成从triton系统中Option结构到系统struct option结构的转换:

  std::vector<struct option> long_options;
  for (const auto& group : option_groups_) {
    for (const auto& o : group.second) {
      long_options.push_back(o.GetLongOption());
    }
  }
  long_options.push_back({nullptr, 0, nullptr, 0});

这几行代码位于:command_line_parser.cc文件的L1167,接下来就是使用getopt_long函数,循环对命令行进行解析,解析的命令行参数值,全部放在了结构体lparams这个TritonServerParameters结构体变量中。

3、main函数中调用

int
main(int argc, char** argv)
{
  // Parse command-line to create the options for the inference
  // server.
  triton::server::TritonParser tp;
  try {
    auto res = tp.Parse(argc, argv);
    g_triton_params = res.first;
    g_triton_params.CheckPortCollision();
  }
  catch (const triton::server::ParseException& pe) {
    std::cerr << pe.what() << std::endl;
    std::cerr << "Usage: tritonserver [options]" << std::endl;
    std::cerr << tp.Usage() << std::endl;
    exit(1);
  }

  .........

}

代码走到g_triton_params = res.first;这一行,就已经获取到了用户输入的所有参数值,当获取到所有参数之后,调用了TritonServerParameters结构成员函数:g_triton_params.BuildTritonServerOptions(),将这些参数设置到TritonServerOptions这个核心类成员中。

以上就是triton命令行注册、解析部分,希望能帮到各位正在学习triton的同学。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值