全部产品
云市场

自定义Processor开发及应用

更新时间:2019-07-09 23:34:30

一、名词解释

Processor:Processor是包含了预测逻辑的程序包,用户请求经过processor处理后返回到客户端,processor的逻辑中包含了模型加载请求预测两部分逻辑,目前EAS提供了一些通用的processor,如pmml,tensorflow,caffe等,如用户需要自定义预测逻辑,则需要根据processor的开发标准开发一个processor。


二、自定义processor开发

1. 使用自定义processor部署前提

为了保护用户的模型及服务安全,自定义processor无法在公共资源组中使用,使用前请先创建专属资源组image.png


2. QuickStart Demo


https://github.com/pai-eas/pai-prediction-example


上述项目包含两个自定义processor的demo:

  • [echo] 请求时将用户输入原样返回,同时返回模型中的文件列表
  • [image_classification] mnist文本分类,输入mnist jpg图片,返回图片分类类别


编译方法见project README,每个processor的本地调试方法见各自目录下的README


3. C/C++ Processor

使用c/c++开发processor,用户需要定义两个函数Load()和Process(),分别用于在服务初始化的时候加载模型和每次收到用户请求时对请求进行相应的处理后返回结果,两个函数的声明如下:


  1. void *initialize(const char *model_entry, const char *model_config, int *state)

参数名字

参数类型

参数描述

model_entry

输入参数

对应创建服务时配置文件中的model_entry字段,用户可传一个文件名,如randomforest.pmml,也可传一个目录,如./model

model_config

输入参数

对应创建服务时配置文件中的model_config字段,模型自定义的配置信息

state

输出参数

模型加载状态返回值,设置为0表示加载成功,否则表示加载失败


返回值

为用户自定义的model变量的内存地址,可为任意类型,由用户自定义


  1. int process(void *model_buf, const void *input_data, int input_size,void **output_data, int *output_size)

参数名字

参数类型

参数描述

model_buf

输入参数

initialize()函数返回的模型的内存地址

input_data

输入参数

用户的数入数据,可为任意字符串或binary数据

input_size

输入参数

用户的输入数据的长度

output_data

输出参数

Processor返回的数据,需在堆上分配内存,模型会负责释放

output_size

输出参数

Processor返回的数据长度


返回值

返回0或200表示成功,可直接返回http错误码,若返回不识别的http错误码,则自动转换为http 400 error

C/C++ Processor示例

下面是一个简单的示例,未加载任何模型数据,预测服务将用户请求直接返回给客户端。

  1. #include <stdio.h>
  2. #include <string.h>
  3. extern "C" {
  4. void *initialize(const char *model_entry, const char *model_config, int *state)
  5. {
  6. *state = 0;
  7. return NULL;
  8. }
  9. int process(void *model_buf, const void *input_data, int input_size,
  10. void **output_data, int *output_size)
  11. {
  12. if (inputSize == 0) {
  13. const char *errmsg = "input data should not be empty";
  14. *outputData = strndup(errmsg, strlen(errmsg));
  15. *outputSize = strlen(errmsg);
  16. return 400;
  17. }
  18. *outputData = strndup((char *)inputData, inputSize);
  19. *outputSize = inputSize;
  20. return 200;
  21. }
  22. }


该processor未读取任何模型信息,将用户输入原样输出给用户,可通过下面的Makefile编译成一个.so

  1. CC=g++
  2. CCFLAGS=-I./ -D_GNU_SOURCE -Wall -g -fPIC
  3. LDFLAGS= -shared -Wl,-rpath=./
  4. OBJS=processor.o
  5. TARGET=libpredictor.so
  6. all: $(TARGET)
  7. $(TARGET): $(OBJS)
  8. $(CC) -o $(TARGET) $(OBJS) $(LDFLAGS) -L./
  9. %.o: %.cc
  10. $(CC) $(CCFLAGS) -c $< -o $@
  11. clean:
  12. rm -f $(TARGET) $(OBJS)


若有其它依赖的.so,务必在Makefile中添加-rpath选项,指定.so的搜索目录,rpath原理可参考https://en.wikipedia.org/wiki/Rpath


4. Java Processor

java的processor一样简单,仅需要定义一个类,除构造函数外,也是只需要Load()和Process()两个函数即可,类的原型如下:


  1. package com.alibaba.eas;
  2. import java.util.*;
  3. public class TestProcessor {
  4. public TestProcessor(String modelEntry, String modelConfig) {
  5. /* 传递模型文件名,可做一些初始化的工作 */
  6. }
  7. public void Load() {
  8. /* 根据模型名加载模型信息 */
  9. }
  10. public byte[] Process(byte[] input) {
  11. /* 对输入数据进行预测处理,返回结果,目前支持byte[]和String,推荐使用byte[],避免编码问题 */
  12. }
  13. public static void main(String[] args) {
  14. /* 主函数非必须,可用于本地单机验证类的功能 */
  15. }
  16. }


中间抛出异常时框架会捕捉到抛出的异常,并将Exception中的message作为错误信息返回给客户端,同时http响应400,用户也可以自己捕获异常,然后输出自己的异常错误信息,如下:


  1. try{
  2. } catch (com.alibaba.fastjson.JSONException e) {
  3. throw new RuntimeException("bad json format, " + e.getMessage());
  4. }


三、单机开发调试

单机调试功能可用于非集群模式用户在本地环境中对模型或processor进行开发调试,相关开发接口及调用接口与线上集群环境完全兼容,本功能可以让用户在开发测试阶段避免频繁部署更新服务,同时也能节省调试所用到的资源费用开销。

注意:该功能依赖于docker,需要在运行eascmd的机器上预装docker。若需要GPU及CUDA,则需要预先在本地机器上安装CUDA及nvidia-docker

1. docker安装

如果还未安装,可以参考https://docs.docker-cn.com/engine/installation/


2.下载客户端工具eascmd

windows环境:http://eas-data.oss-cn-shanghai.aliyuncs.com/tools/eascmdwin64

linux32:http://eas-data.oss-cn-shanghai.aliyuncs.com/tools/eascmd32

linux64: http://eas-data.oss-cn-shanghai.aliyuncs.com/tools/eascmd64

mac: http://eas-data.oss-cn-shanghai.aliyuncs.com/tools/eascmdmac64


3. 创建服务配置文件

配置示例:

  1. {
  2. "name": "diy_test",
  3. "generate_token": "true",
  4. "model_path": "model.tar.gz", #可以写http路径,也可以写本地路径
  5. "model_entry": "./model_path/",
  6. "model_config": "{\"model\": \"deploy.prototxt\", \"weight\": \"bvlc_reference_caffenet.caffemodel\"}",
  7. "processor_path": "diy_predictor_gpu.tar.gz", #可以写http路径,也可以写本地路径
  8. "processor_entry": "diy_predictor_gpu.so",
  9. "processor_type": "cpp",
  10. "cuda": "/usr/local/cuda"
  11. }


相关配置字段说明详见

EASCMD客户端使用手册


4. 部署调试

  1. sudo eascmd test service.json



四、正式部署

PAI-EAS控制台,直接点击模型上传部署,资源组种类选择专属资源组,Processor种类选择自定义processor,将模型和Processor包分别打包上传,填好需要的信息,就可以继续进行后续的部署步骤

image.png