当前位置:网站首页>ONEFLOW source code parsing: automatic inference of operator signature
ONEFLOW source code parsing: automatic inference of operator signature
2022-06-28 18:34:00 【InfoQ】
# import It will trigger a series of initialization , Temporary neglect
import oneflow as flow
# tensor The implementation of is actually very complicated , Because we need to integrate local And distributed global tensor
t = flow.tensor([-1, 0, 1])
r = flow.relu(t)1、 Compile environment
.
├── build
└── oneflow# 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.whlCMAKE_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
# python/oneflow/__init__.py
from oneflow._C import relu
# python/oneflow/_C/__init__.py
from oneflow._oneflow_internal._C import *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);
}
using SubModuleMap = std::map<std::string, std::vector<std::function<void(pybind11::module&)>>>;
SubModuleMap* GetSubModuleMap() {
static SubModuleMap sub_module_map;
return &sub_module_map;
}
// modify map, Enforcement registration
void OneflowModuleRegistry::Register(std::string module_path,
std::function<void(pybind11::module&)> BuildModule) {
(*GetSubModuleMap())[module_path].emplace_back(BuildModule);
}
void OneflowModuleRegistry::ImportAll(pybind11::module& m) {
for (const auto& pair : (*GetSubModuleMap())) {
for (const auto& BuildModule : pair.second) { BuildSubModule(pair.first, m, BuildModule); }
}
}
void OneflowModuleRegistry::BuildSubModule(
const std::string& module_path, pybind11::module& m,
const std::function<void(pybind11::module&)>& BuildModule) {
// ...
BuildModule(m);
// ...
}static void OneflowApiPythonModule9623(pybind11::module&);
namespace {
struct OfApiRegistryInit {
OfApiRegistryInit() {
::oneflow::OneflowModuleRegistry().Register("_C", &OneflowApiPythonModule9623);
}
};
OfApiRegistryInit of_api_registry_init;
}
static void OneflowApiPythonModule9623(pybind11::module & m) {
m.def("relu", &functional::PyFunction<functional::ReluSchema_TTB>);
m.def("pow", &functional::PyFunction<
functional::PowSchema_TTT, functional::ScalarPowSchema_TTScB,
functional::ScalarPowSchema_TTSc, functional::ScalarReversePowSchema_TScT
>);
}3、 Automatic inference of multiple interface signatures
import oneflow as flow
r = flow.randn(1, 10)
flow.pow(r, 2)
flow.pow(r, flow.ones(1, 10))struct ReluSchema_TTB {
using FType = Maybe<one::Tensor> (const std::shared_ptr<one::Tensor>& x, bool inplace);
using R = Maybe<one::Tensor>;
static constexpr FType* func = &functional::Relu;
static constexpr size_t max_args = 2;
static constexpr size_t max_pos_args = 2;
static constexpr char const* signature = "Tensor (Tensor x, Bool inplace=False)";
static FunctionDef function_def;
};
// SchemaT Such as ReluSchema_TTB
template<typename... SchemaT>
class PyFunctionDispatcher {
public:
// schema_t It's No I A signature
template<size_t I>
using schema_t = typename std::tuple_element<I, std::tuple<SchemaT...>>::type;
// schema_size_ Is the number of signatures , such as relu yes 1,pow yes 4
PyFunctionDispatcher() : schema_size_(sizeof...(SchemaT)) {
signatures_.resize(schema_size_);
InitSignatures(std::make_index_sequence<sizeof...(SchemaT)>{});
}
template<size_t I0, size_t... I>
py::object call(const py::args& args, const py::kwargs& kwargs,
std::index_sequence<I0, I...>) const {
// T Is the signature of the current check , such as ReluSchema_TTB
using T = schema_t<I0>;
std::vector<PythonArg> parsed_args(T::max_args);
if (ParseArgs(args, kwargs, &parsed_args, T::function_def, T::max_pos_args,
/*raise_exception*/ schema_size_ == 1)) {
return detail::unpack_call(*T::func, parsed_args);
}
return call(args, kwargs, std::index_sequence<I...>{});
}
py::object call(const py::args& args, const py::kwargs& kwargs, std::index_sequence<>) const {
// throw error ...
return py::none();
}
private:
template<size_t... I>
void InitSignatures(std::index_sequence<I...>) {
__attribute__((__unused__)) int dummy[] = {
((void)(signatures_[I] = schema_t<I>::signature), 0)...};
}
private:
size_t schema_size_;
std::vector<const char*> signatures_;
};
// SchemaT Such as ReluSchema_TTB
template<typename... SchemaT>
inline py::object PyFunction(const py::args& args, const py::kwargs& kwargs) {
static PyFunctionDispatcher<SchemaT...> dispatcher;
return dispatcher.call(args, kwargs, std::make_index_sequence<sizeof...(SchemaT)>{});
}
// py module register
static void OneflowApiPythonModule9623(pybind11::module & m) {
m.def("relu", &functional::PyFunction<functional::ReluSchema_TTB>);
m.def("pow", &functional::PyFunction<
functional::PowSchema_TTT, functional::ScalarPowSchema_TTScB,
functional::ScalarPowSchema_TTSc, functional::ScalarReversePowSchema_TScT
>);
}- positional And keyword Argument type conflict
- In signature keyword The parameter name is in kwargs Does not exist in and does not accept the default value
- Parameter type does not conform to PythonArgCheck Specified internal type inspection requirements
- kwargs contain function_def Parameters not defined in
- take args Expand to each PythonArg Elements , adopt index_sequence And variable length template parameter package ;
- utilize function_traits Derive the function parameter type list ArgsType;
- As Function calls can be simplified to As<typename tuple_element<I, typename ArgsType>>()... The core is to get the actual type of each parameter and give it to As Handle , The final call ObjectAs Realize the conversion of various internal data types .
class PythonArg {
template<typename T>
T As() const {
return ObjectAsHelper<oneflow::detail::remove_cvref_t<T>>()(this).GetOrThrow();
}
};
template<typename F, typename R>
struct unpack_call_dispatcher {
template<size_t... I>
static R apply(const F& f, const std::vector<PythonArg>& args, std::index_sequence<I...>) {
// Here is an appropriate rewriting , hold ArgsType Pull it out
using ArgsType = function_traits<F>::args_type;
return f(args[I]
.As<oneflow::detail::remove_cvref_t<typename std::tuple_element<
I, typename ArgsType>::type>>()...);
}
};
template<typename F>
py::object unpack_call(const F& f, const std::vector<PythonArg>& args) {
constexpr size_t nargs = function_traits<F>::nargs;
using R = typename function_traits<F>::return_type;
return CastToPyObject(
unpack_call_dispatcher<F, R>::apply(f, args, std::make_index_sequence<nargs>{}));
}File ".../oneflow/api/python/functional/py_function.h", line 76, in call
TypeError: pow(): received an invalid combination of arguments. The valid signatures are:
*0: Tensor (Tensor input, Tensor exponent)
*1: Tensor (Tensor input, Scalar exponent, *, Bool inplace=False)
*2: Tensor (Tensor input, Scalar exponent)
*3: Tensor (Scalar exponent, Tensor input)flow.relu(1)
TypeException:
File ".../oneflow/api/python/functional/py_function.cpp", line 98, in ParseArgs
TypeError: relu(): argument 'x' must be tensor, not int- PyFunction yes pybind11 Of def Defined entry function , And save a for the operator dispatcher Object is used to infer the appropriate signature ;
- PyFunctionDispatcher Through the recursive call of template function, the automatic filtering of signature is realized , Save necessary information for parameter validation and exception prompt through member variables ;
- unpack_call The type of operator function to be executed is determined at compile time , This is in PyFunctionDispatcher You can't do it in ;
- unpack_call_dispatcher The role of the vector Expand to multiple elements 、 As an argument to the calling operator function , This is in unpack_call It can't be done in ;
- PythonArg yes Python And C++ Bridge of type conversion , At the same time, it undertakes the function of type inspection ;
- be based on yaml Generated 2 Group files ,yaml.pybind.cpp Call in pybind11 Of m.def Specify the function called by the module , And define the function signature Schema Structure as PyFunction Template parameters .yaml.cpp The specific execution function is defined in , Such as Relu. What connects the two is Schema Field of func, about Relu Operators , Signature Schema Of func Fields are functions functional:Relu.
4、 operator Functor Registration and execution of
static void _oneflow_function_library_0(FunctionLibrary & m);
// Call the registration function by defining a static variable
static int _oneflow_function_library_dummy_0 = []() {
FunctionLibrary* library = FunctionLibrary::Global();
_oneflow_function_library_0(*library);
return 0;
}();
void _oneflow_function_library_0(FunctionLibrary & m) {
m.add_functor<impl::ReluFunctor>("Relu");
};[=]() {
// Func Such as impl::ReluFunctor
Func func;
// func_name come from lambda binding , Such as Relu
return PackedFunctorMaker<func_type>::make(func_name, func);
}
Maybe<one::Tensor> Relu(const std::shared_ptr<one::Tensor>& x, bool inplace) {
static thread_local const auto& __op = CHECK_JUST(
FunctionLibrary::Global()->find
<
Maybe<one::Tensor>,
const std::shared_ptr<one::Tensor>&,
bool
> ("Relu"));
return __op->call(x, inplace);
}
[=]() {
// Func Such as impl::ReluFunctor
Func func;
// func_name come from lambda binding , Such as Relu
return PackedFunctorMaker<func_type>::make(func_name, func);
}// func It's a function variable , Type as impl::ReluFunctor
[func](const remove_cvref_t<Args>&... args) -> R {
return func(std::forward<const remove_cvref_t<Args>&>(args)...);
}- The same name may correspond to more than one Functor. So you can't just use your name as Functor Of key, Need to combine signatures .
- FunctionLibrary Manage all Functor. But singletons are not suitable for template classes , So through the embedded PackedFuncCreatorMap Save different signatures Functor.
- Each signature will specialize in one PackedFuncCreatorMap Template class , Then distinguish different by name Functor.
- First ,yaml Generated 2 individual cpp file , None Functor Information , Only Relu The name 、 as well as Functor Signature information for .Functor It is registered by name in each module .yaml And FunctionLibrary Interact by name and signature .
- secondly ,FunctionLibrary::find Back to PackedFunctor With template parameters ( The parameter is Functor Signature ).find Can I return directly to Functor What about objects? ? Mainly map It is inconvenient to store different types of Functor. Even if Functor Have a common virtual base class 、map Of value Store pointer , But not all Functor The implementation interface of is consistent , Virtual functions do not meet the needs of this scenario . therefore find Cannot return directly Functor object .
- PackedFunctor The role of , It puts the real Functor Wrapped in its own structure ; Its template parameters are the same as Functor The calling interface of is consistent ; its call Methods will Op All the input parameters of the pass lambda Forward to Functor.
- Functor Can act directly as PackedFunctor Member variables of ? It should be possible .PackedFunctorMaker::make The template parameters of also contain Functor. But this way everyone Functor We should specialize in one PackedFunctor, Compiled executable programs tend to swell . And now the implementation ,PackedFunctor Based on Functor Perform function signature specialization , The cost is to do a call forwarding ( Compiler has optimization space ?).
- from Python To C++ Call process analysis
- https://github.com/Oneflow-Inc/oneflow/tree/release/0.7.0
- Overview of deep learning
- The journey of an operator in the framework of deep learning
- The optimal parallel strategy of distributed matrix multiplication is derived by hand
- Train a large model with hundreds of billions of parameters , Four parallel strategies are indispensable
- Reading Pathways( Two ): The next step forward is OneFlow
- About concurrency and parallelism ,Go and Erlang My father is mistaken ?
- OneFlow v0.7.0 Release :New distributed interface ,LiBai、Serving Everything
边栏推荐
- 基于固态激光雷达辅助的十六线机械雷达和单目相机的外参标定方法
- 亿信华辰:地产企业数字化转型想要把握时代机遇
- Go all out to unreal
- Common DOS commands
- Lumiprobe非荧光炔烃研究丨DBCO NHS 酯
- golang json 序列化、反序列化 字符串反序列化成 map[string]interface{}
- How to use the current conversion function in SAP CDs view
- Learning notes: how to time 10ms for 51 single chip microcomputer (STC89C52)
- 运筹学note
- GCC getting started manual
猜你喜欢

How to upgrade from RHEL 8 to RHEL 9

数据库MySQL语句期末复习 CTGU

面部识别试验涉及隐私安全问题?国外一公司被紧急叫停

亿信华辰:地产企业数字化转型想要把握时代机遇

Chapter 2 processing files, cameras and GUI Cameo applications

Redis6 notes 04 master-slave replication, cluster, application problems, new redis6 features

Small program graduation design based on wechat real estate intermediary house viewing appointment small program graduation design opening report function reference

Lumiprobe丨Lumizol RNA 提取试剂解决方案

Small program graduation design based on wechat driving school examination small program graduation design opening report function reference

Lumiprobe非荧光叠丨氮化物研究丨3-叠丨氮丙醇
随机推荐
324. swing sequencing II
基于固态激光雷达辅助的十六线机械雷达和单目相机的外参标定方法
Is it reliable to open an account for the shares of Oriental Wealth software? Where is safe to open an account
DNSLog注入
select/poll/epoll
Small program graduation project based on wechat chess and card room small program graduation project opening report function reference
架构自治服务:构建数据驱动的架构洞察
Small program graduation project based on wechat subscription water supply mall small program graduation project opening report function reference
Use PEGA to develop a simple RPA program
curl: (56) Recv failure: Connection reset by peer
第2章 处理文件、摄像头和图形用户界面cameo应用
Introduction to kubernetes resource object and common commands
A preliminary study of IO model
双功能交联剂丨Lumiprobe 磺基花青7二羧酸研究
堆的概念和代码实现
io模型初探
请教大佬们,oracle cdc的NUMBER类型,打印出来为什么变成字符串了呢,怎么转换回去?
Redis6笔记04 主从复制,集群,应用问题,Redis6新功能
Small program graduation project based on wechat mobile mall small program graduation project opening report function reference
How to create a CSR (certificate signing request) file?