Skip to content

Commit

Permalink
[Docs] Refine user document of Multi-Hash Variable, Processor, Execut…
Browse files Browse the repository at this point in the history
…or-Optimization. (DeepRec-AI#175)
  • Loading branch information
liutongxuan authored Apr 24, 2022
1 parent f28267d commit 083cb5f
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 14 deletions.
7 changes: 4 additions & 3 deletions docs/Executor-Optimization.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# Executor优化
## 功能介绍
Runtime在调度上,做了相应的优化,目前主要优化CPU端执行效率,后续会继续推出GPU runtime优化。

## 用户接口
目前支持几种Executor策略,分别是
目前支持三种Executor策略

#### 原生tensorflow executor

是默认executor,无需开关控制
默认executor策略

#### Inline executor

Expand All @@ -26,7 +27,7 @@ with tf.train.MonitoredTrainingSession(

#### 基于CostModel的Executor

通过动态Trace指定的Session Run情况,统计与计算多组指标,通过CostModel计算出一个较优的调度策略。
通过动态Trace指定的Session Run情况,统计与计算多组指标,通过CostModel计算出一个较优的调度策略。该功能中包含了基于关键路径的调度策略和根据CostModel批量执行耗时短的算子的调度策略。

**使用方式**
首先用户可以指定Trace哪些Step的Sesison Run来收集执行指标,默认是收集100~200 Step的指标,通过设置下列环境变量,用户可以自定义此参数。
Expand Down
4 changes: 2 additions & 2 deletions docs/Multi-Hash-Variable.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Multi-Hash Variable
## 背景
在深度学习场景中,为了训练ID类的特征(例如user id或者item id),通常是将id类的稀疏特征映射到对应的低维稠密embedding向量中。在推荐场景中,随着数据量的逐渐增大,为每一个id类特征都存储一个对应的embedding向量是不现实的(例如商品数量的会达到10亿,embedding vector的维度是16,用float存储,存储量会达到64G)。因此在推荐场景中广泛使用基于Hash的方法,即对每个特征进行一次hash,然后再取获取对应的embedding,这样的方法的确可以减少内存的使用,但是由于存在hash冲突,不同的特征会被映射到同一个embedding向量,进而影响训练效果
在深度学习场景中,为了训练ID类的特征(例如user id或者item id),通常是将id类的稀疏特征映射到对应的低维稠密embedding向量中。在推荐场景中,随着数据量的逐渐增大,为每一个id类特征都存储一个对应的embedding向量,即无冲突Hash方案(EmbeddingVariable)会导致模型通常要比有冲突Hash方法下的模型大(Variable)。为了解决更大的模型带来的Training/Inference性能和资源的开销,DeepRec中已提供了若干功能来解决性能和资源问题,1)特征淘汰,通过将过期特征淘汰清理,避免过期特征积累过多,浪费内存;2)特征准入,低频特征准入机制,避免低频特征过拟合的同时,降低内存占用;3)混合多级EmbeddingVariable,通过将冷门特征存储在廉价更大的存储介质来支持更大的模型;4)DynamicDimensionEmbeddingVariable,通过使用策略让冷门特征使用更小的dim来表达,来降低冷门特征对存储空间的占用。本文中介绍的Multi-Hash Variable功能是另一种降低内存/显存占用的方法

《Compositional Embeddings Using Complementary Partitions for Memory-Efficent Recommendation Systems》paper中提出了一种新的思路,在解决Embedding使用内存量大的问题同时还可以为每个特征分配一个单独的embedding vector,具体方法是:
《Compositional Embeddings Using Complementary Partitions for Memory-Efficent Recommendation Systems》paper中提出了一种新的思路来降低内存占用的方法,具体方法是:

1. 构造若干个小的Embedding table
2. 每个对应的table对应一个hash function, 这些hash function需要互补,即对于每一个id,他对应的hash值集合是唯一的,与其他任何一个id都不完全相同。例如当有两个embedding table的时候,使用Quotient-Reminder可以保证每个key都有唯一的hash集合,具体如下图:
Expand Down
23 changes: 14 additions & 9 deletions docs/Processor.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# 1.介绍
# Processor

## 介绍
DeepRec Serving Processor是用于线上高性能服务的Library,它以DeepRec为基石,实现多种实用功能:

● 支持自动发现并导入全量模型;
Expand All @@ -18,17 +20,19 @@ DeepRec Serving Processor是用于线上高性能服务的Library,它以DeepRe
● 简易的API接口,让用户对接更方便。

Processor的产出是一个独立的so,用户可以很方便的对接到自己的Serving RPC框架中。
# 2.编译

## 编译
编译详见[https://github.com/alibaba/DeepRec](https://github.com/alibaba/DeepRec)项目首页“**How to Build serving library**”部分,编译的产出是“**libserving_processor.so**”。
# 3.使用
## 使用
用户有两种使用方式:

第一,在用户框架代码中直接[dlopen](https://linux.die.net/man/3/dlopen)从而加载so中的符号。

第二,可以结合头文件“**serving/processor/serving/processor.h**”使用,头文件中将Processor相关的API暴露了,通过头文件和“**libserving_processor.so**”来调用serving API也比较方便。

**需要注意**:如果不是使用DeepRec docker,那么可能需要一些额外的so依赖,包括:libiomp5.so,libmklml_intel.so,libstdc++.so.6,用户可以[直接下载](http://tfsmoke1.cn-hangzhou.oss.aliyun-inc.com/deeprec/serving_processor_so.tar.gz),然后在执行时候Preload这些so。
## API接口

#### API接口
Processor提供以下几组C API接口,用户在自己的Serving框架中需要调用下列接口。

**1) initialize**
Expand Down Expand Up @@ -117,7 +121,7 @@ int output_size = 0;
int state = get_serving_model_info(model, &output_data, &output_size);
```

## 数据格式
#### 数据格式
Processor需要的Request,Response等数据格式如下所示,这里我们使用Protobuf作为数据存储格式。同DeepRec下“**serving/processor/serving/predict.proto**”一致。
Protobuf是Protocol Buffers的简称,它是一种数据描述语言,用于描述一种轻便高效的结构化数据存储格式。 Protobuf可以用于结构化数据串行化,或者说序列化。简单来说,在不同的语言之间,数据可以相互解析。Java的protobuf数据被序列化之后在c++中可以原样解析出来,这样方便支持各种场景下的数据互通。
用户在客户端需要将数据封装成下面格式,或者在Process之前转成此格式。
Expand Down Expand Up @@ -280,7 +284,7 @@ message ServingModelInfo {
**对于 PredictResponse**:
map<string, ArrayProto> outputs:是map结构,key是 PredictRequest中output_filter中指定的names,value是返回的tensor。
## 配置文件
#### 配置文件
上面提到,在初始化时候需要调用函数:
```c
void* initialize(const char* model_entry, const char* model_config, int* state);
Expand Down Expand Up @@ -368,7 +372,7 @@ void* initialize(const char* model_entry, const char* model_config, int* state);
"timeline_path": "oss://mybucket/timeline/"
}
```
## 模型路径配置
#### 模型路径配置
在Processor中,用户需要提供checkpoint以及saved_model,processor从saved_model中读取meta graph 信息,包括signature,input,output等信息。模型参数需要从checkpoint中读取,原因是现在的增量更新依赖checkpoint,而不是saved model。在serving过程中,当checkpoint更新了,processor在指定的模型目录下发现有新的版本的模型,会自动加载最新的模型。saved model一般不会更新,除非graph变化,当真的变化了,需要重启新的processor instance。

用户提供文件如下:
Expand All @@ -395,8 +399,9 @@ saved_model:
| _ _ variables
```
以上述为例,在配置文件中"checkpoint_dir"设置为“/a/b/c/checkpoint_parent_dir/”,"savedmodel_dir"设置为“/a/b/c/saved_model/”
# 4.示例
## 示例
End2End的示例详见:serving/processor/tests/end2end/README
这里提供了一个完整的端到端的示例。
# 5.Timeline收集

## Timeline收集
通过在config中配置timeline相关参数,能够获取对应的timeline文件,这些文件是二进制格式,不能直接在`chrome://tracing`中进行展示,用户需要在编译DeepRec完成后目录(一般是/root/.cache/bazel/_bazel_root/)下find这个config_pb2.py文件,并放在serving/tools/timeline目录下,在此目录下执行生成`chrome://tracing`能展示的timeline。

0 comments on commit 083cb5f

Please sign in to comment.