OneFlow源码解析:算子签名的自动推断

本文介绍了OneFlow深度学习框架中算子签名的自动推断过程,从Python前端到C++底层的执行逻辑。通过GDB追踪执行、Python Binding解析,特别是PyFunction和PyFunctionDispatcher在多接口签名自动推断中的作用,以及算子Functor的注册与执行机制。文章以Relu算子为例,详细展示了从Python调用到C++执行的完整流程,深入探讨了签名匹配、参数转换和错误处理等关键环节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

eb6c0f769e0063a07ea0f3ef6811808a.png

撰文 | 郑建华

OneFlow是一个原生支持分布式训练的、高性能的深度学习框架。最近读了一些OneFlow的源码、架构设计和代码实现的文章,简单梳理一下自己的理解。主要通过图形展示调用过程和类之间的关系,只对部分重要的代码作一下分析。

深度学习框架是一个复杂的系统,而用户使用最多的就是算子(op)。用户通过op构造模型,进行训练、预测。这个笔记就从op入手,看看从Python前端到C++底层,OneFlow如何执行算子的计算逻辑。

具体地说,以比较简单的Relu算子为例,分析如下代码怎么执行:

 
 
# import会触发一系列初始化工作,暂时忽略
import oneflow as flow
# tensor的实现其实很复杂,因为要融合local和分布式的global tensor
t = flow.tensor([-1, 0, 1])
r = flow.relu(t)

1

编译环境

在开始分析之前,需要搭建环境编译OneFlow的源码,因为有些代码是在编译构建过程中自动生成的。在分析的过程中,这些自动生成的代码也是必要的环节。

OneFlow提供了官方的编译镜像(https://hub.docker.com/r/oneflowinc/manylinux2014_x86_64_cuda11.2)。用这个镜像可以非常方便地搭建编译环境(https://github.com/Oneflow-Inc/oneflow#option-2-build-in-docker-container-recommended)。

我使用的OneFlow版本是v0.7.0。本地编译环境目录结构如下,build是

cmake的构建目录,oneflow是源码目录。

 
 
.
├── build
└── oneflow

编译比较耗时,可以把两个目录mount到容器,便于后续查看build目录中生成的文件。

在cmake配置、构建过程中,会下载很多第三方源码包,如果网络状况不好容易超时,直接重试cmake/make即可。

# docker run -itd -v $PWD/oneflow:/mnt/oneflow -v $PWD/build:/mnt/build \
#   manylinux2014_x86_64_cuda11.2 bash
cd /mnt/build
cmake -S /mnt/oneflow
cmake --build . # --parallel 8
cd ../oneflow/python
python3 setup.py bdist_wheel
pip install ./dist/oneflow-0.7.0+cpu-cp38-cp38-linux_x86_64.whl

用GDB追踪OneFlow的执行过程

王益:Use GDB to Walkthrough OneFlow Source Code(https://quip.com/JuQ0AuodVJn4

CMAKE_BUILD_TYPE=Debug cmake -S /mnt/oneflow
cmake --build . --parallel 8


source /mnt/build/source.sh
gdb python3


b oneflow::one::MakeLocalTensorFromData


run


import oneflow as flow


flow.Tensor([[1,2,3],[4,5,6]])

2

Python Binding

OneFlow底层是C++实现,通过pybind11实现Python Binding。月踏在从Python到C++调用过程分析对相关内容做了讲解。

2.1 Relu的Python包路径

 
 
# python/oneflow/__init__.py
from oneflow._C import relu


# python/oneflow/_C/__init__.py
from oneflow._oneflow_internal._C import *

2.2 module处理逻辑的注册

Python代码主要在python/oneflow目录,C++实现的包主要在_oneflow_internal下,pybind11的绑定代码位于init.cpp(https://github.com/Oneflow-Inc/oneflow/blob/release/0.7.0/oneflow/api/python/init.cpp):

 
 
PYBIND11_MODULE(_oneflow_internal, m) {
  // ...
  py::class_<::oneflow::cfg::Message, std::shared_ptr<::oneflow::cfg::Message>>(m, "CfgMessage");
  ::oneflow::cfg::Pybind11ModuleRegistry().ImportAll(m);
  ::oneflow::OneflowModuleRegistry().ImportAll(m);
}

其中OneflowModuleRegistry(https://github.com/Oneflow-Inc/oneflow/blob/release/0.7.0/oneflow/api/python/init.cpp#L106)是算子等模块的绑定;Pybind11ModuleRegistry(https://github.com/Oneflow-Inc/oneflow/blob/release/0.7.0/oneflow/api/python/init.cpp#L105)应该是自定义的、类似protobuf的配置数据结构的绑定。

从OneflowModuleRegistry开始的详细调用流程如下:


adb5dfae35c434e707438760a210ad84.png

把代码放到一起看看(https://github.com/Oneflow-Inc/oneflow/blob/release/0.7.0/oneflow/api/python/of_api_registry.cpp):

 
 
using SubModuleMap = std::map<std::string, std::vector<std::function<void(pybind11::module&)>>>;


SubModuleMap* GetSubModuleMap() {
  static SubModuleMap sub_module_map;
  return &sub_module_map;
}


// 修改map,执行注册
void OneflowModuleRegistry::Register(std::string module_path,
                                     std::function<void(pybind11::module&)> BuildModule) {
  (*GetSubModuleMap())[module_path].emplace_back(BuildModule);
}


void OneflowModuleRegistry::ImportAll(pybind11::module&am
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值