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

OneFlow源碼解析:靜態(tài)圖與運行時

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

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

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


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

1?

代碼示例

下面的示例代碼來自官方文檔(https://docs.oneflow.org/master/basics/08_nn_graph.html),是一個線性模型的前向計算。后續(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)時,與靜態(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

啟動各個節(jié)點的控制面(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

啟動各個節(jié)點的數(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)建一個全局的ProcessCtx(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/job/env_global_objects_scope.cpp#L132)對象。然后根據(jù)環(huán)境變量等配置,在各個進(jìn)程間創(chuàng)建gRPC和CommNet的連接,分別負(fù)責(zé)控制面和數(shù)據(jù)面的數(shù)據(jù)傳輸。其中在Bootstrap過程中會初始化全局的ProcessCtx(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/rpc/lib/grpc.cpp#L42),給每個進(jìn)程分配一個全局唯一的rank編號(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)造模型會比較繁瑣。

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)。因為Module通過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包時NewDefaultSession(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/__init__.py#L229)構(gòu)建的session。當(dāng)時沒有初始化,而是在Graph構(gòu)造時進(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í)行時會創(chuàng)建各種全局的資源管理器,比如: ?

LazyJobBuildAndInferCtxMgr

BufferMgr

RegstMgr

ActorMsgBus

ThreadMgr

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

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

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

setattr最重要的動作就是對_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對象。為什么要做這個動作呢?主要是靜態(tài)圖編譯需要借助Block類型來實現(xiàn)代理執(zhí)行的功能,這些功能不適合直接寫到 eager 下的 Module 和 Tensor 上。

這個轉(zhuǎn)換是在ModuleBlock構(gòu)造時調(diào)用set_origin(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/nn/graph/block.py#L131)完成的。對于子Module,會遞歸調(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屬性都會被轉(zhuǎn)換為對應(yīng)的Block對象。

所以,上述示例代碼中,GraphMyLinear實際存儲的是ModuleBlock,Graph.build執(zhí)行時獲取的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中,因為 Module 是做狀態(tài)共享的基本單位,而 Graph 是不允許復(fù)用的。

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

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

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

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

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

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

build函數(shù)

train

導(dǎo)入樣本和label

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

計算損失

計算梯度

返回loss

eval

導(dǎo)入樣本和label

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

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

4.4 小結(jié)

上述幾個類型的關(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?

邏輯圖的編譯

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

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

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

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

__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會繼續(xù)做一些優(yōu)化pass,然后構(gòu)建物理圖、初始化運行時Actor系統(tǒng)。__run會啟動一次DAG的運算。

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

在 Graph 中,build 函數(shù)里面的代碼執(zhí)行都在 graph_build_context 的作用域下,這樣實現(xiàn)了動態(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)。在這個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í)行時初始化。// LazyJobBuildAndInferCtxMgr mgr;mgr.OpenJobBuildAndInferCtx(job_name);

OpenJobBuildAndInferCtx會新建一個Job對象(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/job/job_build_and_infer_ctx_mgr.cpp#L32)、一個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:為計算圖添加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ù),針對其中的每個tensor都在邏輯計算圖中插入一個FeedInputOp(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/system_ops.h#L48)節(jié)點。也就是說,model的輸入(比如樣本tensor,具體參考4.3節(jié)),在靜態(tài)圖中也視為一個op操作。

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

遍歷ArgsTree,對args和kwargs的每個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)。后面會看到,model的output也會調(diào)用__build_io,所以這個函數(shù)名的意思應(yīng)該就是對model的輸入、輸出進(jìn)行靜態(tài)圖的構(gòu)圖工作。

build_graph_input_arg內(nèi)部會構(gòu)造一個FeedInputOpExpr(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/python/oneflow/framework/graph_build_util.py#L213),提交給解釋器執(zhí)行。因為是在lazy作用域內(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會將對應(yīng)的op插入靜態(tài)圖。

附:build input時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í)行時,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)建的那個LazyJobBuildAndInferCtx對象,這個對象負(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,使得各個節(jié)點構(gòu)成一個DAG。

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

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

LazyInterpreter::ApplyImpl的最后,會調(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)造一個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ù)的計算圖構(gòu)建。

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

后面會看到,靜態(tài)圖的運行期已經(jīng)沒有tensor的概念。運行期看到的只是更廣義的Regst存儲,可能代表tensor/blob,也可能是其它控制信息。靜態(tài)圖運行時的輸入,是直接讀取外部 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)會調(diào)用GraphMyLinear.build(),以及ModuleMyLinear.forward()。因為是在lazy模式下運行,matmul和add都會調(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屬性時(如weight/bias),會觸發(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)。這個是怎么執(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è)置個斷點能讓整個調(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"]

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

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

在這個函數(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時,matmul 會被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 中添加一個 matmul operator。同理后面的加法會在 job 中添加一個 add operator。

self.weight 和 self.bias 會觸發(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)。從而增加一個FeedVariableOp到計算圖(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/op_interpreter/lazy_op_interpreter.cpp#L527)。為什么設(shè)置和調(diào)用會距離這么遠(yuǎn)呢?主要是為了讓參數(shù)盡量和消費參數(shù)的 Operator 在一個作用域下,所以實現(xiàn)成了惰性求值來達(dá)到延遲計算的目的。

再后面的步驟就是調(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也是一個op。

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

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

5.4 邏輯圖優(yōu)化

在__build_graph中會調(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。本文的示例代碼比較簡單,并不是典型的計算場景,其forwar和ful計算圖的拓?fù)涫且粯拥?。實際大部的圖優(yōu)化都實現(xiàn)在這個階段,如 Op fusion、AMP、ZeRO、常量折疊等等。

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

隨后會構(gòu)建一個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)。這個對象將負(fù)責(zé)構(gòu)建物理計算圖Plan。它也是整個運行時的擁有者和維護(hù)者。這個對象析構(gòu)時,整個運行時也會有序終止并釋放資源。

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)。

在這個函數(shù)中,JobCompleter().Complete()(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/nn_graph.cpp#L280)會繼續(xù)對邏輯圖做幾輪修改優(yōu)化,補全 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é)點進(jìn)行的(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/nn_graph.cpp#L282)。master節(jié)點會將Plan通過gRPC推送給各個worker節(jié)點(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/framework/nn_graph.cpp#L308),worker節(jié)點從master拉取物理計算圖(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)備初始化運行時了。

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

最終生成的compiled邏輯圖如下??蚣茏詣硬迦肓撕芏嘞到y(tǒng)控制節(jié)點。

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

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

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

Plan.task中的每個元素是一個task,其中的exec_sequence.exec_node對應(yīng)job中的op,通常只有一個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)系。這個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是消費者,

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

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

6?

運行時的初始化

NNGraph::CompileAndInitRuntime中,new Runtime這行代碼會初始化運行時(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會創(chuàng)建Regst和Kernel

給沒有輸入的source_tasks發(fā)送啟動信號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)會將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)造時會創(chuàng)建一個物理線程(?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字段是一個map。如果這個map的所有key都是in_ctrl(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/job/runtime.cpp#L54),這個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)會給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)實體的協(xié)作關(guān)系如下

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

actor_id就是task_id,是在編譯Plan時就確定的。task是編譯時概念,actor是對等的運行時概念。

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ò)的整個物理圖Plan中,actor id相當(dāng)于地址,通過它可以定位唯一的actor實體。

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 入隊消息(https://github.com/Oneflow-Inc/oneflow/blob/4856d691051accd72f13f4139d281e411977b297/oneflow/core/thread/thread.h#L40)。

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

如果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)該會根據(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é)消息的接收和處理。

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

從本地隊列中取出一個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收到消息后,會判斷是否滿足了Act的條件,如果滿足,則會執(zhí)行Act,從而調(diào)用LaunchKernel執(zhí)行計算,Act執(zhí)行結(jié)束后通過ActorMsgBus發(fā)消息通知上下游Actor。

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

6.4 激活source Actor

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

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

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

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

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

7?

Actor

7.1 Actor的創(chuàng)建

Thread在創(chuàng)建Actor時,會先嘗試創(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。

示例代碼的各個節(jié)點對應(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ù)實現(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實例。和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)。一個Actor通常只有一個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)的運行時概念是Regst(https://github.com/Oneflow-Inc/oneflow/blob/release/v0.8.0/oneflow/core/register/register.h#L24),它持有Kernel需要讀寫的內(nèi)存。Regst的概念比Tensor更寬泛,比如框架自動添加的控制Op也會用到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)只記錄需要消費的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í)行計算時,actor能順利執(zhí)行。后面分析Actor的消息處理時會再回過頭來討論一下。

調(diào)用InitBnInOp2BlobInfo會初始化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),這里允許各個Actor子類定制自己的初始化邏輯。通常會調(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 首先會根據(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)計數(shù)。

然后判斷讀寫計數(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 會在第一次執(zhí)行時去 InitBnInOp2Blob 和 InitActMsg。InitBnInOp2Blob 初始化 resgt 中的 bn 與 Blob 的映射關(guān)系,為 kernel 提供通過 bn 訪問 Blob 的功能。InitActMsg 會初始化好所有需要發(fā)送的消息避免后繼發(fā)消息時重復(fù)的構(gòu)建消息。

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

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

普通 Actor::ProcessMsg 會調(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 中類似,會根據(jù)不同的 regst 類型來分別處理,Actor 中對 regst 的狀態(tài)管理方式與 LightActor 不同,LightActor 中的方式更加高效,Actor 中能處理一些特殊情況。

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

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

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

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

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

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消息,這個消息就由HandlerWaitToStart函數(shù)處理。

HandlerWaitToStart校驗消息類型后,將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),實際就是調(diào)用新設(shè)置的handler HandlerNormal。

HandlerNormal中,如果是kCmdMsg,只允許是kStart(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L377)。通過消息類型校驗后,會直接調(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計數(shù) total_reading_cnt_ 歸 0,可消費的register計數(shù) ready_consumed_ 增加到 max_ready_consumed_,前者表示所有的消費者已經(jīng)讀取當(dāng)前 LightActor 的 Regst,后者表示當(dāng)前 LightActor 消費的所有 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)是各個子類自己實現(xiàn)的,一般主要是啟動kernel計算。

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

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

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

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

RegstSlot naive_produced_rs_;

RegstSlot inplace_produced_rs_;

RegstSlot naive_consumed_rs_;

RegstSlot inplace_consumed_rs_;

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

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

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

7.5 Actor上下游之間的通知機制

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)(這個變量表示已經(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)會將Regst指針從隊列中刪掉,相應(yīng)的可用(https://github.com/Oneflow-Inc/oneflow/blob/06a6af1c7f760ba4b12d2dfb8f73d7fda5c7dbab/oneflow/core/lazy/actor/register_slot.cpp#L49)register計數(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)時,如果是consumer發(fā)來的ack消息,會調(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的;同時遞減在讀的 register 計數(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有自己的消息處理機制(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/light_actor.cpp#L299),大致原理應(yīng)該是差不多的。

7.6 Act執(zhí)行的動作

根據(jù)上述討論,Actor收到kRegstMsg后也會進(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),啟動Kernel計算

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的存儲地址mut_dptr賦值(https://github.com/Oneflow-Inc/oneflow/blob/b17a9cd6b930b5817c63623fb682bd708377a93b/oneflow/core/kernel/wait_and_send_ids_kernel.cpp#L47

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

8?

啟動靜態(tài)圖的計算

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

主要調(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在等待的起跑信號。

9?

運行時的退出機制

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

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

9.1 Actor的退出

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

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

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

WaitAndSendIdsKernel這時候正在等待新一輪計算開始(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只會執(zhí)行異步消息發(fā)送(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L437)(不再進(jìn)入while循環(huán))

WaitAndSendIdsActor::HandlerNormal仍然會處理其它Actor發(fā)來的消息(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L340)。但因為IsCustomizedReadReady返回false,會進(jìn)入AsyncSendEORDMsgForAllProducedRegstDesc(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/lazy/actor/actor.cpp#L394)執(zhí)行。它會給每個下游發(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個變量都為0時(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)。

如果上述兩個變量有不為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),將它從自己的存儲中刪除(https://github.com/Oneflow-Inc/oneflow/blob/55b822e4d3c88757d11077d7546981309125c73f/oneflow/core/thread/thread.cpp#L89),并遞減運行Actor的數(shù)量。

9.2 Thread的退出

NNGraph重置runtime_導(dǎo)致運行時對象被析構(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)。同時,重置指針導(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ìn)程都有一套WaitAndSendIds等控制節(jié)點。這也容易理解,因為每個節(jié)點都要執(zhí)行__run和Buffer::Push/Pull,都要啟動本進(jìn)程的Actors執(zhí)行計算。

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

10.1 示例代碼

啟動方式參考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 斷點

11.1.1 Python斷點示例

# 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++斷點示例

啟動命令

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

斷點示例

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è)計(上篇)(https://zhuanlan.zhihu.com/p/337851255)

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

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

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

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

一個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è)計(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源碼解析:自動微分機制

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

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

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

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

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

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

歡迎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)鍵詞:

91麻豆精品在线播放| 在线天天看片免费视频观看| 青青精品视频在线免费观看| 精品人妻少妇一区二区三级| 亚洲精品国产精品乱码不卡| 国产丝袜熟女人妻在线观看| 老男人xx女人视频试看| 亚洲素人中文字幕在线| 中文字幕人妻欧美日韩熟女| 男人插女人下面出浆视频| 丰满人妻精品一区二区三区| 欧美一级色片在线播放| 成年网站在线视频免费| 国产高清三级在线精品福利| 97精品免费观看视频| 蜜臀av在线观看免费| 日韩国产在线不卡av| 中文字幕乱码日韩在线观看| 人妻精品在线观看视频| 男人和女人逼逼的视频| 精品人妻少妇嫩草一区二区三区| 精品国产黄片一二三区| 国产欧美日韩精品在线| 国内精品人妻久久激情| 日韩中文字幕人妻诱惑| 亚洲精品国产av久久| 日韩乱码中文字幕有码视频| 曰本在线精品一区二区三区| 国产黄色片三级三级三级| 97色老99久久九九爱精品| 国产欧美日韩综合精品一区| 熟女人妻专区中文字幕| 青青操视频在线观看免费观看| 亚洲精品中文字幕午夜| 亚洲精选清纯唯美自拍偷拍| 国产偷拍自拍在线免费| 中文人妻一区二区熟女| 国产亚洲精品成人av丝袜| 国产 剧情 在线 精品| 美女自拍偷拍亚洲一区| 蜜臀成人av在线观看| 国产自拍av在线观看| 97精品综合久久视频| 国产伦精品一级二级三级| 成人av在线播放网址| 亚洲黄色资源在线浏览| 成人区人妻精品一区二| 免费的床上很黄不遮挡视频 | 欧美成人一区二区三区视频| 亚洲国产日韩另类丝袜| 精品人妻久久久久一区二| 午夜av中文字幕在线观看| 99九九99久久精品| 青草青青青青青青操死你| 国产高清三级在线精品福利| 国产视频免费在线播放| 久久香蕉亚洲欧美av精品| 亚洲黄色av中文字幕| 国产成人黄色精品视频| 国产免费午夜福利视频| 午夜偷拍视频免费观看| 你懂得在线免费观看99| 日韩av中文在线免费观看| 九一精品人妻一区二区三区| 与女性一起行走男性应走| 中文字幕人妻丝袜成熟乱三区| 欧美一区二区三区四区免费| 麻豆av国语对白麻豆| 毛片久久久久久久久久久| 青青青视频自偷自拍视频1| 欧美熟妇乱色一区二区| 国产成人精品欧美日韩网站| 久久无语av中文字幕| 日本免费一区二区三区中文字幕| 亚洲国产自产一区二区c| 最近免费中文字幕大全高清3| 亚洲av综合av成人av在线| 国内精品伊人久久久久av| 婷婷月色一区二区三区| 国产视频午夜在线播放| 国产成人自拍视频在线| 国产中文精品久高清在线不| 亚洲国产精品美女papa| 99re这里有精品免费视频| 99九九久久国产精品| 中文字幕乱码在线观看| 日韩性感美女在线观看| 亚洲欧美日韩精品麻豆| 国产va欧美va精品va综| 99国产小视频在线播放| 成人在线视频免费播放| 国产精品久久久久久av色| 国产视频免费在线播放| 久久人人妻人人做人人爽| 国内自拍视频在线观看h| 91最新精品视频在线观看| 欧美高潮呻吟久久av无| 久久久久久精品一区二区三区| 丰满人妻视频一区二区| 中文字幕一区人妻激情| 免费观看国产精品黄色| 欧美一区二区三区色污| 99er在线免费视频| 国产免费无码一区二区视频无码| 欧美一区二区三区四区在线观看 | 亚洲熟女久久一区二区| 欧美一区二区在线观看网站| 欧美女奴靠bb唆大鸡巴群交| 女人嫩水逼让大鸡巴操免费看| 91在线视频网站总站| 日韩人妻这里只有精品| 国产爱爱视频在线播放| 免费亚洲一区二区三区| 国产精品96乱子一级视频| 亚洲一区美腿丝袜在线播放| 极品少妇av一区二区| 色综合久久综合欧美综合| 无码国模大尺度自拍视频在线看| 最近免费中文字幕大全高清3| 欧美激情视频免费观看| 亚洲精品午夜免费视频| 国产三区四区在线视频| 青青草草视频在线播放| av天堂中文字幕精品| 美女视频吃奶视频在线观看| 精选国产精品视频在线| 91在线精品免费视频| 一区二区在线观看免费不卡| av激情韩国在线播放| 91久久精品国产91性色| 国产成人av午夜精品免费| 青青色在线视频观看免费| 69人妻精品久久久久88| 白浆熟女精品国产91| 欧美一区二区三区资源| 亚洲乱码国产一区网址| 情趣丝袜美腿写真图片| 国产日韩制服丝袜第一页| 国产精品亚洲在线播放| 噜噜噜色综合久久天天综合| 免费激情视频在线观看| 亚洲一区二区在线看看| 星宫一花av中文在线| 白乳房天天官网性插视频| 亚洲国产免费视频网站| 国产亚洲精品高清一区| 日韩国产制服丝袜专区| 亚洲乱码国产乱码精品精91| 熟女大胸白嫩自慰流白浆| 夜夜骚av一区二区三区啊| 国产精品一级二级三级四级| 欧美日韩午夜精品不卡综合| 国产高清三级在线精品福利| 青青艹视频在线免费观看| 自拍人妻欧美亚洲第三| 区一区二区三在线播放| 国产高清av一区二区在线观看| 欧美成人动漫在线观看| 欧美性少妇一区二区三区| 亚洲欧美综合国产精品一| 久久人妻日韩一二三区| 91成人精品亚洲国产| 亚洲精品中文字幕午夜| 91在线国产视频观看| 日韩中文字幕人妻一区| japanese少妇av| 在线观看不卡一区二区三区| 亚洲国产日韩另类丝袜| 韩国三级一区二区在线观看| 丰满人妻熟妇又伦精品| 欧美国产日韩另类系列| 亚洲成人日韩免费在线播放| 色婷婷av一区二区三区网| 在线观看黄色播放网站| 国产高清免费不卡av| 中文字幕女优乱码久久午夜| 24小时在线免费观看高清视频| 熟女少妇久久中文字幕| 亚洲激情视频在线观看视频| av黄色资源中文字幕| 撒玛利亚女孩在线观看免费全集 | 熟女人妻专区中文字幕| 婷婷月色一区二区三区| 日日摸日日碰天天爽歪歪| 狠狠的干香蕉久久av| 能效等级一级二级三级| av岛国一区二区三区久久| 欧美一区二区三区资源| 国产性一交一乱―色―情人| 国产精品色哟哟在线观看视频| 亚洲无码AV在线免费观| 国产精品18久久久久久二百| 18成人黄色在线观看| 麻豆av国语对白麻豆| 日本一区二区三级在线观看| 1024日韩人妻区二区| 国产97视频免费在线观看| 亚洲男人天堂超碰在线| 成人亚洲精品777777| 国产 中文字幕 乱码 在线| 国产极品粉嫩交性大片| 丝袜美腿在线观看一区| 人妻少妇激情综合小视频| 国产乱码伦人偷精品视频| 精品一片二片三片在线| 欧美一区二区在线播放视频| 亚洲av无码一区二区三区免看| 在线观看国产视频播放| 美女黄a视频大全在线免费观看 | 精品久久久人妻中文字幕| 亚洲一区二区在线看看| 久久精品国产v日韩v亚洲| 国产香蕉97超级碰碰碰| 成人黄色精品视频网站| 青青青国产免费观看视频| 午夜偷拍视频免费观看| 亚洲第一区二区在线观看| 亚洲不伦丝袜人妻在线| 青青草原在线免费观看网址| 国产欧美久久久久久精品一| 美女国产高潮福利片在线看| 韩国三级一区二区在线观看| 国产欧美精品日韩精品视频专区| 撒玛利亚女孩在线观看免费全集| 日本免费精品一二三区| 中文乱码在线观看视频| 福利国产在线观看永久免费| 一边吃扎一边插逼逼视频| 免费观看国产精品黄色| 久久香蕉亚洲欧美av精品| 欧美一区二区国产一区| 亚洲精品沙发专享系列av| 成人A级毛片无码免费看| 夜精品一区二区无码A片| 精品一区二区三区四区在线播放| 超级碰碰碰视频免费观看| 99久久麻豆99久久免费| 最新成人精品视频在线| 国产成人黄色在线观看| 人妻熟女欧美一区二区| 国产自拍免费精品视频| 日本一区二区三区人妻| 女人日男人30分钟视频| 自拍人妻欧美亚洲第三| 97视频在线免费观看网站| 中文字幕在线不卡97| 成人午夜精品一区二区三区| 欧美成人网另类套图超市| 日韩欧美一区二区专区在线观看| 国产一区二区三区伦理片一级 | 欧美一区二区三区中文字幕| 日本视频在线一区二区三区| 法国熟女乱淫xxoo| 5060午夜看片免费| 超碰人妻免费一区二区| 一区二区三区欧美精选| 中文字幕av在线观看网址| 丝袜制服诱惑人妻av| 中文字幕在线免费视频一区| 久久久综合亚洲av家庭乱搞| 熟妇久久久人妻中文字幕| 丰满熟女一区二区三区91| 一区二区三区在线网址| 亚洲乱码在线免费观看| 日韩人妻少妇二三四区| 亚洲自拍一区在线观看| 国产偷拍自拍熟女视频| 亚洲区域一区二区三区| 国产精品久久久久久96| 91草草视频在线观看| 日韩欧美国产精品综合| 国产视频在线观看视频| 欧美女同性恋一区二区三区| 亚洲熟女一区二区av| 婷婷月色一区二区三区| 亚洲制服丝袜美腿在线| 午夜精彩视频网站免费观看| 青青免费在线播放av| 我想看男人日女人的逼| 凹凸在线视频免费观看| 成人国产麻豆一区二区| 女人嫩水逼让大鸡巴操免费看| 男人和女人逼逼的视频| 婷婷丁香精品一区二区三区| 黄色传媒在线免费观看| 国产97自拍视频在线观看| 成人区人妻精品一区二| 日本丝袜美腿在线观看| 欧美在线免费在线视频| 想神马有神马舞蹈视频| 亚洲午夜精品久久久久久人妖| 亚洲国产欧美精品在线| 国产精品一级二级三级四级| 久久久99人妻一区二区三区| 97在线观看视频免费视频 | 亚洲熟女一区二区av| 欧美不卡一区二区三区视频| 青娱乐成人免费公开视频| 午夜不卡在线免费视频| 黄视频免费看网站在线观看| 欧美 日韩 成人 三级| 91在线国产视频观看| 亚洲熟女久久一区二区| 国产精品丝袜久久久久久久久| 精品一片二片三片在线| 91自拍免费在线视频| 激情视频 超黄 在线免费| 国内伦理视频在线观看| 久草视频这里只有精品| 国产自拍免费精品视频| 欧美一区二区三区四区在线观看 | 国产性感丝袜美女av| 国产1区2区3区在线播放| 26uuu亚洲综合色欧美| 日韩国产偷拍自拍在线| 97人妻中文字幕精品一区在线| 人妻熟女欧美一区二区| 真人视频在线免费观看| 国产美女学生在线观看| 麻豆av国语对白麻豆| av资源中文在线天堂播放| 一区二区在线播放三区| 久久老熟女一区二区福利蜜臀| 91麻豆精品在线播放| 色av蜜臀av粉嫩av| 大阴茎疯狂抽插美女视频播放| 日韩美女美女黄色黄色片| 成年人黄视频免费观看网站| 精品国产污污污的网站| 日本青草视频在线观看| 欧美三级精品三级在线| 97人妻中出中文字幕| 青青草原网址在线观看| 可以看手机在线黄色视频网| 国产人妻一区二区免费播放| 亚洲丝袜在线播放一区| 男人和女人上床的真实视频| 国产精品丝袜熟女一二三| 涩播视频在线观看免费| 男人天堂中文字幕av| av中文字幕一二三四| 丰满人妻熟妇又伦精品| 久久久久久狠狠综合一本| 好想被狂操在线无码视频| 免费成人三级在线观看| 欧洲一区二区三区在线播放| 大型黄色av网站在线播放观看| 国产精品亚洲av二区三| 国产精品精品免费视频| 欧洲一区二区三区在线播放| 国产成人乱色视频网站| 自拍 偷拍 亚洲 欧美| 欧美高潮呻吟久久av无| 欧美日韩一区二区三区性| 激情五月婷亚洲蜜臀av| 国产亚洲欧美日韩三级| 99re这里只有精品在线| 自拍 偷拍 亚洲 欧美| 久久久精品久久久99| 亚洲欧美日韩一级免费| 女生高潮喷水视频免费在线观看| 国产福利精品久久av| 青青色在线视频观看免费| 久久久久久狠狠综合一本| 中文字幕乱码在线视频网站| 久久久久久精品一区二区三区| 国产中文精品久高清在线不| 亚洲av丝袜诱惑在线| 亚洲国产欧美精品在线| 熟女一区二区三区 在线| 久久人人妻人人做人人爽| 成年人黄视频免费观看网站| 国产情侣免费观看视频| 国产精品96乱子一级视频| 自拍偷拍亚洲综合在线| 久久精品国产高潮av| 91精品国产人妻国产在线| 国产精品自在在线午夜| 午夜秘密播放器在线观看视频| 亚洲国产日韩另类丝袜| av中文字幕人妻丝袜| 国产美女学生在线观看| 老熟女老熟妇一区二区| 中文字幕久久人妻综合| 在线成本人视频动漫高清| av黄色资源中文字幕| 日本午夜免费在线视频| 国产91情侣在线视频| 久久久久精品久久久久久| 亚洲欧美另类视频一区蜜臀| 在线看片免费人成视久网| 久久99久国产精品66| 99re这里有精品免费视频| 91在线视频网站总站| 亚洲欧美一区二区福利| 日韩性感美女在线观看| 24小时在线免费观看高清视频| 日韩三级黄色免费网站| 国产精品成人免费av| 在线观看国产精品av| 中文乱码字幕视频观看网站免费| 韩国床震吃奶摸下的激烈视频| 人妻一区二区免费播放| 免费一区二区三区四区av| 婷婷丁香精品一区二区三区| 成熟人妻一区二区三区| 亚洲国产免费视频网站| 自拍偷拍亚洲综合在线| 边摸边吃奶边做毛片视频| 亚洲熟女一区二区三区观看| 亚洲精品乱码久久久久久久久| 久久精品国产亚州av| 女人日男人30分钟视频| 九一精品人妻一区二区三区| 最新中文字幕av网站| 99久久精品婷婷久久久久久| 午夜精品一区二区三区在视| 久久久久这里只出精品| 日本人妻中文字幕在线| 肉色丝袜久久精品国产av| 亚洲精品自产拍在线观看动漫| 中文字幕视频观看在线中文| 日韩激情中文字幕在线| 97超碰人妻福利在线| 午夜男女爽爽爽爽爽爽爽| 国产精品成人自拍视频| 国产高清免费不卡av| 国产草草视频在线观看| 大象焦伊人久久综合网色视| 二区三区免费在线观看| 青青久久国内视频网站| 想神马有神马舞蹈视频| 美女扒开胸罩露出奶头免费| 精品国产污污污的网站| 丝袜熟女av一区二区三区| 一区二区三区 日韩 av| 91av在线观看蜜臀| 青春草视频免费观看在线| 国产精品美女自在线观看免费| 欧美激情一区二区二区| 国产视频免费在线播放| 久久久久亚洲av一区二区三区| 日韩精品乱码av在线播放| 久久夜色精品国产亚洲av老牛| 上海性战旗袍丝袜女郎| 亚洲欧美一区二区福利| 天海翼一区二区三区免费| 国产 欧美 日韩在线视频| 日韩中文字幕人妻诱惑| 欧美不卡一区二区三区视频| 高颜值美女视频在线观看| 国产高清在线一区不卡极品| 国产免费av国片精品| 噜噜mm视频在线观看| av中文在线中文av| 97精品免费观看视频| 欧美 亚洲一区二区在线| 青青青爽综合在线视频| 超视在线免费观看视频| 日韩熟女中文字幕一区| 久久久久这里只出精品| 丰满美女一区二区三区| 激情福利视频在线观看| 丰满人妻一区二区三区精品av| 国产揄拍视频在线观看| 79久久久久久久久久| 波多野吉衣久久久久久| 青青草原在线免费观看网址| 国产精品高潮呻吟在线观看| 亚洲乱码国产乱码精品精91| 久久久久久4久久久8| 国产免费综合视频在线观看| 国产精品久久久久久久久91| 国产中文精品久高清在线不| 国产91情侣在线视频| 亚洲乱码国产乱码精品精91| 成人国产一区二区在线| 欧美一区二区三区再线播放| 国产精品髙潮呻吟久久av| 79久久久久久久久久| 国产人妻一区二区免费播放| 亚洲黄色资源在线浏览| 色综合久久综合欧美综合| 97福利国产在线视频| 一区二区三区中国大乳房熟女| 青青草草视频在线播放| 97超碰在线公开免费| 久久精品人妻免费观看| 精品国产乱码久久久久夂| 91精品久久久久久久久| 欧美成人一区二区三区视频| 综合婷婷一区二区三区| 国内网友自拍视频在线| 国产偷拍自拍在线免费| 欧美成人天天综合在线视色| 精品视频在线观看91| 国产亚洲精品成人av丝袜| 人妻又爱又澡人人添人人爽| 蜜臀av在线观看免费| 成熟人妻一区二区三区| 久久久久久久98亚洲精品| 国产又粗又猛又爽又色视频| 亚洲一区二区三区成人在线| 在线国产视频精品视频| 国产精品亚洲av三区色| 久久久久久久久久久高| 精品国产污污污的网站| 国产精品久久久午夜夜伦鲁鲁| 男人操女人逼视频免费观看 | 日本国产一区二区在线观看| 亚洲一区二区三区18| 911精品在线免费观看| 日韩中文字幕人妻诱惑| 欧美一区二区国产一区| 熟妇久久久人妻中文字幕| 高清在线一区二区三区亚洲综合| 18免费在线观看av| 日韩丝袜诱惑网站大全| 欧美在线观看亚洲精品| 男人靠女人靠厉害视频| 亚洲男人天堂超碰在线| 性感丝袜短裙美女啪啪啪| 亚洲欧洲日产日韩激情| 国产 丝袜 欧美中文 另类| 人妻丝袜美腿中文字幕| 亚洲一二三区精品在线观看| 97人妻超碰在线免费视频| 欧美亚洲另类一区二区三| 在线中文字幕有码视频| 97在线观看的视频资源| 在线中文字幕有码视频| 人妻巨乳中文字幕亚洲在线| 久久久久久久久久久亚洲| 青青青色视频在线观看| 你懂的视频精品在线观看 | 欧美一区二区三区伦理国产| 与女性一起行走男性应走| 91麻豆精品在线播放| 中文字幕精品乱码久久久久| 成人av无码区二区三区| 日韩国产制服丝袜专区| 在线 av 中文字幕| 午夜精品福利一区二区蜜股av| 熟女少妇久久中文字幕| 国产高清在线免费观看不卡av| 亚洲国产免费视频网站| 亚洲黄色av中文字幕| 99久久久精品免费看国产| 青青草久久久久综合精品| 欧美午夜理论在线观看| 91超碰在线免费视频| 噜噜mm视频在线观看| 中文字幕亚洲久久爽一区| 亚洲av日韩综合一区在线观看| 国产乱码字幕精品高清人v| 91青青视频在线观看| 午夜不卡在线免费视频| 久久人妻公开中文字幕网| 美女扒开胸罩露出奶头免费| 少妇人妻一区二区三区3d| 91在线国产视频观看| 大奶少妇白虎高潮流视频| 男人添女人下边视频免费| 国产av自拍资源网址| 激情人妻校园春色亚洲欧美| 午夜精品视频一区二区| 97人妻免费公开视频| 成人免费看片98欧美| 亚洲中文字幕一区二区三区av| 99九九久久国产精品| 97在线观看的视频资源| 精品日韩欧美人妻系列| 人妻丝袜美腿中文字幕| 亚洲免费成人精品视频| 成人av在线av在线| 成人区人妻精品一区二| 成人激情自拍图片视频| 亚洲国内av不卡在线| 六年级小女生光滑的小嫩逼| 国产情侣免费观看视频| 成人24小时免费视频| 成人十八禁av男人的天堂| 欧美日韩一区二区三区性| 欧美女奴靠bb唆大鸡巴群交| 青青草原国产视频在线观看| 成人亚洲精品在线观看| 国产视频午夜在线播放| 一区二区三区 国产日韩欧美| 亚洲综合国产一区二区三区| 亚洲黄色分享大全探花| 欧美日韩午夜精品不卡综合| 69人妻精品久久久久88| 在线观看免费黄小视频| 97精品国产高清自在线| 成人在线视频播放 亚洲| 精品国产污污污的网站| 日本中文字幕乱码免费视频| 又色又爽又黄又视频毛片| 国产伦精品一级二级三级| 色av蜜臀av粉嫩av| 亚洲一区二区三区av网站| 成人区人妻精品一区二| 国产女人叫床高潮大片免费| 熟女人妻中文字幕在线看| 人妻巨乳中文字幕亚洲在线| 9999中文字幕在线视频| 男人和女人上床的真实视频| 日韩一区二区三区在线看片| 男人和女人逼逼的视频| 成人 中文字幕 熟女| 日本一区二区不卡精品| 亚洲一区二区在线视频播放| 乱文丝袜乱文丝袜美腿视频| 青青草久久久久综合精品| 91最新国产在线播放| 亚洲激情av一区二区三区| 国产500部视频在线观看| 亚洲精品国产精品懂色av| 久久久久久噜噜噜久久久精品 | 91av在线观看蜜臀| 熟妇久久久人妻中文字幕| 丰满熟女一区二区三区在线播放| 中文字幕乱码中文字幕| 人妻一区二区免费播放| 日韩美女肥臀毛茸茸的阴穴| 大阴茎疯狂抽插美女视频播放 | 丝袜美腿在线观看一区| 亚洲情色国产自拍偷拍| 1024日韩人妻区二区| 日韩欧美人妻激情一区| 91丨九色丨韩国人妖| av中文字幕官网天堂| 欧美一区二区三区啪啪另类| 成年av网站18不禁| 日韩三级黄色免费网站| 亚洲国内av不卡在线| 97免费视频国产在线观看| 高跟丝袜诱惑后入av| 男人添女人下边视频免费| 午夜激情精品视频在线播放| 爽爽爽爽成人观看在线。| av在线中文字幕播放| 白乳房天天官网性插视频| 国产精品成人自拍视频| 男女av一区二区三区| 国产羞羞黄色av网站| 日韩丝袜诱惑网站大全| 亚洲一区二区在线看看| 人妻熟女一区二区91| 欧美生活一区二区三区| 国产成人不卡在线视频| 美女视频吃奶视频在线观看| 亚洲一级二级三级国产av| 国产av成人专区一区| av中文字幕一二三四| 亚洲欧美一区二区三区黑人| 高潮毛片遮挡免费高清| 亚洲欧美另类视频一区蜜臀 | 精品国产污污污的网站| 一区二区三区欧美精选| 中文字幕精品久久久乱码乱码| 国产自拍免费精品视频| 94精品视频在线播放| 国产伦精品一级二级三级| 精品国产黄片一二三区| 日韩不卡毛片午夜在线看片? | 国产97自拍视频在线观看| 中文字幕亚洲久久爽一区| 国产成人叼嘿视频在线观看| 99精品人妻一区二区三蜜桃| 中文字幕乱码在线观看| 久久久99精品久久久久久久| 黄色网页在线免费观看| 风间由美亚洲一区二区三区| 在线观看不卡一区二区三区| 国产理论视频在线观看| 蜜月久久99精品久久久久久| 免费一级av高潮喷水片特| 国产一区二区三区在线h| 久久久久久精品一区二区三区| 最近中文字幕免费mv在线直播| 91最新精品视频在线观看| 日韩毛片无码永久免费韩| 国产AV无码专区AV麻豆| 人妻系列少妇极品熟妇| 97久久久久久久久久久| 亚洲美女乱1区2区3区| 午夜男女爽爽爽爽爽爽爽| 久久久久久久亚洲综合| 成人黄色在线免费播放| 午夜在线观看视频你懂的| 久久久久这里只出精品| 日韩一区二区人妻9999| 一区二区在线观看免费不卡| av天堂中文字幕精品| 精品人妻少妇一区二区三级| 青青色在线视频观看免费| xxx日韩欧美黄色a| 在线观看午夜看亚太视频| 亚洲欧美一区二区三区黑人| 久久国产麻豆免费播放| 得得的爱在线视频免费观看| 久久精品国产高潮av| 先锋视频资源在线播放| 久久黃色特三片視頻視頻視視頻| 熟女人妻中文字幕免费观看| 亚洲一区二区av在线| 青青草草视频在线播放| 韩国床震吃奶摸下的激烈视频| 中文字幕在线乱码观看| 97人妻免费在线视频| 国产黄色av网站在线| av中文字幕一二三四| 国产一区二区三区伦理片一级| 日本中文字幕乱码免费视频| 另类专区日韩有码中文字幕| 亚洲欧洲自拍拍偷第二页| 99爱在线精品视频免费看| 国产一区二区三区亚洲一区| 青青草原精品在线观看视频| 国产欧美日韩精品在线| 国产免费无码一区二区视频无码| 日韩熟女精品91中文字幕| 精品国产专区91精品| 中文字幕亚洲久久爽一区| 91偷拍老熟女露脸合集| 欧美生活一区二区三区| 色av色婷婷91人妻久久久| 在线看片免费人成视久网| 中文字幕乱码激情av| 性感丝袜美女写真视频| 老男人xx女人视频试看| 亚洲国产欧美精品在线| 亚洲一区二区三区18| 国产AV无码专区AV麻豆| 欧美性欧美三级全透明时装秀 | 在线亚洲视频中文字幕| 91成人资源在线观看| 国产日韩亚洲精品av| 成年人黄视频免费观看网站| 午夜草草视频在线观看| 亚洲综合图片一区二区三区| 一区二区三区蜜桃在线观看| 欧美性色欧美a在线视频| 很黄很色的视频免费在线观看 | 国产精品久久99久久久| 熟女人妻专区中文字幕| 精品亚洲一区二区三区ftp| 少妇极品一区二区三区| 国产av一区二区三区老鸦窝| 国产欧美一区二区精品性| 女女同性女同区二区日韩| 久久成人在线视频播放| 国产91av精品在线观看| 亚洲自拍偷拍 欧美激情| 青草视频中文字幕在线观看| 亚洲不卡码一区二区三区| 亚洲人妻av一区二区| 香蕉免费一区二区三区在线观看| 日本午夜免费在线视频| 你懂的视频精品在线观看| 中文字幕在线免费看av| 岛国av丝袜在线播放| 国产一区二区不卡视频在线| 成人免费看片98欧美| 亚洲一区二区三区色视频| 日韩av在线日韩av日韩av| 97人妻中文字幕精品一区在线| 日韩一区二区三区人妻| 欧美日韩三级在线观看| 免费一级av高潮喷水片特| 一边吃扎一边插逼逼视频| 亚洲乱码在线免费观看 | 黄黄的小视频免费在线播放| 人妻中文字幕免费av| 亚洲欧美丝袜美腿 综合| 精品国产一区二区三区不卡免费| 3p少妇欧美一区二区三区| 免费观看国产精品黄色| 国产a三级三级三级精品91区| 九九久久99最新精品| 大奶少妇白虎高潮流视频| 久久香蕉国产熟女线看| 欧美一区二区三区黄片| 99国产小视频在线播放| 一区二区三区看国产片在线| 国产精品高潮呻吟在线观看| 免费av在线网站中文字幕| 国产原创av在线免费播放| 亚洲国产精品美女papa| 亚洲欧美日韩一级免费| 熟妇精品一区二区三区| 久久亚洲国产精品成人| 麻豆国产成人av在线| 亚洲成人av免费在线播放| 亚洲国产一区二区久久| 久久久免费久久久精品| 黄色一级片久久久免费观看| 亚洲成人av区一区二区三区四| 国产欧美精选自拍视频| 久久综合熟女中文字幕| 国内精品人妻久久激情| 成人动漫视频在线观看免费| 青青青青草免费视频看看| 国产av成人专区一区| 在线看片免费人成视久网| 黄腔女兵最经典十句话| 成人动漫视频在线观看免费| 国产福利精品久久av| 日本一区二区三区不卡免费 | 精品人妻一区二区三区成人网 | 欧美国产中文一区二区三区| 日本精品一区二区三区精品在线| 99久久久精品免费看国产| 色综合久久综合欧美综合| 欧美 日韩 一区二区三区| 国产精品久久久久精品| 91精品国产人妻国产在线| 国产偷拍自拍在线免费| 97视频在线免费观看网站| 黄色传媒在线免费观看| 男人插女人逼免费视频| 成人动漫视频在线观看免费| 欧美日韩制服丝袜第一页| 亚洲成人av中文字幕免费播放| 国产中文精品久高清在线不| 国产99在线视频免费| 六年级小女生光滑的小嫩逼| 色94色一区二区三区| 激情五月婷亚洲蜜臀av| 亚洲一区二区三区18| 一区二区三区蜜桃在线观看| 欧美一区二区三区伦理国产| 久久久国产综合av天堂| 国产免费综合视频在线观看| 91最新精品视频在线观看| 亚洲国产免费视频网站| 欧美成人网另类套图超市 | 欧美午夜精品免费视频app| 嘴唇上长黄色的小点点| 欧美一区二区在线播放视频| 亚洲乱码在线免费观看| 国产视频自拍在线观看| 国产日韩精品在线欧美| 日韩成人av在线二区| 亚洲综合色区另类av| 欧美整片一区二区三区| 在线91华人精品国产片| 亚洲无av在线中文字幕男男| 中文字慕人妻一区二区在线视频| 国产在线日韩精品av| 国产免费综合视频在线观看| 老熟女 一区二区三区| 三级久久在线中文字幕| 亚洲一区二区av在线| av在线免费观看网3| 久久久久久精品久久久久久| 欧美一区二区三区伦理国产| 日本美女丝袜天天看人体| 午夜秘密播放器在线观看视频| 国产av成人专区一区| 亚洲一区二区在线视频播放| 一区二区在线观看免费不卡| 亚洲黄色av中文字幕| 97在线视频中文字幕| 国产一区二区三区伦理片一级| 97在线观看视频免费视频| 成人av在线视频资源| 日韩性感美女在线观看| 国内一区二区三区视频在线播放 | 99热爱精品在线观看| 美女制服丝袜高跟诱惑| 国产97视频免费在线观看| 国产sese在线播放| 成人国产一区二区在线| 国产女人叫床高潮大片免费| 亚洲精品自产拍在线观看动漫| 成人免费av网址在线观看| 亚洲综合国产乱码成人| 日韩欧美群交P内射捆绑| 国产自拍偷拍在线免费| av中文字幕官网天堂| 日韩av中文在线免费观看| 亚洲sm一区二区三区| 中文字幕国产av中文| 国产自拍偷拍在线免费| 伊人网av中文字幕精品在线| 日本丝袜美腿在线观看| 与女性一起行走男性应走| 最好看的中文字幕av| 日韩午夜在线视频不卡片| 日韩一级淫片蜜臀播放口| 97在线观看的视频资源| 亚洲 一区 二区三区| 欧美激情1区2区3区4区| 亚洲丝袜诱惑av在线| 日韩人妻丝袜美腿中文| 黄色传媒在线免费观看| 精选国产精品视频在线| 欧美日韩一区 二区 三区| 精品人妻一区二区三区综合部| 波多野吉衣久久久久久| 欧美一区二区国产一区| 日韩欧美久久一区二区| 96精品久久久久久久久| 猫咪av成人永久网站网址| 国产免费黄色av 网站| 高潮毛片遮挡免费高清| 成人动漫视频在线观看免费| 你懂的视频精品在线观看| 超碰在线公开内射日韩版| 欧美特级特黄a大片免费| 亚洲乱码中文字幕综合久久| 亚洲另类激情综合偷自拍图| 久久热视频在线免费观看| 亚洲欧美精品丝袜中文字幕| 在线观看资源青青国产视频| 国产av日韩精品久久| 丰满人妻熟妇又伦精品| 午夜av中文字幕在线观看| 国产sese在线播放| 99视频在线精品免费| 久久综合熟女中文字幕| 高潮毛片遮挡免费高清| 国产精品中文字幕av在线 | 中文字幕熟妇久久久人妻| 国产欧美日韩精品在线| 亚洲av丝袜诱惑在线| 噜噜噜色综合久久天天综合| 中文字幕乱码人妻久久精品| 日韩丝袜诱惑网站大全| 3p少妇欧美一区二区三区| 乱文丝袜乱文丝袜美腿视频| 国产性感丝袜美女av| 国产精品欧美一区二区久久久| 国产精品丝袜久久久久久久久| 亚洲男人天堂超碰在线| 制服 丝袜 欧美 国产精品| 国产1区2区3区在线播放| 亚洲一二三区精品在线观看| 超caopor在线公开视频| 日韩成人午夜福利片在线播放| 免费的床上很黄不遮挡视频| av天堂午夜精品蜜臀| 日韩人妻久久中文字幕| 亚洲av成人噜噜网站| 欧美午夜精品免费视频app| 午夜秋霞在线免费观看| 欧美性色欧美a在线视频| 国产护士性爽视频在线观看| av资源中文在线天堂播放| 国产男女淫片av免费观看| 娇小被黑人爆出水黑人复古| 亚洲国产欧美精品在线| 黄色美女在线观看日韩| 欧美日韩一区二区三区性| 成人av在线播放网址| 9999中文字幕在线视频| 国产高清免费不卡av| 最大的黄色亚洲网站在线观看| 欧美一区二区三区啪啪另类| 一区二区在线观看免费不卡| 久久99久久精品免观看吃奶| 亚洲制服丝袜美腿在线| 中文字幕av网址在线| 久久亚洲国产精品成人| 亚洲黄色av中文字幕| 91国产激情视频在线观看| 女人日男人30分钟视频| 少妇性生活久久久久久| 国产精品露脸对白播放| 精品亚洲一区二区三区ftp| 欧美日韩精品欧美日韩| 中文字慕人妻一区二区在线视频| 亚洲av日韩av无码专区| 日韩情色一区二区三区四区| 午夜精品一区二区三区在视| 亚洲成人av免费在线播放| 国内欧美一区一区三区| 青青免费在线播放av| 人妻中出中文字幕在线| 国产麻豆精品福利在线观看| 高清在线一区二区三区亚洲综合| 日韩情色一区二区三区四区| 午夜精品久久久在线观看| 美女黄a视频大全在线免费观看| 亚洲欧洲偷拍另类av| 午夜激情精品视频在线播放| 24小时在线播放免费观看| 国产小视频在线观看你懂得| 久久人人妻人人做人人爽| 在线观看免费黄小视频| 高颜值美女视频在线观看| 黄色av在线观看网址| 高潮喷水波多野结衣在线观看| 人妻少妇精品一区二区| 日韩熟女精品91中文字幕| 欧美一区二区在线播放视频| 日本一卡视频在线观看免费| 国产视频自拍在线观看| 国内揄拍国内精品人妻迷 | 我想看男人日女人的逼| 女人嫩水逼让大鸡巴操免费看 | 中文字幕在线视频首页| 国产自拍偷拍在线一区| 亚洲一区二区av在线| 亚洲国内av不卡在线| 国产福利在线播放视频| 一边吃扎一边插逼逼视频| 色一情一区二区三区精品| 亚洲av日韩av无码专区| 久久久精品久久久99| 久久久久99精品成人| 久久精品国产熟女亚洲av| 久久精品人妻免费观看| 欧美网址一区二区三区| 精品成人一区二区三区在线观看| 成人在线一区二区三区av| 亚洲熟女一区二区av| 青草视频在线观看亚洲| 爆操欧美牛仔裤肥臀大屁股| 小美女操老头和动物操逼| 国产对白av一区二区| 人妻熟女欧美一区二区| 国产男女淫片av免费观看| 亚洲在线欧美一区二区三区| 欧美性色黄大片人与善| 91亚洲精品久久久久蜜桃| 久久国产精品亚洲av | 黄色美女在线观看日韩| 在线观看的资源网97| 久久精品国产熟女亚洲av| 亚洲综合色在线一区二区| 与女性一起行走男性应走| 亚洲欧美另类视频一区蜜臀| 亚洲 自拍 露出 极品| 夜夜骚av一区二区三区啊 | 亚洲 欧美 日韩成人| 网站免费黄色在线播放| 国产中文精品久高清在线不| 中文字幕视频观看在线中文| 国产粉精品高潮呻吟久久av| 国产精品精品免费视频| 高颜值美女视频在线观看| 欧美亚洲另类自拍丝袜| 丰满人妻99一区二区三区| 国内少妇高潮毛片免费看| 成人在线观看免费视频播放| 国产熟女熟妇一区二区三区av| 国产精品一二av在线| 亚洲激情av一区二区三区| 亚洲三级视频一区二区三区| 免费精品国偷自产在线洗澡| 精品人妻伦一二二区久久| 国产成人av在线精品| 男人和女人的性生活视频| 青青青国产免费观看视频| 久久久久久久亚洲综合| 国产AV无码专区AV麻豆| 中文字幕视频观看在线中文| 久久国产精品亚洲av| 亚洲综合色在线一区二区| 欧美日韩一区三区不卡在线| 欧美一区二区三区资源| 欧洲一区二区三区在线播放| 青青草日韩av在线播放| 人妻一区二区三区精品免费| 另类专区日韩有码中文字幕| 噜噜mm视频在线观看| 国产500部视频在线观看| 免费av网址一区二区| 欧美一区二区国产一区| 凹凸在线视频免费观看| 欧美一区二区在线观看网站| 国产97视频在线观看| 精品国产99国产精品亚洲| 国产av成人专区一区| 欧美日韩激情午夜看片| 青青操新免费观看视频| 国产精品成人自产拍在线| 久久精品中文字幕乱码视频| 熟女一区二区三区 在线| 99人妻精品一区二区三区| 成人亚洲精品在线观看| 国产精品自拍首页视频| 午夜av中文字幕在线观看| 老女人乱淫一区二区三区| 国产精品一级二级盗摄羞羞| 亚洲精选清纯唯美自拍偷拍| 在线播放亚洲一级特黄片| 国产av 一区二区三区四区| 丰满人妻99一区二区三区| 中文字幕乱码在线观看| 98久久久久久久久久| carpon视频在线观看| 色婷婷一区二区三区四区在线 | 麻豆av国语对白麻豆| 久久精品人妻一区二区| 中文字幕乱码亚洲三区| 男人添女人下边视频免费| 久久99这里只有精品| 亚洲情a成黄在线观看动漫尤物| 国产视频二区在线观看| 一区二区三区国产欧美| av一区二区三区看片| 日韩欧美久久一区二区| 婷婷丁香精品一区二区三区| 性感美女肉色丝袜诱惑| 久久香蕉亚洲欧美av精品| 久久乐国产精品亚洲综合| 亚洲综合图片一区二区三区| 欧美不卡一区二区三区视频| 国产熟女人妻在线观看| 久久99久久精品免观看吃奶| 国产精品久久人妻互换| 久久人妻公开中文字幕网| 79久久久久久久久久| 人妻视频资源在线观看| 中文字幕免费av在线| 免费成人三级在线观看| av在线中文字幕资源网| 国产美女在线观看专区| 五十路熟女人妻在线网观看 | 久久99这里只有精品| 在线播放99国产视频| 国内网友自拍视频在线| 我的女人呻吟噢噢噢哦哦哦哦| 国产欧美日韩综合精品一区| 国产 欧美 日韩在线视频| 99久久麻豆99久久免费| 国产精品久久久久久久久91| 人妻av蜜臀一区二不卡| 高跟丝袜诱惑后入av| 青青河边草观看完整版高清 | 91最新黄色免费网站| 国产熟女熟妇一区二区三区av| 欧美 日韩 一区二区三区| 久久国产精品亚洲va麻豆| 亚洲av日韩精品久久 | 黄腔女兵最经典十句话| 猫咪av成人永久网站网址| 蜜臀成人av在线观看| 国产精品一级二级三级四级| 人妻又爱又澡人人添人人爽| 日本一区二区不卡精品| 人妻在线免费观看二区| 色婷婷综合精品久久久| 视频一区二区三区国产在线| 久久久久久噜噜噜久久久精品| 欧美少妇一区二区三区| 黄色福利视频网址大全| 免费a站网址在线观看| 欧美在线免费在线视频| 国产成人乱色视频网站| 欧美在线1区2区3区| 人妻巨乳中文字幕亚洲在线| 国产成人自拍视频在线| 亚洲综合色区另类av| 日韩 欧美 人妻 中文字幕| av中文字幕每日更新| 欧美精品免费在线播放| av一区二区三区看片| 欧美一区久久人妻中文字幕| 91色乱码一区二区三| 亚洲情a成黄在线观看动漫尤物| 二区三区免费在线观看| 伊人精品久久久久中文字幕| 日韩三级黄色免费网站| 欧美精品素人在线观看| 国产高清av一区二区在线观看| 少妇极品一区二区三区| 黄色免费网址在线播放| 欧美一级内射视频在线播放| 国产三级视频在线18播放线观看| 79久久久久久久久久| 综合人妻一区二区三区| 久久久21精品久久久| 久久av成人中文字幕| 日韩三级黄色免费网站| 成人免费视频免费在线观看| 外国大片在线免费观看| 久久久久人妻精品一区二区三区| 黄色美女在线观看日韩| 朋友的妈妈在线免费观看中字 | 国产av一区二区三区老鸦窝| 免费观看成人午夜激情视频| 中文字幕久久人妻综合| 波多野吉衣久久久久久| 又色又爽又黄又视频毛片| 国产熟妇一区二区三区四区| 在线中文字幕有码视频| 久久精品人妻免费观看| 欧美日韩精品欧美日韩| 人妻互换精品一区二区| 久久国产精品亚洲av| 国产97视频在线观看| 国产香蕉97超级碰碰碰| 人妻丝袜一区二区三区四区av| 日韩欧美久久一区二区| 专想操B的猛男操骚妇B| 亚洲一级av对白刺激| 中文字幕女优乱码久久午夜| 日韩女优精品在线观看| 久久久久人妻精品一区二区三区| 精品人妻久久久久一区二| 欧美在线免费激情视频| 高潮毛片遮挡免费高清| 日韩欧美人妻激情一区| 国产精久久久久久一区二区三区| 97人妻中出中文字幕| 韩剧熔炉在线完整免费观看| 男人和女人逼逼的视频| 欧美成人一区二区三区视频| 女人嫩水逼让大鸡巴操免费看| 国产欧美日韩精品一区二区三区| 欧美 日韩 成人 三级| 91偷拍老熟女露脸合集| 成人免费看片98欧美| 欧洲美女一区二区三区| 亚洲一区二区在线视频播放| 久久久久精品久久久久久| 国产成年免费观看视频| 激情av一区av二区| 国产精品久久久午夜夜伦鲁鲁| 激情福利视频在线观看| 色老久久精品偷偷鲁一区| 国产视频二区在线观看| 欧美一区二区三区中文字幕| 亚洲av乱码在线观看| 99热精品素人在线国产丝袜| 亚洲精品国产av久久| 欧美国产精品久久综合| 国产亚洲精品高清一区| 在线成人av一区二区| 桃色视频在线观看97| 带个大鸡巴臭逼的视频。| 国产a久久观看免费视频| av一区中文字幕在线| 精品99在线免费视频| 法国大屁股骚妇口交视屏| 国产免费无码一区二区视频无码| 白浆熟女精品国产91| 欧美日韩一区二区三四| 人妻久久一区二区三区精品99| 超污短视频网站在线观看| 男人和女人的性生活视频| 久久青青草原在线视频| 97精品综合久久视频| 日韩中文字幕人妻诱惑| 青青成人免费在线视频| 乱文丝袜乱文丝袜美腿视频| av人妻一区二区三区| 91公开在线免费视频| 日韩av大片在线免费观看| 国产偷拍自拍熟女视频| 26uuu亚洲综合色欧美 | 午夜免费在线视频国产| 国产视频免费在线播放| 这里都是国产视频精品| 国模在线一区二区三区| 亚洲人妻中文字幕网站| 国产女人叫床高潮大片免费| 亚洲高跟丝袜在线观看| 在线中文字幕有码视频| 日韩精品成人av高清在线观看| 91丨九色丨韩国人妖| 亚洲 综合 欧美 日韩| 99视频一区在线观看| 中文字幕人妻免费网站| 91性色福利在线视频| 国产视频在线观看视频| 国产精品丝袜熟女一二三| 在线观看不卡一区二区三区| 免费播放黄色操逼乱操逼| 性感丝袜美女写真视频| 中文字幕精品久久久乱码乱码| 黄色的网站免费在线看| 欧美情色一区二区三区| 久久久亚洲裙底偷窥综合| 国产乱码字幕精品高清人v| 鲁片鲁一区二区三区在线观看| 日韩人妻熟女中文字幕的视频| 国产精品久久久久久av色| av中文在线中文av| 国产原创AV蜜芽尤物一区 | 成人24小时免费视频| 欧美女奴靠bb唆大鸡巴群交| 撒玛利亚女孩在线观看免费全集| 极品少妇av一区二区| 国产日韩欧美精品久久| 国产视频在线观看视频| 成人日韩av一区二区| 日韩成人伦理片在线观看| 自拍偷拍色亚洲欧美色| 大帝av在线一区二区三区| 熟女系列丰满熟妇一区二区三区| 国产福利在线播放视频| 亚洲一区美腿丝袜在线播放| 风间由美亚洲一区二区三区| 97人妻免费在线视频| 国产欧美精选自拍视频| 视频一区二区三区日韩欧美| 日韩熟女少妇一区二区三区| 丰满人妻熟妇又伦精品| 久久精品人妻一区二区| 激情伦理一区二区三区| 乱文丝袜乱文丝袜美腿视频| 欧美激情一区二区三区成人| 日韩熟女少妇一区二区三区| 老男人xx女人视频试看| 黄色美女在线观看日韩| av在线中文字幕资源网| 青青草原精品在线观看视频| 国产97自拍视频在线观看| 美女胸18下看禁止免费视频| 在线播放一区二区三区三州| 国产va欧美va精品va综| 亚洲综合图片一区二区三区| 丝袜人妻激情在线视频| 九九久久99最新精品| 国产美女视频免费观看网| 91最新国产在线播放| 成人免费av网址在线观看| 91人妻精品一区二区三区不| 黄色一级片久久久免费观看 | 国产原创av在线免费播放| 亚洲一区视频在线免费播放| 中文字幕乱码在线精品| 法国熟女乱淫xxoo| 国产成人精品欧美日韩网站| 91麻豆精品在线播放| 可以免费看的黄色的网站| 人妻熟女一区二区91| 青草视频中文字幕在线观看| 久久99久久精品免观看吃奶| 日本免费一区二区三区中文字幕| 中文字幕在线亚洲视频| 青青青爽综合在线视频| av在线中文字幕播放| 国产揄拍视频在线观看| 97人妻超碰在线免费视频| 青青河边草观看完整版高清| 99视频精品视频观看| 国内精品人妻久久激情| 日韩人妻熟女中文字幕的视频| 97超频精品在线观看| 99国产精品久久全免费| 在线亚洲视频中文字幕| 超碰97在线公开观看| 成人国产一区二区在线| 暖爱视频在线观看视频| 明星性感丝袜图片大全| 2023国产精品自拍视频| 男女av一区二区三区| 韩国床震吃奶摸下的激烈视频| 99热爱精品在线观看| 国产亚洲欧美日韩精品| 午夜秘密播放器在线观看视频| 久久99只有这里有精品| 白白色发布在线播放国产| 亚洲欧美一区二区三区黑人| 99精品人妻一区二区三蜜桃| 国产aV无码片毛片一级韩国| 日本视频在线一区二区三区| 精品国产久久三级av| 日韩综合在线超乳人妻一区| 爱搞视频在线免费观看的网站| 久久精品国产v日韩v亚洲| 国产高清三级在线精品福利| 高潮喷水波多野结衣在线观看| 日韩国产中文字幕精品| av天堂午夜精品蜜臀| 久久亚洲国产精品成人| 国产麻豆精品在线视频| 亚洲自拍一区在线观看| 一区二区三区看国产片在线| 人妻一区二区在线免费播放| 爱搞视频在线免费观看的网站| 三级久久在线中文字幕| 日韩av在线日韩av日韩av| 最新免费av在线观看| 在线观看午夜看亚太视频| 欧美性色黄大片人与善| 久久久久人妻一区精品在线观看 | 夜夜骚av一区二区三区啊| 熟女人妻专区中文字幕| 外国大片在线免费观看| 午夜精品182视频国产| 俄罗斯大鸡吧操骚逼水多舒服| 日韩成人午夜福利片在线播放| 国产有色视频在线网址| 97人妻中文字幕精品一区在线| 亚洲中文字幕一区二区三区av| 久久久久久久久久久亚洲| 午夜嗨起视频在线观看| 99热精品素人在线国产丝袜| 亚洲乱码国产一区网址| 久久久久久久九九九b热| 国产伦精品一区二区三区视频下载| 成人黄动漫在线观看网站| 人妻一区二区免费播放| 少妇的诱惑免费观看完整版中文| 久久三级视频在线观看| 国产成人黄色精品视频| 久久国产精品亚洲av| 成人av日本在线观看| 99久久麻豆99久久免费| 亚洲 一区 二区三区| 成人黄色免费观看网址| 国产理论视频在线观看| 男人女人40分钟视频| 亚洲另类激情综合偷自拍图| 久久久久久4久久久8| 亚洲综合图片一区二区三区| 久久精品女人av一区二区| 亚洲一a区二a区三a区| 亚洲熟女一区二区av| 国产深夜视频在线观看| 久久久久久精品久久久久久| 99久久麻豆99久久免费| 蜜桃av精品视频一区二区三区| 国产精品丝袜熟女一二三| 久久国产精品99精国产| 亚洲一区二区三区成人在线| 激情视频网站在线观看| 粉嫩av一区在线观看| k到视频在线观看免费网站| 国内少妇高潮毛片免费看| 久久夜色精品国产亚洲av老牛| 边摸边吃奶边做毛片视频| 成人啪精品视频网站午夜| 午夜秘密播放器在线观看视频| 中文字幕在线乱码观看| 国产日韩精品在线欧美| 91在线精品免费视频| 青娱乐成人免费公开视频| 中文字幕精品久久久乱码乱码| 欧美一区二区三区资源| 亚洲国产成人精品久久久久| 国产视频自拍在线观看| 欧美性欧美三级全透明时装秀| 国产性一交一乱―色―情人| 国产午夜精品自拍视频| 91最新精品视频在线观看| 99久久麻豆99久久免费| 欧美一级内射视频在线播放| 国产精品久久久久精品日| 99re这里有精品免费视频| 99九九99久久精品| 我想看男人日女人的逼| 男女av一区二区三区| 色老久久精品偷偷鲁一区| 成人国产麻豆一区二区| 精品国产91av在线观看| 在线成人免费观看视频网址| 91国产激情视频在线观看| 日韩三级黄色免费网站| 人妻av蜜臀一区二不卡| 日韩丝袜诱惑网站大全| 欧美国产中文一区二区三区| 99久久国产综合精品五月天| 国产97自拍视频在线观看| 日韩国产在线不卡av| 成人在线免费播放视频| 久久精品久久一区二区| 久久久久久久98亚洲精品| 老熟女老熟妇一区二区| 色婷婷国产精品免费视频| 乱文丝袜乱文丝袜美腿视频| 亚洲av无久久精品一区二区| 国产一区二区蜜臀av| 午夜免费在线观看小视频| 国产亚洲av久久精品| 亚洲一级二级三级国产av| 翔田千里精品久久一区二| 国产真实乱子伦清晰对白| 国产婷婷色一区二区三区五区| 国产精品永久免费自在线观看 | 色偷偷av一区二区三区| 91最新国产在线播放| 亚洲av日韩精品久久 | 女人是为抠逼男人的鸡巴操逼| 国产三级视频在线18播放线观看 | 欧美狠狠一区二区三区| 国产午夜精品视频免费福利| 国产亚洲精品成人av丝袜| 黄视频网站免费观看视频| 青青青爽综合在线视频| 噜噜mm视频在线观看| 亚洲欧美日韩一级免费| 午夜日韩私人大片中国黄页网 | 国产 欧美 日韩在线视频| 天天操天天日天天射天天爽| 欧美精品网站在线视频| 果冻传媒av精品国产网站| 制服丝袜 日韩 国产| 在线天天看片免费视频观看| 成年人播放视频在线观看| 国产精品久久久久久久久91| 自拍人妻欧美亚洲第三| 青青草原国产视频在线观看| 中文字幕免费av在线| 亚洲 人妻 有码 在线| 久久久99人妻一区二区三区| 亚洲中文字幕乱码免费视频| av人妻一区二区三区| 国产a久久观看免费视频| 午夜秘密播放器在线观看视频| 国产精品成人中文字幕| 久久香蕉国产熟女线看| 欧美午夜激情福利国产| 99爱在线精品视频免费看| 亚洲国产一区二区久久| 真人视频在线免费观看| 午夜精品福利一区二区蜜股av| 一区二区三区 日韩 av| 国内自拍视频在线观看h| 丰满熟女一区二区三区91| 在线观看午夜看亚太视频| 99九九久久国产精品| 久久国产精品9999p| 超碰在线最新地址97| k到视频在线观看免费网站| 一区二区三区看国产片在线| 久久99精品久久久久蜜臀| 青青精品视频在线免费观看| 亚洲视频国产精品你懂得| 自拍亚洲一区欧美另类| 国产一区二区蜜臀av| 国产sese在线播放| 国产美女学生在线观看| 日韩欧美国产精品综合| 大阴茎疯狂抽插美女视频播放| 亚洲素人中文字幕在线| 青青草原国产在线免费观看| 午夜18在线观看视频| 久久久久久久精品女人毛片| 熟女人妻中文字幕免费观看| 中文字幕人妻A片免费看| 国产日韩制服丝袜第一页| 爽爽爽爽成人观看在线。| av人妻一区二区三区| 久久人妻公开中文字幕网| 欧美情色一区二区三区| 在线看片免费人成视久网| 欧美日韩在线精品激情| 国产av成人专区一区| 国产一区二区成人av| 国产又粗又长又黄又大的视频| 国产午夜精品自拍视频| 亚洲成人av免费在线播放| 97国产视频在线观看| 人妻系列少妇极品熟妇| 中文字幕乱码在线观看| av性感美女免费在线观看| 午夜免费福利视频大全| 77成人在线免费视频| 久久久久人妻一区精品在线观看 | 亚洲一区二区三区色视频| 美女黄a视频大全在线免费观看| 亚洲另类激情综合偷自拍图| 成人在线免费播放视频| 欧美熟妇一级二级三级a| 国产美女在线观看专区| 久久精品国产高潮av| 高潮毛片遮挡免费高清| 嘴唇上长黄色的小点点| 青青青青草免费视频看看| 最近中文字幕免费mv在线直播|