当前位置:网站首页>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
边栏推荐
- 注意!PMP紧急缓考今天就截止了!
- Can data sources only be connected to Alibaba cloud cloud databases? Can't you connect the databases installed in Alibaba cloud servers?
- Industrial digitalization and new generation digitalization system design platform -- Lecture
- 抓包整理外篇fiddler————了解工具栏[一]
- 做跨境电商一定要学会用PRA软件,解放双手提高效率!
- 【译】clickhouse 22.4和22.5核心特性一览
- June 27, 2022 to July 3, 2022 (UE4 video tutorial)
- 【云驻共创】昇腾异构计算架构CANN,助力释放硬件澎湃算力
- Go 降序排序 取 Top N
- Ask flynk SQL cdc Can you synchronize multiple tables and then sink them into one table? Synchronized tables can be accessed through a joi
猜你喜欢

数据库MySQL语句期末复习 CTGU

Dnslog injection

IDM certification process log embedding point description

Google launches advanced API security to protect APIs from security threats

Small program graduation project based on wechat examination small program graduation project opening report function reference

【软件测试】2022年普通高等学校招生全国统一考试

Industrial digitalization and new generation digitalization system design platform -- Lecture

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

数据资产为王,如何解析企业数字化转型与数据资产管理的关系?

kubeadm创建kubernetes集群
随机推荐
Can I open an account today and buy shares today? Is it safe to open an account online?
注意!PMP紧急缓考今天就截止了!
[cloud resident co creation] shengteng heterogeneous computing architecture cann helps release the surging computing power of hardware
Ask the bosses why the number type of Oracle CDC becomes a string when printed out. How can it be converted back?
Does DMS SQL result set export support parameter transfer?
How to manage interface documents efficiently and gracefully
杂记:数据库go,begin,end,for,after,instead of
Small program graduation project based on wechat subscription water supply mall small program graduation project opening report function reference
如何从RHEL 8升级到RHEL 9
今天开户今天能买股票吗?在线开户是安全么?
Why can't China produce products like idea?
Konva series tutorial 3: Customizing drawings
Lumiprobe 蛋白质标记研究方案
PCB线路板布局和布线都有哪些设计要求?
EasyExcel 学习笔记
select/poll/epoll
Sharing-JDBC分布式事务之Seata实现
Is it reliable to open an account for the shares of Oriental Wealth software? Where is safe to open an account
Applet graduation design based on wechat conference room reservation applet graduation design opening report function reference
OneFlow源码解析:算子签名的自动推断