人妻精品在线观看一区二区三区,蜜臀av精品一区二区三区网站,中文一区二区三区亚洲欧美,熟女人妇精品一区二区,人妻av在线观看视频,欧美日韩国产三级精品网站,黄色免费网站直接进入,超碰公开福利正在播放,国产毛片乡下农村妇女毛片

OneFlow源碼解析:靜態(tài)圖與運(yùn)行時(shí)

來源:CSDN博客 | 2023-01-06 19:07:24 |

作者|鄭建華 更新|許嘯宇、張文驍、成誠OneFlow靜態(tài)圖的訓(xùn)練效率遠(yuǎn)高于動(dòng)態(tài)圖(eager模式)。本文試圖通過一個(gè)簡單例子,結(jié)合v0.8.0版本的代碼,解讀一下靜態(tài)圖和運(yùn)行時(shí)的實(shí)現(xiàn)機(jī)制。

在開始之前,建議先讀一下參考資料中《OneFlow框架的系統(tǒng)設(shè)計(jì)(https://zhuanlan.zhihu.com/p/337851255)》等系列文章。對靜態(tài)圖、運(yùn)行時(shí)的基本概念和設(shè)計(jì)理念有基本的了解,會(huì)更容易理解代碼。


(相關(guān)資料圖)

1?

代碼示例

下面的示例代碼來自官方文檔(https://docs.oneflow.org/master/basics/08_nn_graph.html),是一個(gè)線性模型的前向計(jì)算。后續(xù)主要基于這段代碼進(jìn)行分析。

import oneflow as flowimport oneflow.nn as nnclass ModuleMyLinear(nn.Module): def __init__(self, in_features, out_features): super().__init__() self.weight = nn.Parameter(flow.randn(in_features, out_features)) self.bias = nn.Parameter(flow.randn(out_features)) def forward(self, input): return flow.matmul(input, self.weight) + self.biaslinear_model = ModuleMyLinear(4, 3)class GraphMyLinear(nn.Graph): def __init__(self): super().__init__() # ModuleBlock self.model = linear_model def build(self, input): # ModuleBlock.__call__ return self.model(input)graph_mylinear = GraphMyLinear()input = flow.randn(1, 4)out = graph_mylinear(input)print(out)

2?

oneflow包的初始化

import oneflow在初始化包(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/__init__.py)時(shí),與靜態(tài)圖相關(guān)的主要操作如下:

GetEnv(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/__init__.py#L228

EnvGlobalObjectsScope::Init(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/job/env_global_objects_scope.cpp#L126

啟動(dòng)各個(gè)節(jié)點(diǎn)的控制面(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/job/env_global_objects_scope.cpp#L160-L162)網(wǎng)絡(luò)連接

初始化VM(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/job/env_global_objects_scope.cpp#L180

啟動(dòng)各個(gè)節(jié)點(diǎn)的數(shù)據(jù)面網(wǎng)絡(luò)連接(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/job/env_global_objects_scope.cpp#L184-L188

初始化KernelObserver(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/job/env_global_objects_scope.cpp#L192-L203

NewDefaultSession(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/__init__.py#L229

RegsiterSession(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/framework/multi_client_session.py#L39)?創(chuàng)建 Session,并注冊為 default session(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/session_util.cpp#L89

創(chuàng)建 Python MultiClientSession 并保存到dict(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/framework/session_context.py#L40),但并不 TryInit

創(chuàng)建 C++ MultiClientSessionContext(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/framework/multi_client_session.py#L41)?但并不 TryInit

EnvGlobalObjectsScope::Init中先創(chuàng)建一個(gè)全局的ProcessCtx(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/job/env_global_objects_scope.cpp#L132)對象。然后根據(jù)環(huán)境變量等配置,在各個(gè)進(jìn)程間創(chuàng)建gRPC和CommNet的連接,分別負(fù)責(zé)控制面和數(shù)據(jù)面的數(shù)據(jù)傳輸。其中在Bootstrap過程中會(huì)初始化全局的ProcessCtx(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/rpc/lib/grpc.cpp#L42),給每個(gè)進(jìn)程分配一個(gè)全局唯一的rank編號(hào)(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/rpc/lib/global_process_ctx.cpp#L28)(machine_id(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/rpc/lib/global_process_ctx.cpp#L24))。

本文不涉及網(wǎng)絡(luò)層面的操作,只討論同一進(jìn)程內(nèi)各線程間的交互。

3?

Module類

雖然可以直接用op和tensor構(gòu)造模型,但是op的粒度太細(xì)了,直接用op構(gòu)造模型會(huì)比較繁瑣。

Module(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/module.py#L54)是由op和tensor構(gòu)成的、可復(fù)用的子模塊。利用Module可以更高效、更快捷的構(gòu)建復(fù)雜模型。oneflow.nn(https://github.com/Oneflow-Inc/oneflow/blob/d825243aa7aff5cba8bd3a901b4cc56c2b1a36af/python/oneflow/nn/__init__.py)模塊導(dǎo)出了很多預(yù)定義的Module。

Module定義了自己的屬性設(shè)置邏輯(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/module.py#L262),核心邏輯是

如果value是Parameter類型,就保存到Module._parameters中

如果value是Module類型,就保存到Module._modules中

如果value是Tensor類型,就保存到Module._buffers中

否則按常規(guī)屬性處理

Module可以包含子Module,形成樹結(jié)構(gòu)。因?yàn)镸odule通過setattr將子Module和Parameter都保存到字典結(jié)構(gòu)中,可以方便的遍歷所有Module及其參數(shù)tensor。

4?

Graph類

4.1 構(gòu)造函數(shù)

Graph的構(gòu)造函數(shù)中GetDefaultSession(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/graph.py#L145)得到的session,就是導(dǎo)入oneflow包時(shí)NewDefaultSession(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/__init__.py#L229)構(gòu)建的session。當(dāng)時(shí)沒有初始化,而是在Graph構(gòu)造時(shí)進(jìn)行初始化(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/graph.py#L147)。對應(yīng)的C++函數(shù)是MultiClientSessionContext::TryInit(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/multi_client_session_context.cpp#L67),執(zhí)行時(shí)會(huì)創(chuàng)建各種全局的資源管理器,比如: ?

LazyJobBuildAndInferCtxMgr

BufferMgr

RegstMgr

ActorMsgBus

ThreadMgr

4.2?__setattr__: 將Module和Tensor封裝為Block

Graph.__setattr__ 支持通過設(shè)置屬性的方式把一個(gè) Module 添加到 Graph 中,之后改 Module 就可以被 Graph 調(diào)用了。添加到 Graph 中的 Module,會(huì)被包裝到 Block 里面,Block 起到了代理執(zhí)行的作用,它會(huì)給原 Eager 下的 Module 擴(kuò)展出靜態(tài)執(zhí)行需要的一些特殊功能。

添加到 Graph 中的 Module 和原 Module 共享了狀態(tài)(Parameter、Buffer)和 forward 執(zhí)行邏輯。共享 forward 執(zhí)行邏輯使得靜態(tài)和動(dòng)態(tài)執(zhí)行計(jì)算邏輯相同。共享狀態(tài)則可以使動(dòng)態(tài)圖下的模型狀態(tài)被靜態(tài)圖復(fù)用。基于此,兩個(gè) Graph,一個(gè)用于訓(xùn)練,一個(gè)用于預(yù)測,他們都復(fù)用統(tǒng)一模型 Module,這樣訓(xùn)練和預(yù)測 Graph 也就實(shí)現(xiàn)了模型共享。

setattr最重要的動(dòng)作就是對_add_block的調(diào)用(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/graph.py#L1332),_add_block中主要是調(diào)用get_block_cls并保存結(jié)果(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/graph.py#L1326)。get_block_cls(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/block.py#L39)的作用是將Module及其所有Tensor屬性都轉(zhuǎn)為對應(yīng)的Block對象。為什么要做這個(gè)動(dòng)作呢?主要是靜態(tài)圖編譯需要借助Block類型來實(shí)現(xiàn)代理執(zhí)行的功能,這些功能不適合直接寫到 eager 下的 Module 和 Tensor 上。

這個(gè)轉(zhuǎn)換是在ModuleBlock構(gòu)造時(shí)調(diào)用set_origin(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/block.py#L131)完成的。對于子Module,會(huì)遞歸調(diào)用get_block_cls函數(shù)(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/block.py#L145),這樣所有子Module及其Tensor屬性都會(huì)被轉(zhuǎn)換為對應(yīng)的Block對象。

所以,上述示例代碼中,GraphMyLinear實(shí)際存儲(chǔ)的是ModuleBlock,Graph.build執(zhí)行時(shí)獲取的model屬性也是ModuleBlock對象,ModuleBlock.origin才是ModuleMyLinear。

Graph.__setattr__不允許將Tensor對象設(shè)置為屬性(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/graph.py#L1340)。Tensor只能存到Module中,因?yàn)?Module 是做狀態(tài)共享的基本單位,而 Graph 是不允許復(fù)用的。

4.3 針對不同任務(wù),定義不同的計(jì)算圖

根據(jù)Oneflow Model Zoo的模型示例(https://github.com/Oneflow-Inc/models/blob/1b291f78d8f60e5f04ee0c5962e4611cc4bab40a/Vision/classification/image/alexnet/graph/train.py),train/eval等階段可以創(chuàng)建不同的Graph子類。動(dòng)態(tài)圖下提供了 Module、Optimizer、Dataloader等模塊,這些模型都可以被添加到 Graph 中。不同的組合可以構(gòu)建不同類型的任務(wù)。

在這些不同階段,Graph構(gòu)造函數(shù)的行為、build函數(shù)的輸入輸出都有各自特點(diǎn)。了解這些,看后續(xù)代碼時(shí)會(huì)更容易理解各個(gè)參數(shù)的具體含義。

構(gòu)造函數(shù)

train階段,需要添加Module、損失函數(shù)、優(yōu)化器和dataloader

eval階段,只需要添加Module和dataloader

build函數(shù)

train

導(dǎo)入樣本和label

調(diào)用Module得到前向計(jì)算結(jié)果

計(jì)算損失

計(jì)算梯度

返回loss

eval

導(dǎo)入樣本和label

調(diào)用Module得到預(yù)估結(jié)果

返回預(yù)估結(jié)果和label

4.4 小結(jié)

上述幾個(gè)類型的關(guān)系如下:

下面描述了GraphMyLinear的構(gòu)造流程

* `__init__` * `Graph.__init__` * self.model = linear_model * `Graph.__setattr__` * _add_block * get_block_cls: 遞歸地把Module轉(zhuǎn)為ModuleBlock * `ModuleBlock.__init__` * ModuleBlock.set_origin * `ModuleBlock._origin = origin` (Module) * 對origin的sub modules, parameters, buffers遞歸調(diào)用get_block_cls * `ModuleBlock.__setattr__`

5?

邏輯圖的編譯

計(jì)算機(jī)語言的編譯,是將高級(jí)語言的語句編譯為匯編或機(jī)器指令。深度學(xué)習(xí)框架對計(jì)算任務(wù)的編譯,是將用戶的特定語句操作轉(zhuǎn)換為DAG圖。oneflow中用Job(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/job/job.proto#L30)描述邏輯的計(jì)算圖。

不同于eager模式的動(dòng)態(tài)圖,靜態(tài)圖在開始執(zhí)行前可以得到整個(gè)計(jì)算任務(wù)的所有信息,可以對DAG進(jìn)行多輪優(yōu)化。每輪優(yōu)化都是輸入一個(gè)Job、得到一個(gè)新Job。

最后,根據(jù)分布式環(huán)境配置,將邏輯圖Job轉(zhuǎn)換為物理執(zhí)行的計(jì)算圖Plan(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/job/plan.proto#L34)。在物理圖中,一個(gè)op可能分布在多個(gè)節(jié)點(diǎn)/進(jìn)程。

啟動(dòng)DAG計(jì)算需要調(diào)用Graph.__call__,這個(gè)函數(shù)的執(zhí)行主要分以下幾個(gè)步驟:

__call__

_compile(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/graph.py#L221)?if not _is_compiled

build_graph(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/graph.py#L741

__build_graph(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/graph.py#L759

finish_complie_and_init_runtime(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/graph.py#L742

__run(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/graph.py#L226

邏輯圖編譯主要在__build_graph中進(jìn)行。finish_complie_and_init_runtime會(huì)繼續(xù)做一些優(yōu)化pass,然后構(gòu)建物理圖、初始化運(yùn)行時(shí)Actor系統(tǒng)。__run會(huì)啟動(dòng)一次DAG的運(yùn)算。

5.1 graph_build_context: 為邏輯圖編譯設(shè)置基本環(huán)境

在 Graph 中,build 函數(shù)里面的代碼執(zhí)行都在 graph_build_context 的作用域下,這樣實(shí)現(xiàn)了動(dòng)態(tài)轉(zhuǎn)靜態(tài)的功能。

__build_graph中的graph_build_context(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/graph.py#L851)雖然只有一行代碼,但卻做了幾件非常重要的事情。

首先在context作用域內(nèi)設(shè)置全局的lazy_mode為True(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/framework/graph_build_util.py#L46)。在這個(gè)context作用域內(nèi),所有op都由LazyInterpreter解釋執(zhí)行。

其次,在JobBuildAndInferCtx(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/framework/graph_build_util.py#L47)作用域內(nèi),JobBuildAndInferCtx_Open(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/framework/graph_build_util.py#L57)調(diào)用類似如下C++代碼

// oneflow/api/python/job_build/job_build_and_infer.h// oneflow/core/job/job_build_and_infer_ctx_mgr.cpp// 如前所述,LazyJobBuildAndInferCtxMgr 在 MultiClientSessionContext::TryInit 執(zhí)行時(shí)初始化。// LazyJobBuildAndInferCtxMgr mgr;mgr.OpenJobBuildAndInferCtx(job_name);

OpenJobBuildAndInferCtx會(huì)新建一個(gè)Job對象(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/job/job_build_and_infer_ctx_mgr.cpp#L32)、一個(gè)LazyJobBuildAndInferCtx對象(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/job/job_build_and_infer_ctx_mgr.cpp#L34)。LazyJobBuildAndInferCtx負(fù)責(zé)根據(jù)用戶定制的op等操作,修改Job,其中最主要的功能是添加新 Op。

5.2 __build_io:為計(jì)算圖添加input和output Op

self.__build_io("input",?graph_build_util.build_graph_input_arg,?*args,?**kwargs)

上面這行代碼(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/graph.py#L854-L856)的作用是,對于用戶傳遞給graph_mylinear(input)的input參數(shù),針對其中的每個(gè)tensor都在邏輯計(jì)算圖中插入一個(gè)FeedInputOp(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/system_ops.h#L48)節(jié)點(diǎn)。也就是說,model的輸入(比如樣本tensor,具體參考4.3節(jié)),在靜態(tài)圖中也視為一個(gè)op操作。

__build_io內(nèi)會(huì)用args(即input)和kwargs構(gòu)造一個(gè)ArgsTree。ArgsTree 把 Python 下的輸入、輸出抽象成了一個(gè)樹,輸入、輸出可以是嵌套的 Tuple、List、Dict,元素是 Tensor,嵌套的結(jié)構(gòu)剛好可以表示為樹,而 Tensor 是樹中的葉子節(jié)點(diǎn)。示例代碼中kwargs是空的。

遍歷ArgsTree,對args和kwargs的每個(gè)tensor都調(diào)用傳入的build_func,對于input來說,就是build_graph_input_arg(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/framework/graph_build_util.py#L206)。后面會(huì)看到,model的output也會(huì)調(diào)用__build_io,所以這個(gè)函數(shù)名的意思應(yīng)該就是對model的輸入、輸出進(jìn)行靜態(tài)圖的構(gòu)圖工作。

build_graph_input_arg內(nèi)部會(huì)構(gòu)造一個(gè)FeedInputOpExpr(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/framework/graph_build_util.py#L213),提交給解釋器執(zhí)行。因?yàn)槭窃趌azy作用域內(nèi),由LazyInterpreter解釋執(zhí)行(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/op_interpreter/lazy_op_interpreter.cpp#L471),LazyInterpreter會(huì)將對應(yīng)的op插入靜態(tài)圖。

附:build input時(shí)ArgsTree的內(nèi)部結(jié)構(gòu)

__build_io(input)?中 ArgsTree 的內(nèi)部數(shù)據(jù)組織示意

_named_io_args: NamedArg

_value: tuple

[0]: NamedArg

_value: tuple of NamedArg

[0]: NamedArg

_value: args tensor from?Graph.__call__

[1]: NamedArg

_value: empty kwargs from?Graph.__call__

通過pdb命令可以查看變量:?p args_tree._named_io_args._value[0]._value[0]._value.to_numpy()

5.2.1 將op添加到邏輯圖

LazyInterpreter::ApplyImpl(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/op_interpreter/lazy_op_interpreter.cpp#L471)在執(zhí)行時(shí),GetCurInferCtx()(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/op_interpreter/lazy_op_interpreter.cpp#L500)返回的就是graph_build_context中OpenJobBuildAndInferCtx(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/framework/graph_build_util.py#L57)創(chuàng)建的那個(gè)LazyJobBuildAndInferCtx對象,這個(gè)對象負(fù)責(zé)邏輯圖的構(gòu)建。添加op的主要調(diào)用流程如下:

infer_ctx->AddAndInferConsistentOp(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/op_interpreter/lazy_op_interpreter.cpp#L503

AddAndInferOp(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/job/job_build_and_infer_ctx.cpp#L563

ConstructOp(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/job/job_build_and_infer_ctx.cpp#L580

CheckAndConstructOp(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/operator/operator.cpp#L1216

NewObj(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/operator/operator.cpp#L51

OperatorConf中,多種op配置共享op_type字段(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/operator/op_conf.proto#L412),protobuf oneof的op_type_case常量作為注冊NewObj的key。

系統(tǒng)預(yù)定義的op在oneflow/core/operator(https://github.com/Oneflow-Inc/oneflow/tree/release/v0.8.0/oneflow/core/operator)下,例如UserOp(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/operator/user_op.h#L24)。

AddAndInferOp將返回的Operator保存到LazyJobBuildAndInferCtx的字典中。后續(xù)的函數(shù)調(diào)用,主要是進(jìn)行推導(dǎo)并修改靜態(tài)圖Job,使得各個(gè)節(jié)點(diǎn)構(gòu)成一個(gè)DAG。

JobBuildAndInferCtx相關(guān)的類關(guān)系如下:

5.2.2 lazy tensor 和 eager tensor 的區(qū)別

LazyInterpreter::ApplyImpl的最后,會(huì)調(diào)用BuildTensor(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/op_interpreter/lazy_op_interpreter.cpp#L518)構(gòu)造一個(gè)lazy tensor,作為build_graph_input_arg的返回值(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/framework/graph_build_util.py#L216)。所以__build_io返回的lazy_args(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/graph.py#L854)是lazy tensor,它將替代eager的args(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/graph.py#L828)(也就是用戶輸入的input)參與后續(xù)的計(jì)算圖構(gòu)建。

那么lazy tensor和eager tensor的區(qū)別是什么呢?eager tensor是要即時(shí)計(jì)算的,所以需要真實(shí)數(shù)據(jù);而lazy tensor僅在靜態(tài)圖編譯階段用于推導(dǎo),只需要描述性質(zhì)的元信息。靜態(tài)圖編譯是在lazy模式下運(yùn)行,只是使用lazy tensor 做計(jì)算機(jī)構(gòu)圖和校驗(yàn)。

后面會(huì)看到,靜態(tài)圖的運(yùn)行期已經(jīng)沒有tensor的概念。運(yùn)行期看到的只是更廣義的Regst存儲(chǔ),可能代表tensor/blob,也可能是其它控制信息。靜態(tài)圖運(yùn)行時(shí)的輸入,是直接讀取外部 eager tensor的內(nèi)存數(shù)據(jù)到到regst;輸出應(yīng)該是op寫到regst,通過blob構(gòu)造eager tensor。

5.3 build: 將UserOp和FeedVariableOp添加到邏輯圖

__build_graph中的self.build()(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/graph.py#L861)會(huì)調(diào)用GraphMyLinear.build(),以及ModuleMyLinear.forward()。因?yàn)槭窃趌azy模式下運(yùn)行,matmul和add都會(huì)調(diào)用UserOpExpr重載版本的LazyInterpreter::ApplyImpl(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/op_interpreter/lazy_op_interpreter.cpp#L832),進(jìn)而調(diào)用AddAndInferConsistentOp(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/op_interpreter/lazy_op_interpreter.cpp#L940)進(jìn)行構(gòu)圖操作。

需要說明的是,在引用Module的Parameter屬性時(shí)(如weight/bias),會(huì)觸發(fā)FeedVariableOp的構(gòu)圖操作(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/framework/graph_build_util.py#L226)、調(diào)用對應(yīng)版本的LazyInterpreter::ApplyImpl(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/op_interpreter/lazy_op_interpreter.cpp#L527)。這個(gè)是怎么執(zhí)行的呢?

__build_graph中,在進(jìn)入lazy模式之前,先調(diào)用了_create_states_builder(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/graph.py#L843)。其中self._state()(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/graph.py#L667)返回所有Module的所有Parameter(包括子Module)。

state_block的類型是TensorBlock(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/block.py#L631)。所有的state_block的lazy_origin_builder().method(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/block.py#L647)都被設(shè)置為調(diào)用build_graph_state(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/graph.py#L683-L688)。

給build_graph_state(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/framework/graph_build_util.py#L220)設(shè)置個(gè)斷點(diǎn)能讓整個(gè)調(diào)用過程顯形,主要的調(diào)用棧如下:

-> out = graph_mylinear(input) /usr/local/lib64/python3.6/site-packages/oneflow/nn/graph/graph.py(221)__call__()-> self._compile(*args, **kwargs) /usr/local/lib64/python3.6/site-packages/oneflow/nn/graph/graph.py(741)_compile()-> _, eager_outputs = self.build_graph(*args, **kwargs) /usr/local/lib64/python3.6/site-packages/oneflow/nn/graph/graph.py(759)build_graph()-> outputs = self.__build_graph(*args, **kwargs) /usr/local/lib64/python3.6/site-packages/oneflow/nn/graph/graph.py(864)__build_graph()-> outputs = self.build(*lazy_args, **lazy_kwargs) /mnt/project/machine-learning/oneflow/oneflow/test.py(21)build()-> return self.model(input) /usr/local/lib64/python3.6/site-packages/oneflow/nn/graph/block.py(234)__call__()-> result = self.__block_forward(*args, **kwargs) /usr/local/lib64/python3.6/site-packages/oneflow/nn/graph/block.py(266)__block_forward()-> result = self._origin.__class__.forward(self, *args, **kwargs) /mnt/project/machine-learning/oneflow/oneflow/test.py(11)forward()-> return flow.matmul(input, self.weight) + self.bias /usr/local/lib64/python3.6/site-packages/oneflow/nn/graph/block.py(483)__getattr__()-> p_state = self._get_from_states(name, "_parameters") /usr/local/lib64/python3.6/site-packages/oneflow/nn/graph/block.py(521)_get_from_states()-> _s_block.try_build() /usr/local/lib64/python3.6/site-packages/oneflow/nn/graph/block.py(679)try_build()-> self._lazy_origin_builder.try_build(self) /usr/local/lib64/python3.6/site-packages/oneflow/nn/graph/block.py(627)try_build()-> self.result = self.method()> /usr/local/lib64/python3.6/site-packages/oneflow/framework/graph_build_util.py(227)build_graph_state()-> op_name, var_conf_str, ["in_0"], ["out_0"]

這個(gè)調(diào)用過程比較容易困擾的是,執(zhí)行對象會(huì)在Grpah、GraphMyLinear、ModuleMyLinear、ModuleBlock之間切換。

前面在討論Graph的構(gòu)造時(shí)已經(jīng)提過,執(zhí)行self.model(input)時(shí),Graph.__getattr__返回的屬性model是ModuleBlock對象,所以實(shí)際調(diào)用的是ModuleBlock.__call__。

在這個(gè)函數(shù)內(nèi)調(diào)用__block_forward(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/block.py#L234),其中的_origin(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/block.py#L266)是ModuleMyLinear,進(jìn)入到它的forward方法,執(zhí)行到flow.matmul(input, self.weight) + self.bias時(shí),matmul 會(huì)被LazyOpInterpreter 所執(zhí)行,在 LazyOpInterpreter 中調(diào)用 AddAndInferConsistentOp(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/op_interpreter/lazy_op_interpreter.cpp#L503

,在 Job 中添加一個(gè) matmul operator。同理后面的加法會(huì)在 job 中添加一個(gè) add operator。

self.weight 和 self.bias 會(huì)觸發(fā)調(diào)用ModuleBlock.__getattr__,進(jìn)而調(diào)用_get_from_states(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/block.py#L483),調(diào)用TensorBlock.try_build()(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/block.py#L521)。這里執(zhí)行的就是進(jìn)入lazy模式之前設(shè)置的build_graph_state(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/framework/graph_build_util.py#L220)。從而增加一個(gè)FeedVariableOp到計(jì)算圖(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/op_interpreter/lazy_op_interpreter.cpp#L527)。為什么設(shè)置和調(diào)用會(huì)距離這么遠(yuǎn)呢?主要是為了讓參數(shù)盡量和消費(fèi)參數(shù)的 Operator 在一個(gè)作用域下,所以實(shí)現(xiàn)成了惰性求值來達(dá)到延遲計(jì)算的目的。

再后面的步驟就是調(diào)用__build_io(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/graph.py#L869-L875)插入FetchOutputOp(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/op_interpreter/lazy_op_interpreter.cpp#L589)。也就是說,獲取model的output也是一個(gè)op。

到目前為止,前向計(jì)算圖就構(gòu)建完成了。它的json表示可以參考附錄。net.op是計(jì)算圖的節(jié)點(diǎn),通過input等屬性可以看出節(jié)點(diǎn)之間的連接關(guān)系。

示例代碼的前向計(jì)算圖如下。從這個(gè)圖可以看到,input、output、weights等都是op。

5.4 邏輯圖優(yōu)化

在__build_graph中會(huì)調(diào)用CurJobBuildAndInferCtx_Complete對靜態(tài)圖進(jìn)行多輪優(yōu)化(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/graph.py#L923),對應(yīng)的C++函數(shù)是LazyJobBuildAndInferCtx::Complete()(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/job/job_build_and_infer_ctx.cpp#L975)。

這之后生成的Job是full_job。本文的示例代碼比較簡單,并不是典型的計(jì)算場景,其forwar和ful計(jì)算圖的拓?fù)涫且粯拥?。?shí)際大部的圖優(yōu)化都實(shí)現(xiàn)在這個(gè)階段,如 Op fusion、AMP、ZeRO、常量折疊等等。

到這里,邏輯圖構(gòu)建的主體部分就結(jié)束了。

隨后會(huì)構(gòu)建一個(gè)CNNGraph對象(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/graph.py#L947),對應(yīng)的C++類型是NNGraph(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/nn_graph.h#L33)。這個(gè)對象將負(fù)責(zé)構(gòu)建物理計(jì)算圖Plan。它也是整個(gè)運(yùn)行時(shí)的擁有者和維護(hù)者。這個(gè)對象析構(gòu)時(shí),整個(gè)運(yùn)行時(shí)也會(huì)有序終止并釋放資源。

5.5 物理圖的編譯

接下來就是執(zhí)行finish_complie_and_init_runtime(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/graph.py#L742),其中的核心調(diào)用是self._c_nn_graph.complie_and_init_runtime()(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/graph.py#L802),對應(yīng)的C++函數(shù)是NNGraph::CompileAndInitRuntime(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/nn_graph.cpp#L265)。

在這個(gè)函數(shù)中,JobCompleter().Complete()(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/nn_graph.cpp#L280)會(huì)繼續(xù)對邏輯圖做幾輪修改優(yōu)化,補(bǔ)全 Runtime 執(zhí)行所需要的附加信息,Compiler().Compile()(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/nn_graph.cpp#L285)將邏輯圖轉(zhuǎn)為分設(shè)備的物理圖,并繼續(xù)對Plan進(jìn)行修改優(yōu)化。

Plan的編譯是在master節(jié)點(diǎn)進(jìn)行的(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/nn_graph.cpp#L282)。master節(jié)點(diǎn)會(huì)將Plan通過gRPC推送給各個(gè)worker節(jié)點(diǎn)(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/nn_graph.cpp#L308),worker節(jié)點(diǎn)從master拉取物理計(jì)算圖(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/nn_graph.cpp#L310)。

之后調(diào)用NewRuntimeBuffers創(chuàng)建Buffer對象(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/nn_graph.cpp#L322),Buffer應(yīng)該是主要用于進(jìn)程內(nèi)的信息同步。

然后就準(zhǔn)備初始化運(yùn)行時(shí)了。

示例代碼生成的compiled_job和物理圖Plan的json參見附錄。

最終生成的compiled邏輯圖如下??蚣茏詣?dòng)插入了很多系統(tǒng)控制節(jié)點(diǎn)。

5.6 Plan的結(jié)構(gòu)

示例代碼輸出的Plan json數(shù)據(jù)見附錄。

Plan在邏輯上和compiled_job是等價(jià)的。這里主要關(guān)注task/op之間的關(guān)系。

Plan.task中的每個(gè)元素是一個(gè)task,其中的exec_sequence.exec_node對應(yīng)job中的op,通常只有一個(gè)op(數(shù)組可以支持sub graph)。

exec_node.kernel_conf.op_attribute描述了op信息。其中op_conf包含op name信息。

kernel_conf.op_attribute.op_conf就是Job中的OperatorConf。

kernel_conf.op_attribute.arg_signature.bn_in_op2lbi體現(xiàn)了task/op之間的連接關(guān)系。

bn_in_op就是blob name in op,即op輸入的blob name。

以System-AutoTick-DstSubsetTick_21為例

{ "out": { "op_name": "System-AutoTick-DstSubsetTick_21", "blob_name": "out" }, "in_0": { "op_name": "System-EagerCriticalSection-Interface-End-Tick-19", "blob_name": "out" }, "in_1": { "op_name": "System-AutoTick-SrcSubsetTick_20", "blob_name": "out" }}

exec_node.bn_in_op2regst_desc_id在task層面體現(xiàn)了連接關(guān)系。這個(gè)map中的key表示輸入輸出,value是register id。

{"out": "29","in_0": "27","in_1": "28"}

task.produced_regst_desc描述了對應(yīng)task生產(chǎn)的register,consumer_task_id是消費(fèi)者,

produced_regst_desc.out.regst_desc_type.data_regst_desc.lbi2blob_desc.lbi就是這個(gè)register的logic blob id。

task.consumed_regst_desc_id描述了對應(yīng)task消費(fèi)的register信息

6?

運(yùn)行時(shí)的初始化

NNGraph::CompileAndInitRuntime中,new Runtime這行代碼會(huì)初始化運(yùn)行時(shí)(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/nn_graph.cpp#L331)。主要做的事情包括:

創(chuàng)建Thread

通知Thread創(chuàng)建Actor,Actor會(huì)創(chuàng)建Regst和Kernel

給沒有輸入的source_tasks發(fā)送啟動(dòng)信號(hào)kStart

6.1 Runtime創(chuàng)建Thread

在Runtime的構(gòu)造函數(shù)中,DumpThreadIdsFromPlan(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/job/runtime.cpp#L65)會(huì)將Plan中屬于當(dāng)前進(jìn)程的task的thread id存入thread_ids_變量。AddThreads創(chuàng)建這些Thread對象(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/job/runtime.cpp#L69)。

Thread在構(gòu)造時(shí)會(huì)創(chuàng)建一個(gè)物理線程(?https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/thread/thread.cpp#L39),線程執(zhí)行的是PollMsgChannel方法(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/thread/thread.cpp#L44),Thread就是在這里持續(xù)等待需要處理的新消息。

Thread只處理兩類命令消息:線程終止消息,創(chuàng)建Actor的消息。其它消息交給Actor::ProcessMsg處理(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/thread/thread.cpp#L83)。

6.2 Runtime通知Thread創(chuàng)建Actor

在Runtime的構(gòu)造函數(shù)中,tasks被分為兩類:source_tasks和other_tasks。在示例代碼中,source_tasks(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/job/runtime.cpp#L84-L85)是沒有輸入邊的task。

從代碼邏輯看,在Plan proto中,task的consumed_regst_desc_id字段是一個(gè)map。如果這個(gè)map的所有key都是in_ctrl(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/job/runtime.cpp#L54),這個(gè)task就是source_tasks。

一些source_tasks的示例如下:

System-Src-WaitAndSendIds_16

System-AutoTick-AppendDeviceTick_9

System-EagerCriticalSection-Interface-End-Tick-19

System-EagerCriticalSection-Interface-End-Tick-25

Runtime調(diào)用HandoutTasks函數(shù)(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/job/runtime.cpp#L100-L101)會(huì)給ActorMsgBus發(fā)送構(gòu)建Actor的kConstructActor消息(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/job/runtime.cpp#L49)。

6.3 ActorMsgBus和Thread的消息處理

從接口看,ActorMsgBus?(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/lazy/actor/actor_message_bus.cpp#L24)負(fù)責(zé)消息的發(fā)送(Actor通過ActorMsgBus發(fā)送消息),Thread::PollMsgChannel(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.1/oneflow/core/thread/thread.cpp#L60) 負(fù)責(zé)消息的接收和處理。

相關(guān)實(shí)體的協(xié)作關(guān)系如下

Actor是自調(diào)度的基本單元,接受消息然后工作,工作完后再繼續(xù)發(fā)送消息。

actor_id就是task_id,是在編譯Plan時(shí)就確定的。task是編譯時(shí)概念,actor是對等的運(yùn)行時(shí)概念。

task_id有特定的編碼格式(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/graph/task_id.cpp#L21-L29),從中可以解析出machine_id(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/graph/task_id.cpp#L73)和thread_id(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/graph/task_id.cpp#L77)。

在跨網(wǎng)絡(luò)的整個(gè)物理圖Plan中,actor id相當(dāng)于地址,通過它可以定位唯一的actor實(shí)體。

Actor 通過 ActorMsgBus::SendMsg(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/lazy/actor/actor_message_bus.cpp#L24) 發(fā)送 ActorMsg(https://github.com/Oneflow-Inc/oneflow/blob/4856d691051accd72f13f4139d281e411977b297/oneflow/core/lazy/actor/actor_message.h#L34) 消息。

ActorMsg包含源和目的actor id(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/lazy/actor/actor_message.h#L84-L85)。

如果是進(jìn)程內(nèi)通訊(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/lazy/actor/actor_message_bus.cpp#L26),將通過 ActorMsgBus::SendMsgWithoutCommNet?(https://github.com/Oneflow-Inc/oneflow/blob/4856d691051accd72f13f4139d281e411977b297/oneflow/core/lazy/actor/actor_message_bus.cpp#L49)把 ActorMsg 朝目的 actor 所在的 thread 入隊(duì)消息(https://github.com/Oneflow-Inc/oneflow/blob/4856d691051accd72f13f4139d281e411977b297/oneflow/core/thread/thread.h#L40)。

Thread::EnqueueActorMsg 會(huì)判斷當(dāng)前 thread 是否是 actor thread,如果是則入本地隊(duì)列,否則則入 actor thead 的 channel 隊(duì)列。

如果ActorMsg是跨進(jìn)程消息,ActorMsgBus通過CommNet發(fā)送消息(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/lazy/actor/actor_message_bus.cpp#L42-L44),接收方的CommNet應(yīng)該會(huì)根據(jù)actor id獲得線程id,從ThreadMgr查到Thread,將消息交給Thread處理。

Thread::PollMsgChannel(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.1/oneflow/core/thread/thread.cpp#L60) 負(fù)責(zé)消息的接收和處理。

如果線程本地隊(duì)列l(wèi)ocal_msg_queue_為空,則從thread的channel隊(duì)列中取出全部ActorMsg放入本地隊(duì)列(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.1/oneflow/core/thread/thread.cpp#L63)。

從本地隊(duì)列中取出一個(gè)ActorMsg,然后開始處理。

處理一些特殊的kCmdMsg消息(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.1/oneflow/core/thread/thread.cpp#L67-L79),然后普通消息交給Actor自行處理(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.1/oneflow/core/thread/thread.cpp#L83)。

Actor收到消息后,會(huì)判斷是否滿足了Act的條件,如果滿足,則會(huì)執(zhí)行Act,從而調(diào)用LaunchKernel執(zhí)行計(jì)算,Act執(zhí)行結(jié)束后通過ActorMsgBus發(fā)消息通知上下游Actor。

這些對象之間的消息傳遞關(guān)系如下圖所示

6.4 激活source Actor

目前的實(shí)現(xiàn)中,Actor全部是自調(diào)度的,只能接受來自其他Actor的消息。Actor中有一類比較特殊的source actors,它們與source tasks對應(yīng)。

source actors 沒有上游 actor,它們會(huì)朝下游actor發(fā)送消息從而激活所有的Actor運(yùn)行。

source actors 本身是如何執(zhí)行的呢?它們在接受到 kStart 消息后就會(huì)一直 Act 直到進(jìn)入退出流程。但是其 kernel 會(huì)阻塞在 Buffer(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.1/oneflow/core/common/buffer.h#L26) 處,一直等待其他線程往 buffer 中添加數(shù)據(jù)后,阻塞會(huì)被激活,然后 kernel 執(zhí)行讀取,kernel 完成后,actor 的 Act 結(jié)束,往下游發(fā)送消息。

source actors 由于會(huì)發(fā)生阻塞,所以其必須有單獨(dú)的 actor thread。

Runtime 初始化的的最后一步就是朝各 source actors 發(fā)送 kStart 消息用以激活它們,但 source actors 只有接受到 buffer 的數(shù)據(jù)后才會(huì)往下執(zhí)行,然后朝下游 actors 發(fā)送消息,使所有的 actors 都執(zhí)行起來。

7?

Actor

7.1 Actor的創(chuàng)建

Thread在創(chuàng)建Actor時(shí),會(huì)先嘗試創(chuàng)建為LightActor(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/thread/thread.cpp#L104),如果不成功,再嘗試用預(yù)先注冊的工廠創(chuàng)建Actor。

有幾種TaskType可以用于LightActor(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/lazy/actor/light_actor.cpp#L677-L689):

kNormalForward,比如matmul、add等user op。

kCopyHd

kTick

kCollectiveBoxingGeneric

目前大約有20多種Actor的子類型。其它Actor類型根據(jù)TaskType(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/job/task.proto#L8)預(yù)先注冊。例如WaitAndSendIdsActor。

示例代碼的各個(gè)節(jié)點(diǎn)對應(yīng)的actor類型參見附錄。

Actor相關(guān)的類關(guān)系如下(包含關(guān)系只是表示可以訪問到相關(guān)信息,并不意味著創(chuàng)建或著擁有該類型對象)

7.2 Actor的初始化

Actor的構(gòu)造函數(shù)一般都是空的,構(gòu)建之后需要執(zhí)行Init(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/lazy/actor/actor.cpp#L129)函數(shù)進(jìn)行初始化。

LightActor繼承自ActorBase,不是Actor的子類,有自己的Init函數(shù)實(shí)現(xiàn)。這里只討論Actor的初始化。

在Actor::Init(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/lazy/actor/actor.cpp#L129)中,首先調(diào)用ConstructKernel(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/lazy/actor/actor.cpp#L138)創(chuàng)建kernel實(shí)例。和Operator類似,kernel也是以O(shè)pTypeCase作為注冊的key,例如WaitAndSendIdsKernel(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/kernel/wait_and_send_ids_kernel.cpp#L51)。一個(gè)Actor通常只有一個(gè)kernel。

之后調(diào)用NewRegsts創(chuàng)建Regst(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/lazy/actor/actor.cpp#L152)。Tensor是用戶側(cè)的概念。對應(yīng)的運(yùn)行時(shí)概念是Regst(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/register/register.h#L24),它持有Kernel需要讀寫的內(nèi)存。Regst的概念比Tensor更寬泛,比如框架自動(dòng)添加的控制Op也會(huì)用到Regst。

Actor將自己創(chuàng)建的Regst保存到produced_regsts_(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/lazy/actor/actor.cpp#L153)。

TakeOverNaiveConsumed(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/lazy/actor/actor.cpp#L182)只記錄需要消費(fèi)的regst id,但并不push到consumed_regsts_。

TakeOverNaiveProduced(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/lazy/actor/actor.cpp#L183)既記錄生產(chǎn)的regst id,也push到naive_produced_rs_(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/lazy/actor/actor.cpp#L249)。這種區(qū)別是為了首次執(zhí)行計(jì)算時(shí),actor能順利執(zhí)行。后面分析Actor的消息處理時(shí)會(huì)再回過頭來討論一下。

調(diào)用InitBnInOp2BlobInfo會(huì)初始化BlobInfo(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/lazy/actor/actor.cpp#L184)。

之后就是調(diào)用VirtualActorInit(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/lazy/actor/actor.cpp#L185),這里允許各個(gè)Actor子類定制自己的初始化邏輯。通常會(huì)調(diào)用OF_SET_MSG_HANDLER宏(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/lazy/actor/actor.h#L76-L80)設(shè)置Actor的消息處理函數(shù)。

7.3 Actor的消息處理

LightActor 首先會(huì)根據(jù)消息類型分別處理 kRegstMsg 和 kEordMsg 消息。HandleRegstMsg(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.1/oneflow/core/lazy/actor/light_actor.cpp#L424) 中根據(jù) RegstMsg 的 type (kProduced 或 kComsumed) 來分別處理各種讀寫狀態(tài)計(jì)數(shù)。

然后判斷讀寫計(jì)數(shù)是否達(dá)到了判斷條件,如果達(dá)到了意味著滿足了讀寫 regst 的條件,然后就 執(zhí)行 ActOnce(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.1/oneflow/core/lazy/actor/light_actor.cpp#L451)。

LightActor::ActOnce 會(huì)在第一次執(zhí)行時(shí)去 InitBnInOp2Blob 和 InitActMsg。InitBnInOp2Blob 初始化 resgt 中的 bn 與 Blob 的映射關(guān)系,為 kernel 提供通過 bn 訪問 Blob 的功能。InitActMsg 會(huì)初始化好所有需要發(fā)送的消息避免后繼發(fā)消息時(shí)重復(fù)的構(gòu)建消息。

然后就是 LaunchKernel,接著會(huì) ResetState 重置 regst 狀態(tài)。

LaunchKernel 后就會(huì)把之前構(gòu)建好的消息發(fā)送出去,同步消息會(huì)直接入隊(duì) thread 消息隊(duì)列,異步消息通過 callback 發(fā)送到 ActorMsgBus。

普通 Actor::ProcessMsg 會(huì)調(diào)用 msg handler 來處理消息,最常見的 msg handler 就是 Actor::HandlerNormal(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.1/oneflow/core/lazy/actor/actor.cpp#L329)。

Actor::HandlerNormal 中流程跟 LightActor 中類似,會(huì)根據(jù)不同的 regst 類型來分別處理,Actor 中對 regst 的狀態(tài)管理方式與 LightActor 不同,LightActor 中的方式更加高效,Actor 中能處理一些特殊情況。

消息處理完畢后,就會(huì)調(diào)用 ActUntilFail,ActUntilFail 會(huì)判斷 IsReadReady 和 IsWriteReady 來決定是否可以進(jìn)行 Act。

最常見的 NaiveActor::Act() 就是執(zhí)行 AsyncLaunchKernel。

Act 完成后,就開始朝上下游發(fā)送 regst 消息。

還有一些特殊的 Actor,我們以WaitAndSendIdsActor為例,觀察一下這類Actor的消息處理機(jī)制。

之所以選擇這個(gè)例子,一是這個(gè)Actor比較簡單;二是這是一個(gè)典型的source task,想看一下計(jì)算圖是怎么被觸發(fā)啟動(dòng)計(jì)算的。

Thread收到的消息如果不是kStopThread或kConstructActor,就調(diào)用Actor::ProcessMsg(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/thread/thread.cpp#L83),將消息轉(zhuǎn)給Actor處理。

ProcessMsg函數(shù)只是簡單的將消息轉(zhuǎn)給handler處理(https://github.com/Oneflow-Inc/oneflow/blob/b6bf3f8843679111eb1edf79deefce814d250f4e/oneflow/core/lazy/actor/actor.h#L38)。

WaitAndSendIdsActor::VirtualActorInit中,handler被設(shè)置為HandlerWaitToStart(https://github.com/Oneflow-Inc/oneflow/blob/22f70a1719f371a54512633bb92086580d9c3c89/oneflow/core/lazy/actor/wait_and_send_ids_actor.cpp#L53)。

Runtime的構(gòu)造函數(shù)中,發(fā)送的第一批消息是給source_tasks的kStart消息,這個(gè)消息就由HandlerWaitToStart函數(shù)處理。

HandlerWaitToStart校驗(yàn)消息類型后,將handler設(shè)置為HandlerNormal(https://github.com/Oneflow-Inc/oneflow/blob/b17a9cd6b930b5817c63623fb682bd708377a93b/oneflow/core/job/runtime.cpp#L109)(這也是大部分Actor的默認(rèn)handler),然后調(diào)用ProcessMsg(https://github.com/Oneflow-Inc/oneflow/blob/22f70a1719f371a54512633bb92086580d9c3c89/oneflow/core/lazy/actor/wait_and_send_ids_actor.cpp#L74),實(shí)際就是調(diào)用新設(shè)置的handler HandlerNormal。

HandlerNormal中,如果是kCmdMsg,只允許是kStart(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L377)。通過消息類型校驗(yàn)后,會(huì)直接調(diào)用ActUntilFail(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L378)。

7.4 Act執(zhí)行的條件

LightActor 和 Actor 判斷能否進(jìn)行 Act 采用了不同的策略,LightActor 的效率更高,Actor 能處理一些特殊情況。

對于 LightActor,當(dāng)在讀的register計(jì)數(shù) total_reading_cnt_ 歸 0,可消費(fèi)的register計(jì)數(shù) ready_consumed_ 增加到 max_ready_consumed_,前者表示所有的消費(fèi)者已經(jīng)讀取當(dāng)前 LightActor 的 Regst,后者表示當(dāng)前 LightActor 消費(fèi)的所有 Regst 已經(jīng)到達(dá)(由上游發(fā)送的 Regst 消息)。

對于 Actor,Actor::ActUntilFail中,Act方法(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L424)是各個(gè)子類自己實(shí)現(xiàn)的,一般主要是啟動(dòng)kernel計(jì)算。

但是在執(zhí)行Act之前,需要先確認(rèn):

Act執(zhí)行依賴的數(shù)據(jù)是否都已經(jīng)就緒?(IsReadReady)

Act生產(chǎn)出來的數(shù)據(jù),消費(fèi)方是否已經(jīng)用完、并收到ack消息確認(rèn)?(IsWriteReady)

Actor有4個(gè)與此相關(guān)的成員變量

RegstSlot naive_produced_rs_;

RegstSlot inplace_produced_rs_;

RegstSlot naive_consumed_rs_;

RegstSlot inplace_consumed_rs_;

xx_produced_rs_存儲(chǔ)的是當(dāng)前Actor的下游consumer返回的、已經(jīng)使用完畢的ack regst信息。(當(dāng)前Actor生產(chǎn)的Regst存儲(chǔ)在produced_regsts_中。)

運(yùn)行時(shí)在初始化的過程中,所有Actor都沒有運(yùn)行過,任何Actor都不可能收到ack消息,所以在Actor初始化時(shí),要預(yù)先填充xx_produced_rs_,這樣才能保證Actor在首次運(yùn)行前是WriteReady的,才能順利啟動(dòng)執(zhí)行。

xx_consumed_rs_存儲(chǔ)的是上游依賴發(fā)來的數(shù)據(jù)。它不需要預(yù)先填充。因?yàn)閟ource_tasks沒有輸入依賴,自然就是ReadReady的;而xx_produced_rs_在初始化時(shí)的預(yù)先填充又保證它是WriteReady的,所以source_tasks可以直接運(yùn)行。source_tasks的輸出消息發(fā)給下游,下游也會(huì)變?yōu)镽eadReady,而下游在初始化后也保證是WriteReady的。整個(gè)Actor系統(tǒng)就可以這樣運(yùn)轉(zhuǎn)起來了。

7.5 Actor上下游之間的通知機(jī)制

Act執(zhí)行完畢后,需要將結(jié)果數(shù)據(jù)發(fā)給下游consumer。以 WaitAndSendIds 的 Naive Produced 為例,ActUntilFail中的調(diào)用流程如下:

AsyncSendNaiveProducedRegstMsgToConsumer(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L427

VirtualAsyncSendNaiveProducedRegstMsgToConsumer(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L441

HandleProducedNaiveDataRegstToConsumer(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L446

HandleRegstToConsumer(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L577)

EnqueueAsyncMsg(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L523

如果目標(biāo)線程是當(dāng)前線程,ActorMsgBus::SendMsg(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L662

否則,將消息加入async_msg_queue_(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L664

增加 total_reading_cnt_(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L526)(這個(gè)變量表示已經(jīng)發(fā)消息給下游、但未收到的ack數(shù)量)

naive_produced_rs_.PopFrontRegsts(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L581

AsyncSendProducedCtrlRegstMsgToConsumer

注意naive_produced_rs_.PopFrontRegsts(https://github.com/Oneflow-Inc/oneflow/blob/06a6af1c7f760ba4b12d2dfb8f73d7fda5c7dbab/oneflow/core/lazy/actor/register_slot.cpp#L53)會(huì)將Regst指針從隊(duì)列中刪掉,相應(yīng)的可用(https://github.com/Oneflow-Inc/oneflow/blob/06a6af1c7f760ba4b12d2dfb8f73d7fda5c7dbab/oneflow/core/lazy/actor/register_slot.cpp#L49)register計(jì)數(shù)減1(https://github.com/Oneflow-Inc/oneflow/blob/06a6af1c7f760ba4b12d2dfb8f73d7fda5c7dbab/oneflow/core/lazy/actor/register_slot.cpp#L49)。

而在Actor::HandlerNormal中處理收到的kRegstMsg消息(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L340)時(shí),如果是consumer發(fā)來的ack消息,會(huì)調(diào)用TryUpdtStateAsProducedRegst(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L355),將Regst再添加到 naive_produced_rs_ 中(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L654),以保證當(dāng)前Actor在收到所有ack后是WriteReady的;同時(shí)遞減在讀的 register 計(jì)數(shù)total_reading_cnt_。

Actor對依賴的上游消息的處理是類似的。通過以下函數(shù)調(diào)用給上游發(fā)送ack消息、通知 register 已經(jīng)用完,可以繼續(xù)更新了:

AsyncSendNaiveConsumedRegstMsgToProducer(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L431

AsyncRetInplaceConsumedRegstIfNoConsumer(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L432)在Actor::HandlerNormal中收到kRegstMsg消息后,將消息添加到consumed_rs_(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L344),以保證當(dāng)前Actor在收到所有依賴數(shù)據(jù)后是ReadReady的。

LightActor有自己的消息處理機(jī)制(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/light_actor.cpp#L299),大致原理應(yīng)該是差不多的。

7.6 Act執(zhí)行的動(dòng)作

根據(jù)上述討論,Actor收到kRegstMsg后也會(huì)進(jìn)入ActUntilFail執(zhí)行。如果讀寫都是Ready,就執(zhí)行Act(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L424)。以WaitAndSendIdsActor為例,主要調(diào)用鏈路如下:

AsyncLaunchKernel(https://github.com/Oneflow-Inc/oneflow/blob/22f70a1719f371a54512633bb92086580d9c3c89/oneflow/core/lazy/actor/wait_and_send_ids_actor.cpp#L58

ek.kernel->Launch(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L562),啟動(dòng)Kernel計(jì)算

Forward(https://github.com/Oneflow-Inc/oneflow/blob/eae9ff38f074479d79ce24b0f6e0594f82126171/oneflow/core/kernel/kernel.cpp#L52

ForwardDataContent(https://github.com/Oneflow-Inc/oneflow/blob/eae9ff38f074479d79ce24b0f6e0594f82126171/oneflow/core/kernel/kernel.cpp#L65

buffer->Pull(https://github.com/Oneflow-Inc/oneflow/blob/b17a9cd6b930b5817c63623fb682bd708377a93b/oneflow/core/kernel/wait_and_send_ids_kernel.cpp#L40

給regst的存儲(chǔ)地址mut_dptr賦值(https://github.com/Oneflow-Inc/oneflow/blob/b17a9cd6b930b5817c63623fb682bd708377a93b/oneflow/core/kernel/wait_and_send_ids_kernel.cpp#L47

buffer->Pull會(huì)等待條件變量的通知(https://github.com/Oneflow-Inc/oneflow/blob/49f60e682518436dfeb37344a15902a959e0e4f2/oneflow/core/common/buffer.h#L60)?,F(xiàn)在,看上去所有Actor都已準(zhǔn)備就緒,只等發(fā)令槍一響就開跑了。

8?

啟動(dòng)靜態(tài)圖的計(jì)算

Graph.__run(https://github.com/Oneflow-Inc/oneflow/blob/81edd938826a7ea903174d682348847658b64653/python/oneflow/nn/graph/graph.py#L226)會(huì)扣動(dòng)發(fā)令槍的板機(jī),啟動(dòng)計(jì)算圖的一輪計(jì)算。

主要調(diào)用流程如下:

RunLazyNNGraph(https://github.com/Oneflow-Inc/oneflow/blob/81edd938826a7ea903174d682348847658b64653/python/oneflow/nn/graph/graph.py#L1076

builder->LaunchLazyJob(https://github.com/Oneflow-Inc/oneflow/blob/8f672eea116cae4a73bb7309e7496b08d7ec9a32/oneflow/core/framework/nn_graph.cpp#L568

LaunchLazyJobInstructionType(https://github.com/Oneflow-Inc/oneflow/blob/8f672eea116cae4a73bb7309e7496b08d7ec9a32/oneflow/core/framework/instructions_builder.cpp#L179

Buffer::Push(https://github.com/Oneflow-Inc/oneflow/blob/8f672eea116cae4a73bb7309e7496b08d7ec9a32/oneflow/core/framework/instructions_builder.cpp#L179

這里的Buffer::Push就是WaitAndSendIdsKernel在等待的起跑信號(hào)。

9?

運(yùn)行時(shí)的退出機(jī)制

整個(gè)運(yùn)行時(shí)包含很多對象和資源,安全有序的退出是龐雜而又細(xì)致的工作。這里僅以WaitAndSendIds為例,從一個(gè)側(cè)面觀察一下運(yùn)行時(shí)的退出機(jī)制。

運(yùn)行時(shí)的退出始于NNGraph對象的析構(gòu)(https://github.com/Oneflow-Inc/oneflow/blob/8f672eea116cae4a73bb7309e7496b08d7ec9a32/oneflow/core/framework/nn_graph.cpp#L76)。

9.1 Actor的退出

NNGraph在析構(gòu)時(shí),會(huì)關(guān)閉所有的Buffer對象(https://github.com/Oneflow-Inc/oneflow/blob/8f672eea116cae4a73bb7309e7496b08d7ec9a32/oneflow/core/framework/nn_graph.cpp#L82)。

Buffer在關(guān)閉時(shí),會(huì)設(shè)置is_closed_ = true并通知所有監(jiān)聽者(https://github.com/Oneflow-Inc/oneflow/blob/49f60e682518436dfeb37344a15902a959e0e4f2/oneflow/core/common/buffer.h#L81)。但是Pull會(huì)繼續(xù)處理完已經(jīng)提交的計(jì)算。

所以,Buffer應(yīng)該是主要用于進(jìn)程內(nèi)的通信和異步協(xié)調(diào)的一個(gè)類。

WaitAndSendIdsKernel這時(shí)候正在等待新一輪計(jì)算開始(https://github.com/Oneflow-Inc/oneflow/blob/b17a9cd6b930b5817c63623fb682bd708377a93b/oneflow/core/kernel/wait_and_send_ids_kernel.cpp#L40),結(jié)果收到Pull返回的kBufferStatusErrorClosed(https://github.com/Oneflow-Inc/oneflow/blob/49f60e682518436dfeb37344a15902a959e0e4f2/oneflow/core/common/buffer.h#L61)。

WaitAndSendIdsActor::IsCustomizedReadReady以后就一直返回false(https://github.com/Oneflow-Inc/oneflow/blob/22f70a1719f371a54512633bb92086580d9c3c89/oneflow/core/lazy/actor/wait_and_send_ids_actor.cpp#L68),IsReadReady也返回false(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L533)。

這之后,ActUntilFail只會(huì)執(zhí)行異步消息發(fā)送(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L437)(不再進(jìn)入while循環(huán))

WaitAndSendIdsActor::HandlerNormal仍然會(huì)處理其它Actor發(fā)來的消息(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L340)。但因?yàn)镮sCustomizedReadReady返回false,會(huì)進(jìn)入AsyncSendEORDMsgForAllProducedRegstDesc(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L394)執(zhí)行。它會(huì)給每個(gè)下游發(fā)送kEordMsg消息(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L614)。

Actor在收到上游發(fā)來的kEordMsg消息后,遞減remaining_eord_cnt_(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L331)。

remaining_eord_cnt_被初始化為Actor的輸入regst的數(shù)量(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L171)。

total_reading_cnt_是當(dāng)前Actor生產(chǎn)的、已經(jīng)發(fā)給consumer、但尚未收到ack的消息數(shù)量。

Actor目前仍可以正常接收consumer發(fā)來的ack消息。

當(dāng)上述2個(gè)變量都為0時(shí)(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L395),意味著所有上游都發(fā)出了kEordMsg消息,也收到了所有下游的ack消息。Actor就給Thread返回1(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L397)。

如果上述兩個(gè)變量有不為0的,就修改handler,由HandlerZombie(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L399)處理后續(xù)收到的消息。

Thread收到Actor返回的1后(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/thread/thread.cpp#L84),將它從自己的存儲(chǔ)中刪除(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/thread/thread.cpp#L89),并遞減運(yùn)行Actor的數(shù)量。

9.2 Thread的退出

NNGraph重置runtime_導(dǎo)致運(yùn)行時(shí)對象被析構(gòu)(https://github.com/Oneflow-Inc/oneflow/blob/8f672eea116cae4a73bb7309e7496b08d7ec9a32/oneflow/core/framework/nn_graph.cpp#L83)。

Runtime刪除所有Thread(https://github.com/Oneflow-Inc/oneflow/blob/b17a9cd6b930b5817c63623fb682bd708377a93b/oneflow/core/job/runtime.cpp#L117)。

ThreadMgr給所有Thread發(fā)送kStopThread消息(https://github.com/Oneflow-Inc/oneflow/blob/c8c6d351fa28c5ebce948d69c06670a783f83f74/oneflow/core/thread/thread_manager.cpp#L64)。同時(shí),重置指針導(dǎo)致Thread析構(gòu)(https://github.com/Oneflow-Inc/oneflow/blob/c8c6d351fa28c5ebce948d69c06670a783f83f74/oneflow/core/thread/thread_manager.cpp#L66)。

Thread的物理線程退出PollMsgChannel循環(huán)(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/thread/thread.cpp#L68)。

Thread等待物理線程結(jié)束,關(guān)閉channel(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/thread/thread.cpp#L52)。

10?

分布式場景的靜態(tài)圖

分布式的compile_job、物理圖Plan和單機(jī)場景有明顯變化。

比如,每個(gè)進(jìn)程都有一套WaitAndSendIds等控制節(jié)點(diǎn)。這也容易理解,因?yàn)槊總€(gè)節(jié)點(diǎn)都要執(zhí)行__run和Buffer::Push/Pull,都要啟動(dòng)本進(jìn)程的Actors執(zhí)行計(jì)算。

matmul和broadcast_add等user op也會(huì)在兩個(gè)節(jié)點(diǎn)進(jìn)行計(jì)算。 ?

10.1 示例代碼

啟動(dòng)方式參考Global Tensor的官方文檔。

import oneflow as flowimport oneflow.nn as nnP0 = flow.placement("cpu", ranks=[0, 1])a0_sbp = flow.sbp.split(0)class ModuleMyLinear(nn.Module): def __init__(self, in_features, out_features): super().__init__() self.weight = nn.Parameter(flow.randn(in_features, out_features, placement=P0, sbp=flow.sbp.broadcast)) self.bias = nn.Parameter(flow.randn(1, out_features, placement=P0, sbp=flow.sbp.broadcast)) def forward(self, input): return flow.matmul(input, self.weight) + self.biaslinear_model = ModuleMyLinear(4, 3)class GraphMyLinear(nn.Graph): def __init__(self): super().__init__() # ModuleBlock self.model = linear_model def build(self, input): # ModuleBlock.__call__ return self.model(input)graph_mylinear = GraphMyLinear()input = flow.randn(5, 4, placement=P0, sbp=flow.sbp.split(1))out = graph_mylinear(input)print(out)

11?

附錄

11.1 斷點(diǎn)

11.1.1 Python斷點(diǎn)示例

# python3 -m pdb test.pybreak test.py:25break oneflow/nn/graph/graph.py:221break oneflow/nn/graph/graph.py:741break oneflow/nn/graph/graph.py:745break oneflow/nn/graph/graph.py:759break oneflow/nn/graph/graph.py:828break oneflow/nn/graph/graph.py:777break oneflow/nn/graph/graph.py:1066break oneflow/nn/graph/graph.py:1133break oneflow/framework/graph_build_util.py:227

11.1.2 C++斷點(diǎn)示例

啟動(dòng)命令

source /mnt/oneflow/build/source.shgdb --args python3 /mnt/oneflow/test.py# set breakpoints# run

斷點(diǎn)示例

set breakpoint pending onbreak oneflow::ActorMsg::BuildEordMsgbreak oneflow/core/common/buffer.h:80break oneflow::(anonymous namespace)::CheckAndConstructOpbreak oneflow::WaitAndSendIdsActor::Actbreak oneflow::WaitAndSendIdsActor::HandlerWaitToStartbreak oneflow/core/lazy/actor/light_actor.cpp:452break oneflow/core/lazy/actor/light_actor.cpp:485break oneflow::ForeignInputKernel::ForwardDataContentbreak oneflow::vm::LaunchLazyJobInstructionType::Compute

11.2 靜態(tài)圖的json表示

forward(https://quip.com/OMc4A0HOOr0C)

full(https://quip.com/JLaMAHGBLXmK)

compiled(https://quip.com/tXjuAiS3J0Ab)

plan(https://quip.com/a0DMAAIte6PQ)

11.3 actor type

naive_actor

System-AutoTick-AppendDeviceTick_9System-AutoTick-DstSubsetTick_12System-AutoTick-DstSubsetTick_21System-AutoTick-DstSubsetTick_27System-AutoTick-Prepend-DeviceTick_7System-AutoTick-SrcSubsetTick_20System-AutoTick-SrcSubsetTick_26System-AutoTick-SrcSubsetTick_8System-AutoTick-Tick_11System-AutoTick-Tick_13System-EagerCriticalSection-Callback-23System-EagerCriticalSection-Callback-29System-EagerCriticalSection-Interface-Begin-Tick-18System-EagerCriticalSection-Interface-Begin-Tick-24System-EagerCriticalSection-Interface-End-Tick-19System-EagerCriticalSection-Interface-End-Tick-25System-EagerCriticalSection-Wait-22System-EagerCriticalSection-Wait-28

light_actor

_GraphMyLinear_0_input.0.0_2_GraphMyLinear_0_output.0.0_2model.biasmodel-broadcast_add-1model-matmul-0model.weightSystem-AutoTick-SinkTick_15System-SyncAllRanksSinkTick_14

wait_and_send_ids_actor

???System-Src-WaitAndSendIds_16

call_back_notify_actor

???System-Sink-CallbackNotify_17

12?

參考資料

oneflow v0.8.0(https://github.com/Oneflow-Inc/oneflow/tree/release/v0.8.0)

OneFlow框架的系統(tǒng)設(shè)計(jì)(上篇)(https://zhuanlan.zhihu.com/p/337851255)

OneFlow框架的系統(tǒng)設(shè)計(jì)(中篇)(https://zhuanlan.zhihu.com/p/338699487)

OneFlow框架的系統(tǒng)設(shè)計(jì)(下篇)(https://zhuanlan.zhihu.com/p/339208452)

一個(gè)Job在OneFlow中的執(zhí)行過程—上篇(https://zhuanlan.zhihu.com/p/344531540)

一個(gè)Job在OneFlow中的執(zhí)行過程—中篇(https://zhuanlan.zhihu.com/p/355654002)

一個(gè)Job在OneFlow中的執(zhí)行過程—下篇(https://zhuanlan.zhihu.com/p/363689736)

靜態(tài)圖模塊 nn.Graph(https://docs.oneflow.org/master/basics/08_nn_graph.html)

OneFlow系統(tǒng)設(shè)計(jì)(https://docs.oneflow.org/v0.4.0/basics_topics/essentials_of_oneflow.html)

torch.nn.Module(https://pytorch.org/docs/1.10/generated/torch.nn.Module.html)

其他人都在看

OneFlow源碼解析:自動(dòng)微分機(jī)制

ChatGPT的一小步,NLP范式轉(zhuǎn)變的一大步

李白:你的模型權(quán)重很不錯(cuò),可惜被我沒收了

OpenAI掌門Sam Altman:AI下一個(gè)發(fā)展階段

32篇年度最佳AI論文;Python編譯器Codon開源

比快更快,開源Stable Diffusion刷新作圖速度

OneEmbedding:單卡訓(xùn)練TB級(jí)推薦模型不是夢

歡迎Star、試用OneFlow最新版本:GitHub - Oneflow-Inc/oneflow: OneFlow is a deep learning framework designed to be user-friendly, scalable and efficient.OneFlow is a deep learning framework designed to be user-friendly, scalable and efficient. - GitHub - Oneflow-Inc/oneflow: OneFlow is a deep learning framework designed to be user-friendly, scalable and efficient.https://github.com/Oneflow-Inc/oneflow/

關(guān)鍵詞:

国产97视频免费在线观看| 久久99久久久久久久久| 噜噜mm视频在线观看| 美女精品一区二区三区免费观看| 97超碰人妻在线观看| 欧美日韩乱码视频在线免费观看 | 国产精品精品免费视频| 亚洲欧美精品丝袜中文字幕| 日韩欧美一区二区专区在线观看| 青青草原精品免费在线视频| 一区二区三区中国大乳房熟女| 大香视频依人在线中文字幕| 丰满人妻视频一区二区| 日韩 国产 欧美 在线 一区| 亚洲熟女一区二区三区观看 | 成人av无码区二区三区| 青青热久免费精品视频| 色94色一区二区三区| 抽搐高潮痉挛白浆无码av| 亚洲 综合 欧美 日韩| 高颜值美女视频在线观看| 丰满美女一区二区三区| 视频一区二区三区国产在线| 国产盗摄一区二区三区在线| 欧美一区二区三区黄片| 欧美熟妇乱色一区二区| 青青草原国产视频在线观看| 综合人妻一区二区三区| 欧洲乱码在线观看视频| 超碰在线公开内射日韩版| 午夜精品久久久在线观看| 婷婷色综合一区二区久久久| 国产成人黄色精品视频| 男生把小鸡鸡插到大美女的屁股| 超级碰碰在线视频国产| 国产精品久久久久久码| 97超碰在线播放视频| 日韩欧美人妻激情一区| 国产精品久久久久久96| 中文字幕在线免费看av| 最近中文字幕免费观看av| 最近中文字幕免费观看av | 久久久久久精品一区二区三区| 日韩情色一区二区三区四区| 国产青青草在线观看视频| 国产日韩制服丝袜第一页| 青娱乐成人免费公开视频| 久久婷婷香蕉国产精品| 亚洲精品沙发专享系列av| 91黄页网站在线观看| 久久精品国产亚洲av四区| 成人h色视频在线观看| 18免费在线观看av| 情趣丝袜美腿写真图片| 欧美 自拍 丝袜 人妻| 国产理论亚洲天堂av| av现场直播亚洲乱码| 国产精品入口蜜臀人妻| 区一区二区三在线播放| 日韩国产制服丝袜专区| 国内揄拍国内精品人妻迷| 国产亚洲欧美日韩中文在线蜜臀| 欧美精品素人在线观看| 欧美一区二区三区99| 撒玛利亚女孩在线观看免费全集 | 欧美激情高潮无遮挡男男| 翔田千里精品久久一区二| 国产视频二区在线观看| 中文字幕女优乱码久久午夜| 免费激情视频在线观看| 人妻精品在线观看一区二区三区| 一区二区在线播放三区| 男人把女人捅到爽歪歪黄| 绿帽老公让娇妻蒙眼被人操 | 欧美精品久久久久久久久91| 国产亚洲精品高清一区| 亚洲成人av免费在线播放| av中文字幕人妻丝袜| 日韩丝袜诱惑网站大全| 中文字幕日韩在线久久| 性做久久久久久久毛片| 法国熟女乱淫xxoo| 超碰在线最新地址97| 国产三级欧美系列日韩系列| 国产乱码伦人偷精品视频| 国产深夜视频在线观看| 青青青视频自偷自拍视频1| 人妻视频资源在线观看| 青青在线观看国产免费视频| 亚洲情色一区二区三区四区五区| 久久久久久久久极品内射| 国产女老师的诱惑在线播放观看 | 日韩 国产 欧美 在线 一区| 亚洲av专区在线观看国产| 久久婷婷香蕉国产精品| 青青草原免费体验视频| 午夜不卡在线免费视频| 国产精品久久综合亚洲av| 国产aV无码片毛片一级韩国| 欧美一区二区在线播放视频| 国产揄拍视频在线观看| 精品一区二区三区四区在线播放| 国产精品一级二级三级四级| av性感美女免费在线观看| 在线观看资源青青国产视频| 高潮喷水波多野结衣在线观看| 欧美不卡一区二区三区视频| 美女扒开胸罩露出奶头免费 | 亚洲乱码国产一区二区| 国产精品久久人妻互换| 情趣丝袜美腿写真图片| 亚洲一区二区三区天海翼| 国产亚洲欧美日韩三级| 精品人妻一区二区三区综合部| 国产97视频在线观看| 91国产激情视频在线观看| 久久99av无色码人妻蜜柚| 国产精彩自拍视频在线观看| 亚洲一区视频在线免费播放| 五十路熟女人妻在线网观看| 国产a三级三级三级精品91区| 少妇一区二区三区97少妇| 免费av在线网站中文字幕| 明日花绮罗人妻大乳av| 99视频在线精品免费| av中文字幕一区在线| 亚洲欧美一区二区福利| 国产精品一级二级盗摄羞羞| 在线观看国产视频播放| 亚洲在线欧美一区二区三区| 日韩一级淫片蜜臀播放口| 久久久久久狠狠综合一本| 人妻精品在线观看一区二区三区| 亚洲一区二区av在线| 成人亚洲精品777777| 夜夜骚av一区二区三区啊| 最新中文字幕av大全| av中文字幕官网天堂| 亚洲欧美精品丝袜中文字幕| 久久久久久久精品女人毛片| 97超碰超碰在线观看| 日韩美女美女黄色黄色片| av在线免费观看网3| av网站在线观看青青草| 亚洲不卡码一区二区三区| 国产青青草在线观看视频| 色婷婷av国产精品欧美| 国产极品粉嫩交性大片| 国产日韩欧美精品久久| 欧美不卡一区二区三区视频| 亚洲精品 乱码久久久久久| 青青青青娱乐在线观看| 69人妻精品久久久久88| 成人av无码区二区三区| 老熟女一区二区三区四区| 中文字幕精品乱码久久久久| 欧美情色一区二区三区| 国产理论亚洲天堂av| 久久久久久噜噜噜久久久精品| 国产精品成人自产拍在线| 二区三区免费在线观看| 99爱在线精品视频免费看| 伊人精品久久久久中文字幕| 亚洲欧美另类在线一区二区| 97成人在线视频免费观看| 国产精品一区二区精品视频| 亚洲最大黄色av网站| 国产精品久久久久九九九九| 国产一区二区在线直播| 国产高清一级视频在线观看| 成人国产麻豆一区二区| 国产精品美女自在线观看免费| 在线播放一区二区三区三州| 精品日本一区二区三区四区 | 色婷婷一区二区三区四区在线 | 美女网站免费非常非常黄的| 97超碰在线公开免费| 久久亚洲精品色噜噜狠狠| 欧美午夜理论在线观看| 亚洲黄色av中文字幕| 69久久久久久人妻白浆| 在线人妻av播放观看| 国产老人一区av二三区| 日韩人妻少妇二三四区| 久久久久久久精品女人毛片 | 黄色av在线观看网址| 国产成人自拍视频在线| 国产精品永久免费自在线观看| 国产性一交一乱―色―情人| 蜜臀av在线一区二区三区四区| 亚洲情色一区二区三区四区五区| av资源在线中文天堂| 国产精品精品免费视频| 夜夜欢性恔真人免费视频| 熟女一区二区三区 在线| 日产精品99久久久久久久久| 成人黄色av免费网站| 国产三级视频在线18播放线观看 | 亚洲国产精品免费线观看视频| 丰满熟女一区二区三区在线播放| 国产精品国产三级国产普通话一| 国产白嫩在线观看视频| 美女自拍偷拍亚洲一区| 日韩欧美少妇一区二区三区| 精品久久久中文字幕人妻 | 日韩国产偷拍自拍在线| 国产a久久观看免费视频| 国产精品自在在线午夜| 外国大片在线免费观看| 人妻精品在线观看一区二区三区| 精品无人区一区二区三区av| 精久久中文字幕人妻最新| 成年人黄色片视频网站| 国产精品丝袜久久久久久久久| 国产原创AV蜜芽尤物一区| 大香视频依人在线中文字幕| 欧美在线视频午夜精品| 欧美成人网另类套图超市| 2023国产精品自拍视频| av天堂午夜精品蜜臀| 中文字幕在线午夜人妻| 自拍偷自拍亚洲精品10p | 日韩 制服 丝袜 中文| 亚洲中文字幕乱码免费播放| 欧美一区二区在线播放视频| 亚洲最大黄色av网站| 蜜月久久99精品久久久久久| 一道一本av精品久久毛片| 久久久久久久久99密月| 亚洲 综合 欧美 日韩| 97精品综合久久视频| 亚洲中文字幕一区二区三区av| 人妻丝袜一区二区三区| av中文字幕一区在线| 青青艹视频在线免费观看| 欧美一区二区三区爽爽爽| 久久久久这里只出精品| 91自拍免费在线视频| 麻豆av国语对白麻豆| 国产午夜精品视频免费福利| 亚洲不卡码一区二区三区| 久久99只有这里有精品| 精品久久久中文字幕人妻| 国产精品久久人妻互换| 黄色网页在线免费观看| 91国产自拍在线视频| 久久久免费一区二区三区| 久久久久久噜噜噜久久久精品 | 麻豆国产成人av在线| 久久久久亚洲精品乱码按摩| 国产成人免费a在线资源| 欧美性少妇一区二区三区| 免费的黄网站在线观看视频| 日韩中文字幕avsex| 久久久久久狠狠综合一本| 我的女人呻吟噢噢噢哦哦哦哦| 国内网友自拍视频在线| 91青青视频在线观看| 成人24小时免费视频| 亚洲熟女一区二区三区观看| 久久精品人妻免费观看| xxx日韩欧美黄色a| 先锋视频资源在线播放| 亚洲情色一区二区三区四区五区| 日本国产一区二区在线观看| 一道一本av精品久久毛片| 亚洲欧美另类视频一区蜜臀| 国产中文精品久高清在线不| 日韩一区二区三区在线看片| 国产一级视频在线观看免费 | 性感丝袜短裙美女啪啪啪| 老熟女老熟妇一区二区| 人妻系列少妇极品熟妇| 久久久久亚洲av一区二区三区| 亚洲欧美一区二区三区黑人| 成人国产精品视频在线| 99九九99久久精品| 蜜臀av夜夜澡人人爽人人| 国产精品一级二级盗摄羞羞| 亚洲精品午夜免费视频| 久久久久亚洲av一区二区三区| 大香国产视频中文字幕| 深夜在线视频在线观看| 97成人在线视频免费观看| 蜜臀av在线观看免费| 国内网友自拍9色视频| 国产成年免费观看视频| 色偷偷av一区二区三区| 国产av中文字幕乱码| 青青草久久久久综合精品| 久久久亚洲裙底偷窥综合| av在线免费观看网3| 97人妻中出中文字幕| 国产人妻一区二区免费播放| 精品人妻av在线观看| 星宫一花av中文在线| 人妻又爱又澡人人添人人爽| 激情av一区av二区| 成人国产一区二区在线| 国产免费九九久久精品a级| 国产精品亚洲av二区三| 国产成人在线视频播放| 1024在线国产视频| 色综合久久久久久久久8噜啦噜| 97色老99久久九九爱精品| 专想操B的猛男操骚妇B| 国产一区二区在线97| 亚洲一a区二a区三a区| 一区二区三区看国产片在线| 天海翼一区二区三区免费| 国产精品丝袜久久久久久久久| 黄色av在线免费播放| 人妻丝袜一区二区三区四区av| 乱文丝袜乱文丝袜美腿视频| 色av色婷婷91人妻久久久| 国产自拍偷拍在线免费| 成人av日本在线观看| 欧洲美女一区二区三区| 97精品国产高清自在线| 国产亚洲精品线视频在线| 日韩激情中文字幕在线| 日韩熟女精品91中文字幕| 国产视频二区在线观看| 日韩少妇一区二区三区四区五区| 久久人妻公开中文字幕网| 亚洲区域一区二区三区| 亚洲av日韩综合一区在线观看 | 狠狠的干香蕉久久av| 亚洲乱女色熟一区二区三区| 欧美日韩精品一级二级三级| 国产97视频免费在线观看| 久久久精品久久久久久69| 爽爽爽爽成人观看在线。| 日韩熟女中文字幕一区| 国产亚洲欧美日韩中文在线蜜臀| 成人免费三级在线观看| 青青视频在线观看播放观看| 91成人资源在线观看| 亚洲国产成人精品久久久久| 亚洲一区二区三区18| 99久久在线免费观看| 欧美青青一区二区三区| 亚洲中文自拍另类av| 日韩素人mium丝袜| 国产高清在线一区不卡极品| 男人插女人下面出浆视频| 国产精品一级二级盗摄羞羞| 亚洲欧美视频在线观看网站| 1024在线国产视频| 国产爱爱视频在线播放| 国产成年免费观看视频| 97超碰人妻福利在线| 亚洲精品中文字幕午夜| 免费av网址一区二区| 精品熟女少妇一区二区| 3p少妇欧美一区二区三区| 99九九久久国产精品| 24小时在线播放免费观看| 大鸡巴操小嫩逼免费全裸| 亚洲人妻av一区二区| 中文字幕亚洲久久爽一区| 美女黄a视频大全在线免费观看| 91在线精品免费视频| 性感美女一区二区三区| 成人极品av免费观看| 蜜臀av国内精品久久久久久| 欧美成人天天综合在线视色 | 欧美网址一区二区三区| 果冻传媒av精品国产网站| 成人美女主播在线播放| 我想看男人日女人的逼| 青青成人免费在线视频| 国产成人不卡在线视频| 日韩中文字幕人妻诱惑| 丰满熟女一区二区三区91| 日韩精品成人av高清在线观看| 久久久久久久久久久高| 亚洲 自拍 欧美 中文| 在线91华人精品国产片| 亚洲情色一区二区三区四区五区| 日韩 制服 丝袜 中文| 亚洲一二三区精品在线观看| 欧美日韩在线精品激情| 久久久久久久精品女人毛片| 免费激情视频在线观看| 国产亚洲免费在线视频| 国产日韩精品在线欧美| 伊人视频在线免费观看| 一边吃扎一边插逼逼视频| 青青青青草免费视频看看| 久久久久久精品一区二区三区| 在线观看日韩三级视频| 岛国av丝袜在线播放| 91精品久久久久久久久| 一级成人欧美一区在线观看| 蜜月久久99精品久久久久久| 77成人在线免费视频| 久久久久久狠狠亚洲综合| 96精品久久久久久久久| 好吊色欧美一区二区三区四区| 成年av网站18不禁| 美女黄a视频大全在线免费观看| 老师美女脱了内裤露屁股| 欧美网址一区二区三区| 超碰在线公开内射日韩版| 亚洲制服丝袜美腿在线| 97人妻中文字幕精品一区在线| 国内自拍视频在线观看h| 精品国产一区二区三区不卡免费| 日韩少妇一区二区三区四区五区| 青青操新免费观看视频| 久久香蕉亚洲欧美av精品| 人妻一区二区三区精品免费| 国产亚洲免费在线视频| 与女性一起行走男性应走| 99久久久精品免费看国产| 国产精品亚洲在线播放| 欧美视频精品综合在线| 久久人妻日韩一二三区| 成人av在线视频资源| 大鸡巴操小嫩逼免费全裸| 韩剧熔炉在线完整免费观看| 嘴唇上长黄色的小点点| 日韩av三级在线网站| 亚洲丝袜av在线观看| 欧美日韩一区二区三区性| 国产免费无码一区二区视频无码| 国产偷拍自拍熟女视频| 欧美日韩激情午夜看片| 曰本在线精品一区二区三区| 大奶少妇白虎高潮流视频| 日本午夜免费在线视频| 国产免费三级三级三级| 99久久国产一区二区三区| 中文字幕乱码在线观看| 两鸡巴日一个骚逼浪的视频| 国产熟妇一区二区三区四区| 日韩人妻有码一区二区| 中文字幕av网址在线| 亚洲激情av一区二区三区| 久久人妻一区二区精选| 色综合久久88色综合天| 久久无语av中文字幕| 你懂的视频精品在线观看| 国产欧美久久久久久精品一| 国产成人亚洲综合av| 国产性感丝袜美女av| 欧美成人动漫在线观看| 久久人人妻人人做人人爽| 欧美国产日韩另类系列| 亚洲国产精品免费线观看视频| 最新中文字幕av网站| 你懂的视频精品在线观看 | 丁香婷婷久久久久成人天堂国产 | 欧美成人网另类套图超市| 99久久麻豆99久久免费| 免费播放黄色操逼乱操逼| 中文字幕亚洲熟女精品人妻| 中文字幕免费av在线| 日韩一区二区人妻9999| 人妻精品在线观看一区二区三区 | 中文字慕人妻一区二区在线视频| 日本午夜免费在线视频| 亚洲乱码国产一区网址| 超碰人妻免费一区二区| 最新中文字幕av大全| 91亚洲精品久久久久蜜桃| 欧美 亚洲一区二区在线| 国产高清亚洲精品视频| 女生高潮喷水视频免费在线观看 | 日韩在线不卡一区在线观看| 国产男女淫片av免费观看| 色综合久久久久久久久8噜啦噜 | 青娱乐成人免费公开视频| 美女精品一区二区三区免费观看 | 男人添女人下边视频免费| 能效等级一级二级三级| 在线成人av一区二区| 日韩成人伦理片在线观看| 国产国拍成人精品视频| 亚洲国产99精品国自产| 国产国拍成人精品视频| 亚洲乱码在线免费观看| 美女精品一区二区三区免费观看| 国产婷婷色一区二区三区五区| 精品熟女少妇一区二区| 亚洲天堂中文av网站| 欧美一区二区在线观看网站| 国产视频在线观看视频| 97视频在线免费观看网站| 蜜桃臀美女福利xxoo| 少妇一区二区三区97少妇| 日韩欧美久久一区二区 | 国模午夜写真福利在线| 97视频在线免费观看网站| 国产女老师的诱惑在线播放观看 | 熟女人妻中文字幕免费观看| av大全一区二区三区| 久久亚洲精品国产日韩高潮| 69人妻精品久久久久88| 人妻视频资源在线观看| 日韩美女美女黄色黄色片| 自拍偷拍色亚洲欧美色| 97超碰人妻福利在线| 丰满人妻一区二区三区精品av| 精品无人区一区二区三区av| 熟女五十路一区二区三区| 亚洲中文字幕日韩av| 人妻一区二区三区精品免费| 超碰视频在线观看免费| 黄色av网站手机在线播放| 人妻一区二区三区精品免费| 青青青国产免费观看视频| 亚洲国产免费视频网站| 成人在线观看免费视频播放| 能效等级一级二级三级| 国产一区二区三区在线h| 国产精品色图在线观看| 试婚99天视频免费完整版观看| 国产精品成人自产拍在线| 国产又粗又黄在线播放| 亚洲成人制服丝袜av| 亚洲国产免费视频网站| 久久99久久久久久久久| 欧美青青一区二区三区| 亚洲中文字幕一区二区三区av| 97人妻在线公开视频| 黄色av在线免费播放| 综合久久国产中文人妻少妇在线| 国产很黄很色精品久久久| 熟女人妻中文字幕免费观看| 亚洲黄色资源在线浏览| 97com超碰在线免费| 国产免费午夜福利视频| 久久人妻公开中文字幕网| 亚洲乱码中文字幕综合久久| 亚洲一区视频在线免费播放| 欧美成人一区二区三区视频| 亚洲熟女一区二区av| 日韩丝袜诱惑网站大全| 日韩在线一区二区三区中文字幕| 在线成人免费观看视频网址| 欧美一区二区三区啪啪另类| 美女自拍偷拍亚洲一区| 青青在线观看国产免费视频| 色94色一区二区三区| 极品少妇av一区二区| 欧美专区一区二区在线| 亚洲国产日韩精品欧美| 亚洲精选清纯唯美自拍偷拍| 久久精品女人av一区二区| 中文字幕在线不卡97| 亚洲欧美视频在线观看网站| 自拍人妻欧美亚洲第三| 神马不卡午夜在线观看| 亚洲精品国产av久久| 美女黄网站永久观看网站不卡| 亚洲不伦丝袜人妻在线| 成人永久免费激情视频在线 | 亚洲精品沙发专享系列av| 亚洲精品国产精品乱码不卡| 91福利国产成人精品播放| 欧美三级精品三级在线| 人妻视频资源在线观看| 午夜av中文字幕在线观看| 国产偷拍自拍在线免费| 成人24小时免费视频| 中文字幕乱码不卡一区二区三区| 边摸边吃奶边做毛片视频| 青娱乐成人免费公开视频| 成人永久免费激情视频在线 | 97超碰人妻在线观看| 最近中文字幕免费mv在线直播| 国产欧美久久久久久精品一| 美女观看网站免费不卡视频| 国产自拍偷拍在线免费| 美女视频吃奶视频在线观看| av网站在线观看青青草| 亚洲激情视频在线观看视频| 欧美 日韩 成人 三级| 国产91av精品在线观看| 亚洲午夜av久久久精品| 亚洲黄色av中文字幕| 亚洲精品中文字幕一二| 男人插女人下面出浆视频| rct378在线中文字幕| 人妻系列少妇极品熟妇| 久久婷婷香蕉国产精品| 上海性战旗袍丝袜女郎| 青青青国产免费观看视频| 欧美情色一区二区三区| 91超碰国产在线观看| 日本一区二区三区不卡免费 | 大乳美女疯狂榨取精子视频| 激情av一区av二区| 国产精品久久久久精品| 深夜在线视频在线观看| 精品一区二区三区四区在线播放| 国产精品人妻中文字幕| 亚洲乱码国产一区二区| 中文字幕乱码日韩在线观看| 暖爱视频在线观看视频| 高跟丝袜诱惑后入av| 91国产自拍在线视频| 国产又粗又黄在线播放| 日韩人妻这里只有精品| 中文字幕人妻熟女人妻av| 日韩人妻有码一区二区| 国产成人不卡在线视频| 国产视频免费在线播放| 最新中文字幕av大全| 欧美一区二区三区aa大片漫| 二区三区免费在线观看| 国产熟女人妻在线观看| 日本中文字幕乱码免费视频| 亚洲欧美一级久久精品| 性色成人区人妻精品一区二区| 国产成人av午夜精品免费| av在线男人社区日韩| 亚洲国产日韩精品欧美| 国产欧美日韩精品在线| 99久久久精品免费看国产| 法国熟女乱淫xxoo| 日本国产一区二区在线观看| 日本一区二区三区不卡免费 | 国产护士性爽视频在线观看| 久久精品国产亚洲av四区| 免费成人三级在线观看| 少妇直播一区二区三区| 人妻少妇激情综合小视频| 轻轻插青青草视频在线播放| 亚洲国产熟女一区二区三区胖妞| 成人黄色免费观看网址| 日韩激情中文字幕在线| 男人和女人逼逼的视频| 国产成人乱色视频网站| 中文字幕乱码不卡一区二区三区| 午夜激情精品视频在线播放| 丰满人妻精品一区二区三区| 久亚洲国产精品蜜臀尤物| 污污污网址免费在线观看| 国产视频免费在线播放| 欧美久久久久久久久久久久久| 神马不卡午夜在线观看| 青青草原网址在线观看| 欧美午夜精品免费视频app| 欧美在线视频午夜精品| 免费一区二区三区四区av| 国内偷拍中文字幕蜜臀| 带个大鸡巴臭逼的视频。| 欧美一区二区国产一区| 欧美日韩午夜精品不卡综合| av天堂午夜精品蜜臀| 97在线观看的视频资源| 亚洲一级av对白刺激| 在线播放亚洲一级特黄片| 午夜免费在线观看小视频| 国产亚洲av久久精品| 国产一区二区不卡视频在线| 人妻在卧室被老板疯狂进入| 国外成人免费激情在线视频| 欧美午夜理论在线观看| 日韩欧美中文字幕人妻| 久久av成人中文字幕| 中文字幕在线免费看av| 最新中文在线乱码av| 黄色一级片久久久免费观看| 国产亚洲精品线视频在线| 最新国产网友自拍视频在线| 日本一区二区不卡精品| 国产有色视频在线网址| 青青青爽综合在线视频| 丰满熟女一区二区三区在线播放 | 天天操天天日天天射天天爽| 亚洲丝袜诱惑av在线| 国产乱人视频免费观看| 中文字幕在线视频亚洲| japanese少妇av| 亚洲国产一区二区久久| 欧美一区二区三区99| 97超碰人妻福利在线| 91偷拍老熟女露脸合集| 国产欧美在线视频观看| 老师美女脱了内裤露屁股| 在线播放99国产视频| 午夜性生大片免费在线观看| 亚洲人妻一区二区91| 欧美激情高潮无遮挡男男| 国产亚洲精品成人av丝袜| 色视频在线免费观看视频播放| 亚洲中文字幕乱码免费视频| 男生把小鸡鸡插到大美女的屁股| 中文字幕视频观看在线中文| 国产1区2区3区在线播放| 成人区人妻精品一区二| 青娱乐成人免费公开视频| 国产一二三自拍视频在线观看 | 中文字幕在线免费看av| 欧美一区二区三区爽爽爽| 97自拍视频国产视频| 国产深夜视频在线观看| 国产亚洲欧美日韩精品| 久久久免费一区二区三区| 国产精品一级二级盗摄羞羞| 国产小视频在线观看你懂得| 欧美久久久久久久久久久久久| 免费播放黄色操逼乱操逼| 色94色一区二区三区| 日本丝袜美腿在线观看| 97人妻超碰在线免费视频| 99re这里只有精品在线| 18免费在线观看av| 国产精品丝袜熟女一二三| 91最新精品视频在线观看| 91在线成人在线视频| 99久久国产综合精品五月天| 在线播放网站一区二区三区| 精品熟女少妇一区二区| 黄色av网站 亚洲精品| 国产97自拍视频在线观看| 久久香蕉亚洲欧美av精品| 成人国产精品视频在线| 白白色发布在线播放国产| 成人24小时免费视频| 日韩中文字幕人妻诱惑| 精品久久99在线观看| 午夜秘密播放器在线观看视频 | 亚洲欧美日韩精品麻豆| 最新成人精品视频在线| 少妇性生活久久久久久| 亚洲乱码国产一区网址| 日韩人妻这里只有精品| 国产网友自拍视频一区| 人妻熟女欧美一区二区| 中文字幕av网址在线| 亚洲国产日韩另类丝袜| 欧美日韩三级在线观看| 夜夜骚av一区二区三区啊| 成人国产一区二区在线| 国产高清免费不卡av| 成人黄色av免费网站| 肉色丝袜久久精品国产av| 国产精品一区二区精品视频| av大全一区二区三区| 最好看的中文字幕av| 亚洲国产熟女一区二区三区胖妞| 99久久国产综合精品五月天| 中文字幕女优乱码久久午夜| 蜜臀国产在线观看播放免费| 久久久久亚洲精品乱码按摩| 成人国产精品av在线| 黑丝美女的骚逼尖叫高潮声| 国产自拍av在线观看| 青青河边草观看完整版高清| 日韩国产中文字幕精品| av在线亚洲国产精品婷婷| av在线不卡中文字幕宾馆| 欧美在线免费在线视频| 国产三级视频在线18播放线观看| 熟女大胸白嫩自慰流白浆| 久久综合熟女中文字幕| 丝袜人妻激情在线视频| 亚洲一级二级三级国产av| 久久国产精品亚洲av| av中文字幕一区在线| 91性色福利在线视频| 黄色美女在线观看日韩| 国产自产拍午夜免费视频| 午夜精彩视频网站免费观看| 国产一级视频在线观看免费| 日韩熟女人妻国产av| 青青草日韩av在线播放| 亚洲 综合 欧美 日韩| 女人日男人30分钟视频| 成人国产一区二区在线| 国产欧美日韩精品在线| 青青青草原成人在线视频| 爽爽爽爽成人观看在线。| 精品成人一区二区三区在线观看| 亚洲av乱码在线观看| 欧美一区2区三区在线播放| 久久成人在线视频播放| 欧美日韩一区 二区 三区| 日韩中文字幕在线av| 97超碰人妻在线观看| 国产成人自拍视频网址| 国产熟女丝袜一区二区三区四区 | 亚洲成av人在线免费观看| 狠狠久久亚洲美洲专区| 丁香婷婷久久久久成人天堂国产| 精品人妻一区二区三区综合部| 5060午夜看片免费| 成人国产精品av在线| 中文字幕在线日韩第一精品| 人妻av在线中文字幕| 福利国产在线观看永久免费| 成人免费三级在线观看| 91在线国产视频观看| 日韩成人伦理片在线观看| 97超碰免费观看在线| 中文字幕久久久2029| 欧美情色一区二区三区| 久久人人妻人人做人人爽| 亚洲欧洲日产日韩激情| 国内网友自拍视频在线| 国产精品久久久久精品日| 波多野吉衣久久久久久| 人妻丝袜一区二区三区| 99九九久久国产精品| 人妻少妇激情综合小视频| 青草视频在线观看亚洲| 亚洲第一区二区在线观看| 日韩欧美群交P内射捆绑| 免费亚洲一区二区三区| 久久人人爽人人爽人人片669| 国产情侣免费观看视频| 青青草原免费体验视频| 精品视频在线观看91| 97人妻中文字幕精品一区在线| 国产精品露脸自拍av| 熟女人妻中文字幕免费观看| 久久久久人妻精品一区二区三区| 久久国产精品9999p| 成年人黄色片视频网站| 男人天堂中文字幕av| 一区二区三区中国大乳房熟女| 亚洲黄色av中文字幕| 色婷婷国产精品免费视频| 18免费在线观看av| 超视在线免费观看视频| 18免费在线观看av| 九九激综合五月天国产| 超级碰碰碰视频免费观看| 亚洲成人制服丝袜av| 少妇人妻一区二区三区3d| 成人日韩av一区二区| 日韩欧美成人精品视频在线| 97人妻免费在线视频| 亚洲乱熟女一区二区三区com| 国产亚洲精品线视频在线| 小视频在线观看你懂的| 在线 av 中文字幕| 91av在线观看蜜臀| 久久精品国产高潮av| 97国产视频在线免费观看 | 丰满人妻一区二区三区精品av| 你懂的视频精品在线观看 | 国产又粗又黄在线播放| 久久一区二区三区av| 色综合久久综合欧美综合| 亚洲一区二区在线看看| 久久婷婷香蕉国产精品| 美女黄网站永久观看网站不卡| 欧洲乱码在线观看视频| 成熟人妻一区二区三区| seseav在线观看| 欧美成年一区二区三区| 最近中文字幕免费观看av| 欧美激情高潮无遮挡男男| 亚洲第一区二区在线观看| 中文字幕在线不卡97| 久久91丨国产人妻熟女| 97自拍视频国产视频| 欧美情色一区二区三区| 国产成人不卡在线视频| 日韩欧美成人精品视频在线| 精品熟妇人妻一区二区三区四区 | 亚洲熟女久久一区二区| 成人永久免费激情视频在线| 试婚99天视频免费完整版观看| 亚洲三级一区二区三区四区| 国产免费无码午夜福利蜜臀| 深夜视频在线观看免费| 韩剧熔炉在线完整免费观看| 美女黄网站永久观看网站不卡| 午夜18在线观看视频| 97国产视频在线观看| 狠狠久久亚洲美洲专区| 亚洲欧美另类视频一区蜜臀| 中文字幕国产av中文| 午夜在线观看视频你懂的| 日本一区二区三区不卡免费 | 亚洲精品 乱码久久久久久| 91成人精品亚洲国产| 色视频在线免费观看视频播放| 国产性感丝袜美女av| 国产一区二区蜜臀av| 久久久久人妻精品一区二区三区 | 白白色发布在线播放国产| 欧美性少妇一区二区三区| 欧美女奴靠bb唆大鸡巴群交| 美女自拍偷拍亚洲一区| 国产免费在线视频观看| 国产三级视频在线18播放线观看 | 国产精品丝袜久久久久久久久| 26uuu亚洲综合色欧美| 日韩欧美久久一区二区| 免费观看国产精品黄色| 国产精品髙潮呻吟久久av| 日韩美女美女黄色黄色片| 欧美日韩精品欧美日韩| 黄色十八禁精品无遮挡| 77成人在线免费视频| 美女制服丝袜高跟诱惑| 青青草原国产视频在线观看| 午夜精品视频一区二区| 日韩少妇一区二区三区四区五区| 日韩一区二区人妻9999| 国产精品久久久久久久久91| 国产午夜精品视频免费福利| 综合av一区二区三区| 自拍偷自拍亚洲精品10p| 欧美一区二区免费在线观看| 国产亚洲综合精品av| 欧美激情视频一区二区三区| 成人在线视频播放 亚洲| 超碰97在线视频观看| 久久久久这里只出精品| 日韩国产精品99久久久久久| 夜夜欢性恔真人免费视频| 久久久久久噜噜噜久久久精品| 国内精品人妻久久激情| 午夜av中文字幕在线观看| 女女同性女同区二区日韩| 欧美一区二区三区av| 一级一看免费完整版毛片| 色综合久久久久久久久8噜啦噜 | 国产国拍成人精品视频| 色一情一区二区三区精品| 人妻互换精品一区二区| 精品国产综合av蜜臀18| 久久国产麻豆免费播放| 国产欧美日韩精品在线| 一边吃扎一边插逼逼视频| 人妻熟女一区二区三区98| 久久精品国产v日韩v亚洲| 97人妻中文字幕精品一区在线| 26uuu亚洲综合色欧美| 美女黄a视频大全在线免费观看| 亚洲乱熟女一区二区三区com| av网站在线观看青青草| 免费播放黄色操逼乱操逼| 中文字幕人妻丝袜成熟乱三区| 久久99久久精品免观看吃奶| 亚洲精品自产拍在线观看动漫| 久久久久久精品一区二区三区| 国产熟女丝袜一区二区三区四区| 国产精品精品久久久18| 黄色污染网站在线观看| 欧美一区二区三区四区免费| 亚洲中文自拍另类av| 免费的黄网站在线观看视频| 久久热视频在线免费观看| 精品熟女少妇一区二区| 精品日本一区二区三区四区| 亚洲欧美日韩av在线观看| 亚洲中文自拍另类av| 国产色图视频在线观看| 丝袜人妻激情在线视频| 久久久久人妻一区精品在线观看| 男人操女人逼视频免费观看| 在线天天看片免费视频观看| 久久综合熟女中文字幕| 国产黄色片三级三级三级| 亚洲乱女色熟一区二区三区| 国产乱码伦人偷精品视频| 国产av 一区二区三区四区| 国产午夜福利精品理论片久久| 青娱乐 青青青操 天天日| 一本92午夜免费不卡福利片 | 人妻少妇亚洲自拍av| 久久久久久久久99密月| 国内自拍 都市激情 人妻| 国产97视频免费在线观看| 国产亚洲精品高清一区| 国产精品露脸自拍av| 午夜秘密播放器在线观看视频| av岛国一区二区三区久久| 熟妇精品一区二区三区| 美女制服丝袜高跟诱惑| 亚洲丝袜诱惑av在线| 绿帽老公让娇妻蒙眼被人操| 99视频精品视频观看| 伊人色综合久久天天伊人婷| 伊人av超碰伊人久久久| 欧美日韩乱码视频在线免费观看| 国产欧美在线视频观看 | 日本视频在线一区二区三区| 亚洲丝袜在线播放一区| 欧美亚洲另类一区二区三| 明星性感丝袜图片大全| av中文字幕每日更新| 黄黄的小视频免费在线播放| 欧美日韩激情一区二区在线观看| 26uuu亚洲综合色欧美| 色综合久久综合欧美综合| 国产视频在线观看视频| 亚洲午夜免费在线观看| 人妻av在线中文字幕| 久久久久久久亚洲综合| 欧美一区二区三区中文字幕| 中文字幕精品久久久乱码乱码| 91最新国产在线播放| 97资源超碰在线中文| 久久亚洲一区二区夜夜嗨| 国产成人不卡在线视频| 中文字幕在线亚洲视频| 国产精品永久免费自在线观看| 青青精品视频在线免费观看| 翔田千里精品久久一区二| 亚洲区域一区二区三区| 91人人妻人人做人人爱| 夜夜欢性恔真人免费视频| 中文字幕在线免费视频一区| 国产成人av午夜精品免费 | 亚洲综合色在线一区二区| 成人在线观看免费视频播放| 日韩成人伦理片在线观看| 久久人妻一区二区精选| 久久99av无色码人妻蜜柚| 国产精品久久久久久码| 97 在线免费观看视频| 欧美国产中文一区二区三区| 日韩美女肥臀毛茸茸的阴穴| 日韩中文字幕在线av| 久久人妻一区二区精选| 五十路熟女人妻在线网观看 | 在线播放一区二区三区三州| 亚洲成人制服丝袜av| 免费激情视频在线观看| 国产500部视频在线观看| 97人妻免费在线视频| 国产亚洲综合精品av| 国产传媒一区二区三区四区五区| 人妻精品在线观看视频| 午夜嗨起视频在线观看| 人妻少妇偷人一区二区三区 | 少妇直播一区二区三区| 国产伦精品一级二级三级| 国内少妇高潮毛片免费看| 久久精品国产v日韩v亚洲| 国产AV躁一二三区免费播放 | 国产精品久久人妻互换| 美女午夜写真福利视频| 久久久久久狠狠亚洲综合| 欧美日韩制服丝袜第一页| 麻豆国产成人av在线| 精品日本一区二区三区四区| 911精品在线免费观看| 成人啪精品视频网站午夜| 果冻传媒av精品国产网站| 男生把小鸡鸡插到大美女的屁股| 欧美国产中文一区二区三区| 国产一二三自拍视频在线观看| 青青热久免费精品视频| 国产91精品入口人妻| av在线观看亚洲中文| 国产一区二区三区伦理片一级| 性感丝袜美女写真视频| 久久人人妻人人做人人爽| 中文字幕人妻熟女人妻av| 5060午夜看片免费| 老熟女 一区二区三区| 亚洲精品你懂的在线观看| 人妻在线免费观看二区| 5060午夜看片免费| 日本伦理色呦呦在线观看| 日本午夜免费在线视频| 亚洲国产免费视频网站| 一区二区在线观看免费不卡| 久久99亚洲精品久久频| 久久精品国产v日韩v亚洲| 超长假大鸡巴从肛门捅到胃视频| 24小时在线播放免费观看| av天堂午夜精品蜜臀| 久久国产精品9999p| 国产成人av午夜精品免费| 日本一卡视频在线观看免费| 日本丝袜美腿自拍亚洲| 97视频在线免费观看网站| 中文乱码在线观看视频| 女人嫩水逼让大鸡巴操免费看| 亚洲三级一区二区三区四区| 国产亲乱的性视频网站| 青青青色视频在线观看| 精品日本一区二区三区四区| 蜜臀国产在线观看播放免费| 国产精品久久久久九九九九| 免费的黄网站在线观看视频| 成人黄色免费在线网站| 欧美熟妇乱色一区二区| av人妻一区二区三区| 最新欧美69堂在线视频| 高清在线一区二区三区亚洲综合| 国产精品美女久久久久久不卡| 国产精品美女自在线观看免费| 亚洲欧美另类视频一区蜜臀| 免费观看成人午夜激情视频| 大型黄色av网站在线播放观看| 精品 亚洲av 国产探花| av天堂免费在线播放| 欧美三级精品三级在线| 国产婷婷色一区二区三区五区| 老熟女 一区二区三区| 最大的黄色亚洲网站在线观看| 成人在线播放亚洲一区| 爱搞视频在线免费观看的网站| 国产精品久久久久久96| 午夜不卡在线免费视频| 亚洲国产精品黑丝美女| 欧美熟妇一级二级三级a| 久久99亚洲精品久久频| 免费的床上很黄不遮挡视频| 欧美女同性恋一区二区三区| 好想被狂操在线无码视频| 亚洲欧美另类视频一区蜜臀| 97视频在线观看免费播放| 韩国三级一区二区在线观看| 激情五月婷亚洲蜜臀av| 欧美 亚洲一区二区在线| 中文字幕在线免费看av| 香蕉免费一区二区三区在线观看| 色婷婷av国产精品欧美| 黄色av在线观看网址| 日韩在线不卡一区在线观看| 欧美亚洲另类自拍丝袜| 国产国拍成人精品视频| 超碰97在线公开观看| 久久久久久狠狠亚洲综合| 国产丝袜熟女人妻在线观看| 欧美成人天天综合在线视色| 亚洲乱码精品中文字幕| 国产视频在线观看视频| 精久久中文字幕人妻最新| 亚洲综合色区另类av| 国产熟女丝袜一区二区三区四区| 日本人妇十八禁在线观看| 男人靠女人靠厉害视频| 色av色婷婷91人妻久久久| 国产中文精品久高清在线不| 久久国产精品9999p| 你懂的视频精品在线观看| 日韩av在线日韩av日韩av| 精品人妻久久久久一区二| 成人十八禁av男人的天堂| 日韩av大片在线免费观看| 久久香蕉亚洲欧美av精品 | 大岛优香中文字幕av人妻| 久久综合久久狠狠综合| 一区二区三区欧美精选| 国产自拍免费精品视频| 久久人人妻人人做人人爽| 亚洲综合图片一区二区三区| 日韩三级黄色免费网站| 国产精品久久久久久码| 人妻少妇亚洲自拍av| 日本国产一区二区在线观看| 久久久久久久精品女人毛片| 免费一级av高潮喷水片特| 亚洲av成人噜噜网站| 久久亚洲国产精品成人| 日韩人妻有码一区二区| 欧美午夜精品免费视频app| 久久三级视频在线观看| 国产精品成人免费av| 亚洲国产日韩另类丝袜| 黄色av在线免费播放| 中文字幕乱码不卡一区二区三区| 欧美性色黄大片人与善| 少妇人妻一区二区三区3d| 欧美三级精品三级在线| 高跟丝袜诱惑后入av| 国产精品久久久久久96| 国产偷拍自拍在线免费| 直接免费观看黄色的网站| 国产欧美久久久久久精品一| 久久99亚洲精品久久频| 欧美一区二区三区伦理国产| av人妻一区二区三区| 精品欧美成人观看一级| 青草视频中文字幕在线观看| av中文在线中文av| 国产一区二区三区亚洲一区| 日本国产一区二区在线观看| 男人添女人下边视频免费| 中文字幕av在线观看网址| 国产亚洲精品高清一区| 欧美日韩三级在线观看| 中文字幕在线午夜人妻| 中文字幕在线视频亚洲| 在线中文字幕有码视频| 国产精品一级二级盗摄羞羞| 国产熟妇一区二区三区四区| 日本中文字幕乱码免费视频| 国产欧美在线视频观看| 国产AV无码专区AV麻豆| 亚洲av日韩综合一区在线观看 | 久久久久精品久久久久久| 国产偷拍自拍熟女视频| 亚洲一区二区欧美激情| 97人妻中出中文字幕| 熟妇久久久人妻中文字幕| 女生高潮喷水视频免费在线观看 | 国产成人黄色精品视频| 成人美女主播在线播放| 99久久精品婷婷久久久久久| 97在线观看的视频资源| 久久精品中文字幕乱码视频| 欧美一区二区三区四区免费| 久久人人妻人人做人人爽| 九九久久久久无限久久| 国产欧美日韩精品在线| 日韩不卡毛片午夜在线看片? | 熟女少妇久久中文字幕| 大奶少妇白虎高潮流视频| 欧美日韩乱码视频在线免费观看 | 97视频在线免费观看网站| 色婷婷一区二区三区四区在线| 精品一区二区三区四区在线播放 | 国产成人叼嘿视频在线观看| 好想被狂操在线无码视频| 巨乳少妇av中文字幕| av性感美女免费在线观看| 亚洲国产精品美女papa| 婷婷丁香精品一区二区三区| 91在线视频网站总站| 欧美熟妇乱色一区二区| 久久一区二区三区av| 国产欧美精品日韩精品视频专区 | 在线观看不卡一区二区三区| 人妻丝袜美腿中文字幕| 亚州精品一区二区@v| 久久精品人妻系列av| 99久久国产综合精品五月天| 中文字幕av网址在线| 国产视频免费在线播放| 人妻巨乳中文字幕亚洲在线| 亚洲 中文 字幕 人妻| 午夜男女爽爽爽爽爽爽爽| 欧美狠狠一区二区三区| 亚洲av无久久精品一区二区| 精品国产乱码久久久久久男人| 亚洲乱女色熟一区二区三区 | 自拍偷自拍亚洲精品10p| 青青青国产免费观看视频| 绝美人妻一区二区在线观看| 97在线观看视频免费视频| 精品成人一区二区三区在线观看| 一区二区在线观看免费不卡| av天堂午夜精品蜜臀| 久久国产精品99精国产| 国产精品入口蜜臀人妻| 亚洲av乱码在线观看| 内射中文字幕在线观看| 久久婷婷亚洲国产综合蜜臀| 日韩午夜在线视频不卡片| 国产精品亚洲在线播放| 在线观看黄色播放网站| 一道一本av精品久久毛片| 亚洲精品 乱码久久久久久| 综合久久国产中文人妻少妇在线| 欧美一区二区三区爽爽爽| av人妻一区二区三区| 青青草原免费体验视频| 欧美午夜理论在线观看| 亚洲国产精品黑丝美女| 可以看手机在线黄色视频网| 亚洲乱熟女一区二区三区com| 精品亚洲一区二区三区ftp| 91亚洲精品久久久久蜜桃| av一区中文字幕在线| 欧美成人一区二区三区视频| 人妻丝袜一区二区三区| 人妻一区二区在线免费播放| 亚洲欧美视频在线观看网站| 日韩欧美人妻激情一区| 国内偷拍中文字幕蜜臀| 精品久久久久久久久妇女| 抽搐高潮痉挛白浆无码av| av在线中文字幕播放| 中文字幕综合av一区二区三区| 中文字幕亚洲久久爽一区| 与女性一起行走男性应走| 黄色福利视频网址大全| 国产成人精品欧美日韩网站| 亚洲精品专区一区二区| 最新免费av在线观看| 丰满熟女一区二区三区在线播放| 久青青草视频在线播放| 亚洲观看一区二区三区四区| 法国大屁股骚妇口交视屏| 久久99av无色码人妻蜜柚| 国产熟妇一区二区三区四区| 精品成人一区二区三区在线观看| 内射中文字幕在线观看| 97久久公开视频在线| 欧美一区二区免费在线观看| 99视频一区在线观看| 欧美激情高潮无遮挡男男| 在线天天看片免费视频观看| 内射中文字幕在线观看| 国产精品自拍首页视频| 免费的黄网站在线观看视频| 国产一区二区在线直播| 超碰在线最新地址97| 色视频在线免费观看视频播放| 国产亚洲综合精品av| 中文字幕乱码日韩在线观看| 国产三级欧美系列日韩系列| 日本国产一区二区在线观看| 国模在线一区二区三区| 日韩欧美成人精品视频在线| 法国大屁股骚妇口交视屏| 91精品福利自产拍在线观看| 男人天堂中文字幕av| 日韩欧美国产精品综合| 欧美日韩午夜精品不卡综合| 亚洲一区二区在线视频播放| 精品人妻av中文字幕乱码男同| 大香视频依人在线中文字幕| 激情av一区av二区| 久久精品国产熟女亚洲av| 日韩 国产 欧美 在线 一区| 久久99只有这里有精品| 成人在线视频播放 亚洲| 日本性感丝袜女秘书诱惑| 在线91华人精品国产片| 男人插女人逼有声视频| 日本美女丝袜天天看人体| 欧美成人性做爰77777| 欧美亚洲另类丝袜在线| 久久亚洲一区二区夜夜嗨| 青草青青青青青青操死你| 自拍偷拍亚洲综合在线| 欧美性色黄大片人与善| 黄色在线观看不卡无广告| 最新免费av在线观看| 人妻一区二区免费播放| 韩国性感美女热舞视频| 午夜精品一区二区三区在视| 国产美女学生在线观看| 国内伦理视频在线观看| 国产有色视频在线网址| 午夜秋霞在线免费观看| 大奶少妇白虎高潮流视频| 人妻在线免费观看二区| 青青青草青在线视频免费观看了| 中文字幕人妻免费网站| 国产老人一区av二三区| 黄视频网站免费观看视频| 成人 中文字幕 熟女| 99视频精品视频观看| 国产精品久久久久精品| 羞羞av一区二区三区| 国产精品特级露脸AV毛片| 搬开女人下面使劲插视频| 91在线精品免费视频| 久久三级视频在线观看| 亚洲午夜av久久久精品| 网站免费黄色在线播放| 中文字幕在线午夜人妻| 91大神精品免费在线播放| 免费av在线网站中文字幕| 亚洲sm一区二区三区| 91精品久久久久久五月| 日韩国产中文字幕精品| 精品视频在线观看91| 青青成人免费在线视频| 大鸡巴操小嫩逼免费全裸| 国产盗摄一区二区三区在线| 三上悠亚在线中文字幕| 欧美日韩乱码视频在线免费观看 | 亚洲一区视频在线免费播放| 少妇直播一区二区三区| 最新中文字幕av大全| 成人av无码区二区三区| 97精品日韩在线视频| 亚洲欧洲偷拍另类av| 亚洲 人妻 有码 在线| 亚洲人妻av一区二区| 试婚99天视频免费完整版观看| 人妻av在线中文字幕| 爆操欧美牛仔裤肥臀大屁股| 国产精品欧美一区二区久久久| 日本一区二区三区人妻| 欧美在线免费在线视频| 亚洲一级二级三级国产av| 视频一区二区三区国产在线| 久久福利视频在线播放| 青青青青国产在线视频| 在线国产视频精品视频| 欧美激情视频一区二区三区| 超碰人妻免费一区二区| 久久99只有这里有精品| 中文字幕在线亚洲视频| 中文字幕中文av在线精品| 久久久久久久亚洲综合| 婷婷月色一区二区三区| 亚洲国产日韩精品欧美| 在线免费观看青青草av| 成人黄色免费观看网址| 能看国产小视频的网站| 国产精品髙潮呻吟久久av| 成熟人妻一区二区三区| 免费在线观看亚州av| 亚洲中文字幕乱码免费视频| 国产成人在线视频播放| 免费观看国产精品黄色| 国产欧美精品日韩精品视频专区 | 成人区人妻精品一区二| 少妇的玉足让我爽翻天| 日本一区二区三级在线观看| 先锋视频资源在线播放| 日本人妇十八禁在线观看| 亚洲一区二区欧美激情| 猫咪av成人永久网站网址| 亚洲欧洲偷拍另类av| 我的放荡丝袜美腿老师| 日本欧美一区二区视频| 在线观看午夜看亚太视频| 青青成人免费在线视频| 日韩 欧美 人妻 中文字幕| 亚洲三级视频一区二区三区| 午夜精品182视频国产| 爱搞一区二区三区av| 熟女人妻专区中文字幕| 亚洲在线欧美一区二区三区| 少妇人妻av毛片在线看| 最新中文在线乱码av| 国产精品久久久午夜夜伦鲁鲁| 试婚99天视频免费完整版观看| 最新成人精品视频在线| 久久久久久4久久久8| 午夜免费福利视频大全| 凹凸在线视频免费观看| 亚洲一区二区三区18| 最近中文字幕免费mv在线直播| 污污污黄视频免费观看| 国产乱码伦人偷精品视频| 国产欧美精选自拍视频| 人妻少妇偷人一区二区三区| 国产91av精品在线观看| 久久人妻公开中文字幕网| 成人在线视频播放 亚洲| 明日花绮罗人妻大乳av| 成人黄色在线免费播放| 国产在线日韩精品av| 日本免费一区二区三区中文字幕| 在线播放99国产视频| 极品少妇av一区二区| 久久香蕉亚洲欧美av精品| 国产爱爱视频在线播放| jizz视频在线观看| 久久久久久噜噜噜久久久精品| 欧美一区二区三区爽爽爽| 亚洲 中文 字幕 人妻| 97人妻在线公开视频| 美女国产高潮福利片在线看| 成人亚洲精品在线观看| 亚洲黄色分享大全探花| 97人妻中文字幕精品一区在线 | 得得的爱在线视频免费观看| 国产伦精品一级二级三级| 国产精品乱码在线观看| 黄色av在线观看网址| 天天操天天日天天射天天爽| 欧美一区二区三区啪啪另类| 日韩人妻久久中文字幕| 美女制服丝袜高跟诱惑| 国产aV无码片毛片一级韩国| 国产自拍精品在线视频| 一区二区三区在线网址| 欧美日韩在线精品激情| 国产av自拍资源网址| xxx日韩欧美黄色a| 美女午夜写真福利视频| 国产精品欧美一区二区久久久| 久久久久久4久久久8| 国产精品96乱子一级视频| 国产97自拍视频在线观看| 午夜秋霞在线免费观看| 人妻一区二区在线免费播放| 国产成人在线视频播放| 丰满熟女一区二区三区91| 久久99亚洲精品久久频| 99re成人精品免费视频| 午夜精品视频一区二区| AV午夜福利一片免费看久久 | 亚洲男人天堂超碰在线| 国产亚洲成人精品视频| 久久久久久久久久久高| 麻豆国产成人av在线| 97com超碰在线免费| av中文字幕官网天堂| 国产免费综合视频在线观看| 日韩一区二区三区人妻| 一区二区三区看国产片在线| 风间由美亚洲一区二区三区| 99热爱精品在线观看| 久久久久久狠狠综合一本| 99热精品素人在线国产丝袜 | 久久黃色特三片視頻視頻視視頻| 大岛优香中文字幕av人妻| 丝袜美腿在线观看一区| 国产精品中文字幕av在线 | 国产综合日韩精品欧美| 久青青草视频在线播放| 国产av中文字幕乱码| 97在线观看免费观看视频| 熟女系列丰满熟妇一区二区三区| 欧美日韩精品一级二级三级| 国产美女在线观看专区| 国产亚洲欧洲在线成人| 亚洲 人妻 有码 在线| 在线 av 中文字幕| 男人和女人的性生活视频| 男人天堂中文字幕av| 中文字幕熟妇久久久人妻| 男女av一区二区三区| 人妻中出中文字幕在线| 国产乱精品一区二区视频了| 白乳房天天官网性插视频| 中文字幕在线乱码观看| 亚洲综合色区另类av| 国产av 一区二区三区四区| 精品熟女一区二区三区免费视频| 色偷偷av一区二区三区| japanese少妇av| 国产高清三级在线精品福利| 熟妇久久久人妻中文字幕| 欧美亚洲另类丝袜在线| 大奶少妇白虎高潮流视频| 凹凸在线视频免费观看| 免费亚洲一区二区三区| av大全一区二区三区| av在线观看亚洲中文| 乱文丝袜乱文丝袜美腿视频| 国产精品久久久久精品| 26uuu亚洲综合色欧美| 亚洲丝袜诱惑av在线| 国产成人免费a在线资源| 亚洲另类激情综合偷自拍图| 国内少妇高潮毛片免费看| 亚洲成人av免费在线播放| 日本午夜免费在线视频| 亚洲真人丝袜av一区二区| 99视频一区在线观看| 成人免费三级在线观看| 国产精品露脸自拍av| 国产精品96乱子一级视频| 国产成人不卡在线视频| 伊人网av中文字幕精品在线| 97 在线免费观看视频| av人妻一区二区三区| 精品国产乱码久久久久夂| 亚洲欧美成人自偷自拍一区| 日韩熟女精品91中文字幕| 久久久21精品久久久| 久久乐国产精品亚洲综合| 国产美女爽到喷出水来视频99 | 精品亚洲一区二区三区ftp| VA乱伦无码视频免费播放| 日本欧美一区二区视频| 久久久久久久98亚洲精品| 97久久久久久久久久久| 最好看的中文字幕av| 人妻av在线中文字幕| 丰满人妻一区二区三区精品av | 岛国av丝袜在线播放|