diff --git a/README.md b/README.md index af5ba616def9aa345e3e67decd6cba43552b6d46..076e45a8a76fd59f6a34164d3f0a7ae92ae5fee3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# ElasticCTR +# ElasticREC -ElasticCTR是分布式训练CTR预估任务和Serving流程一键部署的方案,用户只需配置数据源、样本格式即可完成一系列的训练与预测任务 +ElasticREC是分布式训练CTR预估任务和Serving流程一键部署的方案,用户只需配置数据源、样本格式即可完成一系列的训练与预测任务 * [1. 总体概览](#head1) * [2. 配置集群](#head2) @@ -14,15 +14,15 @@ ElasticCTR是分布式训练CTR预估任务和Serving流程一键部署的方案 1.快速部署 -ElasticCTR当前提供的方案是基于百度云的Kubernetes集群进行部署,用户可以很容易扩展到其他原生的Kubernetes环境运行ElasticCTR。 +ElasticREC当前提供的方案是基于百度云的Kubernetes集群进行部署,用户可以很容易扩展到其他原生的Kubernetes环境运行ElasticREC。 2.高性能 -ElasticCTR采用PaddlePaddle提供的全异步分布式训练方式,在保证模型训练效果的前提下,近乎线性的扩展能力可以大幅度节省训练资源。在线服务方面,ElasticCTR采用Paddle Serving中高吞吐、低延迟的稀疏参数预估引擎,高并发条件下是常见开源组件吞吐量的10倍以上。 +ElasticREC采用PaddlePaddle提供的全异步分布式训练方式,在保证模型训练效果的前提下,近乎线性的扩展能力可以大幅度节省训练资源。在线服务方面,ElasticREC采用Paddle Serving中高吞吐、低延迟的稀疏参数预估引擎,高并发条件下是常见开源组件吞吐量的10倍以上。 3.可定制 -用户可以通过统一的配置文件,修改训练中的训练方式和基本配置,包括在离线训练方式、训练过程可视化指标、HDFS上的存储配置等。除了通过修改统一配置文件进行训练任务配置外,ElasticCTR采用全开源软件栈,方便用户进行快速的二次开发和改造。底层的Kubernetes、Volcano可以轻松实现对上层任务的灵活调度策略;基于PaddlePaddle的灵活组网能力、飞桨的分布式训练引擎Fleet和远程预估服务Paddle Serving,用户可以对训练模型、并行训练的模式、远程预估服务进行快速迭代;MLFlow提供的训练任务可视化能力,用户可以快速增加系统监控需要的各种指标。 +用户可以通过统一的配置文件,修改训练中的训练方式和基本配置,包括在离线训练方式、训练过程可视化指标、HDFS上的存储配置等。除了通过修改统一配置文件进行训练任务配置外,ElasticREC采用全开源软件栈,方便用户进行快速的二次开发和改造。底层的Kubernetes、Volcano可以轻松实现对上层任务的灵活调度策略;基于PaddlePaddle的灵活组网能力、飞桨的分布式训练引擎Fleet和远程预估服务Paddle Serving,用户可以对训练模型、并行训练的模式、远程预估服务进行快速迭代;MLFlow提供的训练任务可视化能力,用户可以快速增加系统监控需要的各种指标。 本方案整体结构请参照这篇文章 [ElasticCTR架构](elasticctr_arch.md) @@ -85,19 +85,6 @@ bash elastic-control.sh -c ```bash bash elastic-control.sh -l ``` -2.mlflow可视化界面 - -注意:为了正常预览,请确保您本机的8111端口未被占用 - -在训练过程中,用户还可以通过mlflow的可视化界面来追踪训练进度,当屏幕上有如下输出后, -```bash -mlflow ready! -``` -用户可以用本机的浏览器访问127.0.0.1:8111查看训练情况界面。如果本机有公网ip且8111端口开放,那么用户可以在任何机器上用浏览器访问${external_ip}:8111 查看训练情况界面 - -可以看到页面显示效果如下所示: -![elastic.png](https://github.com/suoych/WebChat/raw/master/MacHi%202019-11-25%2014-19-30.png) -![dashboard.png](https://github.com/suoych/WebChat/raw/master/MacHi%202019-11-25%2014-18-32.png) ## 5. 预测服务 用户可以输入以下指令查看file server日志: diff --git a/elastic-ctr-cli/elastic-control.sh b/elastic-ctr-cli/elastic-control.sh index 77a8c6a534cd4fd3f39bd850d5c56315fbb26cb0..d0c34f2025c64ddb18870320969e1ac802c95454 100644 --- a/elastic-ctr-cli/elastic-control.sh +++ b/elastic-ctr-cli/elastic-control.sh @@ -364,14 +364,14 @@ function log() echo "Cube Transfer Log Has not been generated" fi echo "" - echo "Padddle Serving Log:" - serving_pod=$(kubectl get po | grep paddleserving | awk {'print $1'}) - kubectl logs ${serving_pod} | grep __INFO__ > paddleserving.log - if [ -f paddleserving.log ]; then - tail -n 20 paddleserving.log - else - echo "PaddleServing Log Has not been generated" - fi + #echo "Padddle Serving Log:" + #serving_pod=$(kubectl get po | grep paddleserving | awk {'print $1'}) + #kubectl logs ${serving_pod} | grep __INFO__ > paddleserving.log + #if [ -f paddleserving.log ]; then + # tail -n 20 paddleserving.log + #else + # echo "PaddleServing Log Has not been generated" + #fi } datafile_config() @@ -395,9 +395,9 @@ function apply() kubectl delete jobs.batch.volcano.sh fleet-ctr-demo fi kubectl apply -f fleet-ctr.yaml - python3 listen.py & - echo "waiting for mlflow..." - python3 service.py + # python3 listen.py & + # echo "waiting for mlflow..." + # python3 service.py return } @@ -406,7 +406,7 @@ function apply() ############################################################################### CMD="" -CPU=4 +CPU=2 MEM=4 CUBE=2 TRAINER=2 @@ -478,6 +478,30 @@ while true; do esac done +if [ $CMD = "config_resource" ]; then + + if ! grep '^[[:digit:]]*$' <<< "$CPU" >> /dev/null || [ $CPU -lt 1 ] || [ $CPU -gt 4 ]; then + die "Invalid CPU Num, should be greater than 0 and less than 5." + fi + + if ! grep '^[[:digit:]]*$' <<< "$MEM" >> /dev/null || [ $MEM -lt 1 ] || [ $MEM -gt 4 ]; then + die "Invalid MEM Num, should be greater than 0 and less than 5." + fi + + if ! grep '^[[:digit:]]*$' <<< "$PSERVER" >> /dev/null || [ $PSERVER -lt 1 ] || [ $PSERVER -gt 9 ]; then + die "Invalid PSERVER Num, should be greater than 0 and less than 10." + fi + + if ! grep '^[[:digit:]]*$' <<< "$TRAINER" >> /dev/null || [ $TRAINER -lt 1 ] || [ $TRAINER -gt 9 ]; then + die "Invalid TRAINER Num, should be greater than 0 and less than 10." + fi + + if ! grep '^[[:digit:]]*$' <<< "$CUBE" >> /dev/null || [ $CUBE -lt 1 ] || [ $CUBE -gt 9 ]; then + die "Invalid CUBE Num, should be greater than 0 and less than 10." + fi +fi + + case $CMD in config_resource) config_resource diff --git a/elastic-ctr-cli/listen.py b/elastic-ctr-cli/listen.py index f0d85104911d59e91b6d450312b3e9a26f78788d..0794f737dcbd30809fd88889c8a96837d985cfd1 100644 --- a/elastic-ctr-cli/listen.py +++ b/elastic-ctr-cli/listen.py @@ -14,6 +14,7 @@ def rewrite_yaml(path): os.system(cmd) time.sleep(5) +os.system("rm -rf ./mlruns >/dev/null 2>&1") while True: r = os.popen("kubectl get pod | grep fleet-ctr-demo-trainer-0 | awk {'print $3'}") info = r.readlines() diff --git a/elastic-ctr-cli/service_auto_port.py b/elastic-ctr-cli/service_auto_port.py new file mode 100644 index 0000000000000000000000000000000000000000..79bd1a78bcb33e75ddb60d86bb09a11bf362b249 --- /dev/null +++ b/elastic-ctr-cli/service_auto_port.py @@ -0,0 +1,32 @@ +import time +import os +import socket + + +def net_is_used(port, ip='0.0.0.0'): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + try: + s.connect((ip, port)) + s.shutdown(2) + print('Error: %s:%d is used' % (ip, port)) + return True + except: + #print('%s:%d is unused' % (ip, port)) + return False + +os.system("ps -ef | grep ${USER} | grep mlflow | awk {'print $2'} | xargs kill -9 >/dev/null 2>&1") +os.system("ps -ef | grep ${USER} | grep gunicorn | awk {'print $2'} | xargs kill -9 >/dev/null 2>&1") + +current_port = 8100 +while True: + if os.path.exists("./mlruns"): + if not net_is_used(current_port): + os.system("mlflow server --default-artifact-root ./mlruns/0 --host 0.0.0.0 --port " + str(current_port) + " >/dev/null 2>&1 &") + time.sleep(3) + print("mlflow ready, started at port" + str(current_port) + "!") + exit(0) + else: + current_port = current_port + 1 + continue + else: + time.sleep(30)