diff --git a/doc/DEPLOY.md b/doc/DEPLOY.md index 8e2db2906e3c8677b16bc63818d49a8a1231e72f..2a99f4b982834a98ec95e996bc22f8684512954e 100644 --- a/doc/DEPLOY.md +++ b/doc/DEPLOY.md @@ -55,16 +55,16 @@ ![PaddlePaddle分布式训练和Serving流程化部署拓扑](./deploy/ctr-prediction-end-to-end-deployment.png) 其中: -1) 分布式训练集群在百度云k8s集群上搭建,并通过[volcano](https://volcano.sh/)提交分布式训练任务和资源管理 -2) 分布式训练产出dense参数和ProgramDesc,通过http服务直接下载到Serving端,给Serving加载 -3) 分布式训练产出sparse embedding,由于体积太大,通过cube稀疏参数服务提供给serving访问 -4) 在线预测时,Serving通过访问cube集群获取embedding数据,与dense参数配合完成预测计算过程 +1. 分布式训练集群在百度云k8s集群上搭建,并通过[volcano](https://volcano.sh/)提交分布式训练任务和资源管理 +2. 分布式训练产出dense参数和ProgramDesc,通过http服务直接下载到Serving端,给Serving加载 +3. 分布式训练产出sparse embedding,由于体积太大,通过cube稀疏参数服务提供给serving访问 +4. 在线预测时,Serving通过访问cube集群获取embedding数据,与dense参数配合完成预测计算过程 以下从3部分分别介绍上图中各个组件: -1) 分布式训练集群和训练任务提交 -2) 稀疏参数服务部署与使用 -3) Paddle Serving的部署 -4) 客户端访问Paddle Serving完成CTR预估任务预测请求 +1. 分布式训练集群和训练任务提交 +2. 稀疏参数服务部署与使用 +3. Paddle Serving的部署 +4. 客户端访问Paddle Serving完成CTR预估任务预测请求 ## 环境配置 **环境要求** :helm、kubectl、go @@ -274,16 +274,16 @@ python dumper.py --model_path=xxx --output_data_path=xxx **注意事项:**文档中使用的CTR模型训练镜像中已经包含了模型裁剪以及稀疏参数产出的脚本,并且搭建了一个http服务用于从外部获取产出的dense模型以及稀疏参数文件。 - ## 大规模稀疏参数服务Cube的部署和使用 Cube大规模稀疏参数服务服务组件,用于承载超大规模稀疏参数的查询、更新等各功能。上述分布式训练产出的稀疏参数,在k8s中以http文件服务的形式提供下载;cube则负责将稀疏参数读取、加工,切分成多个分片,灌入稀疏参数服务集群,提供对外访问。 -Cube一共拆分成三个组件,共同完成上述工作: +Cube一共拆分成四个组件,共同完成上述工作: -1) cube-transfer 负责监听上游数据产出,当判断到数据更新时,将数据下载到cube-builder建库端 -2) cube-builder 负责从上游数据构建cube内部索引格式,并切分成多个分片,配送到由多个物理节点组成的稀疏参数服务集群 -3) cube-server 每个单独的cube服务承载一个分片的cube数据 +1. cube-transfer 负责监听上游数据产出,当判断到数据更新时,将数据下载到cube-builder建库端,然后将建库的数据配送到由多个物理节点组成的稀疏参数服务集群 +2. cube-builder 负责从上游数据构建cube内部索引格式,并切分成多个分片,完成建库工作 +3. cube-server 每个单独的cube服务承载一个分片的cube数据 +4. cube-agent 与cube-server伴生部署,负责接受cube-transfer下发的指令,在本地执行实际的数据下载维护等操作 关于Cube的详细说明文档,请参考[Cube设计文档](https://github.com/PaddlePaddle/Serving/tree/develop/cube/doc/DESIGN.md)。本文仅描述从头部署Cube服务的流程。 @@ -307,20 +307,20 @@ gflags.conf transfer.conf ``` 其中: -1) bin/cube, bin/cube-builder, bin/cube-transfer是上述3个组件的可执行文件。**bin/cube是cube-server的可执行文件** +1) bin/cube, bin/cube-agent, bin/cube-builder, bin/cube-transfer是上述3个组件的可执行文件。**bin/cube是cube-server的可执行文件** 2) conf/gflags.conf是配合bin/cube使用的配置文件,主要包括端口配置等等 3) conf/transfer.conf是配合bin/cube-transfer使用的配置文件,主要包括要监听的上游数据地址等等 -接下来我们按cube server, cube-builder, cube-transfer的顺序,介绍Cube的完整部署流程 +接下来我们按cube server/agent, cube-builder, cube-transfer的顺序,介绍Cube的完整部署流程 -### 2. 分片cube server部署 +### 2. 分片cube server/agent部署 #### 2.1 配置文件修改 -首先修改cube server的配置文件,将端口改为我们需要的端口: +首先修改cube server的配置文件,将port改为我们需要的端口号,(当本机内存资源紧张时,将in_mem修改为false将以磁盘访问的模式启动cube server): ``` --port=8000 @@ -330,22 +330,25 @@ gflags.conf transfer.conf #### 2.2 拷贝可执行文件和配置文件到物理机 -将bin/cube和conf/gflags.conf拷贝到多个物理机上。假设拷贝好的文件结构如下: +将bin/cube,bin/cube-agent和conf/gflags.conf拷贝到多个物理机上。假设拷贝好的文件结构如下: ``` $ tree . |-- bin | `-- cube -`-- conf -`-- gflags.conf +| `-- cube-agent +|-- conf +| `-- gflags.conf ``` -#### 2.3 启动 cube server +#### 2.3 启动 cube server/agent ```bash nohup bin/cube & +nohup bin/cube-agent -P 8001 & ``` +其中cube-agent在启动命令中使用 -P 参数指定监听端口号 ### 3. cube-builder部署 @@ -353,68 +356,214 @@ nohup bin/cube & cube-builder配置项说明: -TOBE FILLED +均在启动参数中提交 -修改如下: +参数项如下: ``` -下游节点地址列表 -TOBE FILLED -``` +open_builder: Usage : ./open_build --help +Flags from /home/work/dangyifei/open-builder/src/main.cpp: +-cur_version (current version, no need) type: int32 default: 0 //单机builder模式下不需要 +-depend_version (depend version, job mode delta need) type: int32 default: 0 //单机builder base模式下不需要,patch模式找到meta_info里的base的key +-dict_name (dict name, no need) type: string default: "" //词典名,单机builder模式下不加默认空,用来和版本拼接生成索引文件名 +-input_path (source data input path) type: string default: "" //必须,源数据所在路径,仅支持本地路径 +-job_mode (job mode base/delta default:base) type: string default: "base" //默认base模式,delta模式:-job_mode=delta +-last_version (last version, job mode delta need) type: int32 default: 0 //单机builder base模式下不需要,patch模式找到meta_info里的base的id +-master_address (master address, no need) type: string default: "" //单机builder模式不需要,会把index meta信息写到本地output/meta_info目录下 +-only_build (wheather build need transfer) type: bool default: true //单机builder模式不需要,代表是不是单机builder,如果false会向master_address发送请求,将index meta信息写到远程 +-output_path (source data input path) type: string default: "" //必须,索引建库数据的输出路径,仅支持本地路径 +-shard_num (shard num) type: int32 default: -1 //必须,数据切分的分片数量 +``` #### 3.2 拷贝可执行文件到物理机 +需要将bin/cube-builder拷贝到物理机上。 +只利用builder工具建立索引无特殊位置要求,如果介入配送环节使用必须和cube-transfer同机部署。 +假设单独使用builder工具,文件结构如下: -部署完成后目录结构如下: ``` -TOBE FILLED +$ tree +`-- cube-builder +|-- source +| `-- test_seqfile +|-- output ``` #### 3.3 启动cube-builder - +##### 3.3.1接入配送流程 +拷贝bin/cube-builder和cube-transfer程序同机器 +相关参数已经封装好,只需要在cube-transfer的conf/transfer.conf里配置好cube-builder的地址、源数据和建库数据output的地址即可 +##### 3.3.2单机builder,假设分片数为2,词典名为test +base模式 ``` 启动cube-builder命令 +./open_builder -input_path=./source -output_path=./output -shard_num=2 -dict_name=test +``` +运行后会根据当前时间戳自动生成建库索引文件夹1565323045_1565323045和meta信息文件夹meta_info结构如下: +``` +$ tree +`-- cube-builder +|-- source +| `-- test_seqfile +`-- output + |-- 1565323045_1565323045 + | |-- test_part0 + | | |-- data.0 + | | |-- data.n + | | |-- index.0 + | | `-- index.n + | |-- test_part0.tar + | |-- test_part0.tar.md5 + | |-- test_part1 + | | |-- data.0 + | | |-- data.n + | | |-- index.0 + | | `-- index.n + | |-- test_part1.tar + | `-- test_part1.tar.md5 + `-- meta_info + |-- 1565323045_1565323045_0_0.json + `-- 1565323045_1565323045_1_0.json +``` +test_part0.tar和test_part0.tar.md5是shard0分片的数据和md5校验,1565323045_1565323045_0_0.json是0号分片的索引长度和数量,在对应版本的delta建库中需要 +delta模式 +需要依赖于上次的base或者delta的id和key,1565323045_1565323045_0_0.json前一个时间戳是id,后一个是key(和分片数据的目录key_id相反),对应cube-builder输入参数-last_version和-depend_version,保持output和dict_name不变(builder会寻找上一轮的index meta信息) +``` +启动cube-builder命令 +-input_path=./source -output_path=./output -shard_num=2 -depend_version=1565323045 -last_version=1565323045 -job_mode=delta -dict_name=test +``` +运行后会根据当前时间戳自动生成delta建库索引文件夹1565323045_1565326078和meta信息文件夹meta_info结构如下: +``` +$ tree +`-- cube-builder +|-- source +| `-- test_seqfile +`-- output + |-- 1565323045_1565323045 + | |-- test_part0 + | | |-- data.0 + | | |-- data.n + | | |-- index.0 + | | `-- index.n + | |-- test_part0.tar + | |-- test_part0.tar.md5 + | |-- test_part1 + | | |-- data.0 + | | |-- data.n + | | |-- index.0 + | | `-- index.n + | |-- test_part1.tar + | `-- test_part1.tar.md5 + |-- 1565323045_1565326078 + | |-- test_part0 + | |-- data.0 + | | |-- data.n + | | |-- index.0 + | | `-- index.n + | |-- test_part0.tar + | |-- test_part0.tar.md5 + | |-- test_part1 + | | |-- data.0 + | | |-- data.n + | | |-- index.0 + | | `-- index.n + | |-- test_part1.tar + | `-- test_part1.tar.md5 + `-- meta_info + |-- 1565323045_1565323045_0_0.json + |-- 1565323045_1565323045_0_0.json + |-- 1565326078_1565323045_0_0.json + `-- 1565326078_1565323045_1_0.json +``` +#### 3.4 seqfile工具 +builder输入数据的源格式必须为seqfile,key为uint64(输入必须为二进制8个字节),value为序列化的二进制 +提供明文转seqfile工具和读seqfile工具,位置在output/tool里kvtool.py和kv_to_seqfile.py +kvtool.py 是读seqfile工具,会输出读到的kv信息,参数是文件地址假设在/home/work/test下的seqfile,运行方式如下: +``` +python kvtool.py /home/work/test/seqfile +``` +kv_to_seqfile.py是明文转seqfile工具,依赖于kvtool.py,会将明文kv转为seqfile文件存储,并输出donefile,在kv_to_seqfile.py的27和30行修改输入和donefile路径: +``` + +BASE_DONEFILE = DATA_PATH + "donefile/base.txt" #base donefile文件地址 +SOURCE_FILE = './source/file.txt' #明文源数据路径 +``` +要求明文txt内的格式,每行一对kv,用:分割,示例如下: +``` +1:1 +2:2 +10:10 11 12 +11:this is eleven +12:value can string +1676869128226002114:48241 37064 91 -539 114 51 -122 269 229 -134 -282 +1657749292782759014:167 40 98 27 117 10 -29 15 74 67 -54 ``` - ### 4. cube-transfer部署 #### 4.1 cube-transfer配置修改 cube-transfer配置文件是conf/transfer.conf,配置比较复杂;各个配置项含义如下: - -1) TOBE FILLED -2) TOBE FILLED -... - -我们要将上游数据地址配置到配置文件中: - ``` -cube-transfer配置文件修改地方:TOBE FILLED +[default] +dict_name: test_dict //词典名 +mode: base_delta //配送模式base_only/base_delta +storage_place: LOCAL //默认LOCAL,表示使用单机builder工具 +buildtool_local: /home/work/test-builder/build/cube-builder //build工具位置,必须在本地,绝对路径 +donefile_address: /home/work/test-transfer/test_data/donefile //donefile位置支持本地路径和远程ftp或者http服务(ftp://或者http://),只到最后文件夹,文件夹内最多2个文件base.txt patch.txt +output_address: /home/work/test-transfer/test_data/output //build后数据索引输出位置 +tmp_address: /home/work/test-transfer/test_data/tmp //transfer工具运行中临时文件存放位置 +shard_num: 1 //分片数 +copy_num: 2 //每片副本数 +deploy_path: /home/work/test_dict //不用修改 +transfer_address: 10.10.10.5 //cube-transfer本机的ip + +[cube_agent] +agent0_0: 10.10.220.15:8001 //0号分片0号副本的agent ip:port +cube0_0: 10.10.220.15:8000:/ssd2/cube_open //0号分片0号副本的cube ip:port:deploy_path +agent0_1: 10.10.180.40:8001 //0号分片1号副本的agent ip:port +cube0_1: 10.10.180.40:8000:/home/disk1/cube_open //0号分片1号副本的cube ip:port:deploy_path ``` #### 4.2 拷贝cube-transfer到物理机 -拷贝完成后,目录结构如下: - +将bin/cube-transfer和conf/transfer.conf拷贝到多个物理机上,构建output和tmp文件夹用来存放配送的中间文件。假设拷贝好的文件结构如下: ``` -TOBE FILLED +$ tree +. +|-- cube-transfer +|-- output +|-- tmp +`-- conf + |-- transfer.conf ``` - #### 4.3 启动cube-transfer - +假设启动服务端口8099,-l参数是log等级 --config是配置文件位置 ``` -启动cube-transfer命令 +./cube-transfer -p 8099 -l 4 --config conf/transfer.conf ``` +### 4.4 cube-transfer支持查询接口 +> 获取当前词典状态 +>http://10.10.10.5:8099/dict/info -### 4.4 验证 +> 获取实例当前状态 +>http://10.10.10.5:8099/instance/status -一旦cube-transfer部署完成,它就不断监听我们配置好的数据位置,发现有数据更新后,即启动数据下载,然后通知cube-builder执行建库和配送流程,将新数据配送给各个分片的cube-server。 +> 获取配送历史从最近的base到当前正在配送的delta +>http://10.10.10.5:8099/dict/deploy/history -在上述过程中,经常遇到如下问题,可自行排查解决: -1) TOBE FILLED -2) TOBE FILLED -3) TOBE FILLED +### 4.5 donefile格式协议 +一旦cube-transfer部署完成,它就不断监听我们配置好的donefile数据位置,发现有数据更新后,即启动数据下载,然后通知cube-builder执行建库和配送流程,将新数据配送给各个分片的cube-server。 +id最好使用版本产出时间戳,base和patch每产出一条直接在donefile文件最后加一行即可,文件名固定base.txt、patch.txt +>base.txt每行一条,id和key相同,目录下可有多个文件,不能有文件夹 +>``` +>{"id":"1562000400","key":"1562000400","input":"/home/work/test_data/input/seqfile"} +>``` +>patch.txt每行一条,key为base的id +>``` +>{"id":"1562000401","key":"1562000400","input":"/home/work/test_data/input/seqfile"} +>{"id":"1562000402","key":"1562000400","input":"/home/work/test_data/input/seqfile"} +>``` ## 预测服务部署 @@ -467,6 +616,8 @@ $ cmake -DWITH_GPU=OFF .. # 不需要GPU $ make -jN # 这里可修改并发编译线程数 $ make install $ cd output/demo/serving +$ ls +bin conf data kvdb log ``` #### 1.3 配置修改 @@ -552,11 +703,28 @@ conf/cube.conf是一个完整的cube配置文件模板,其中只要修改nodes ##### 1.3.4 模型文件 -Paddle Serving自带了一个可以工作的CTR预估模型,是从BCE上下载下来的,其制作方法为: 1) 分布式训练CTR预估任务,保存模型program和参数文件 2) 用save_program.py保存一份用于预测的program (文件名为**model**)。save_program.py随trainer docker image发布 3) 第2步中保存的program (**model**) 覆盖到第1)步保存的模型文件夹中**model**文件,打包成.tar.gz上传到BCE +Paddle Serving自带了一个可以工作的CTR预估模型,是从BCE上下载下来的,其制作方法为: +1. 分布式训练CTR预估任务,保存模型program和参数文件 +2. 用save_program.py保存一份用于预测的program (文件名为**model**)。save_program.py随trainer docker image发布 +3. 第2步中保存的program (**model**) 覆盖到第1步保存的模型文件夹中**model**文件,打包成.tar.gz上传到BCE 如果只是为了验证demo流程,serving此时已经可以用自带的CTR模型加载模型并提供预测服务能力。 -为了应用重新训练的模型,只需要从k8s集群暴露的ftp服务下载新的.tar.gz,解压到data/model/paddle/fluid下,覆盖原来的ctr_prediction目录即可。从K8S集群暴露的ftp服务下载训练模型,请参考文档[PaddlePaddle分布式训练和Serving流程化部署](http://icode.baidu.com/repos/baidu/personal-code/wangguibao/blob/master:ctr-embedding-to-sequencefile/path/to/doc/DISTRIBUTED_TRANING_AND_SERVING.md) +为了应用重新训练的模型,只需要从k8s集群暴露的http服务下载新的ctr_model.tar.gz,解压到data/model/paddle/fluid下,并将内容移至原来的ctr_prediction目录即可: +```bash +$ cd data/model/paddle/fluid +$ wget ${HTTP_SERVICE_IP}:${HTTP_SERVICE_PORT}/data/ctr_model.tar.gz +$ tar zxvf ctr_model.tar.gz # 假设解压出一个inference_only目录 +$ rm -rf ctr_prediction # 删除旧的ctr_prediction目录下内容 +$ cp -r inference_only/* ctr_prediction +$ cd ../../../../ # 切换至serving所在目录 +$ ls +bin conf data kvdb log +$ killall serving # 杀死旧的serving进程 +$ bin/serving & # 重启serving +``` + +从K8S集群暴露的http服务下载训练模型,请参考文档[PaddlePaddle分布式训练和Serving流程化部署](http://icode.baidu.com/repos/baidu/personal-code/wangguibao/blob/master:ctr-embedding-to-sequencefile/path/to/doc/DISTRIBUTED_TRANING_AND_SERVING.md) #### 1.4 启动Serving