/
githubmirror
/
incubator-mxnet
Обзор
Документация
Войти
/
githubmirror
/
incubator-mxnet
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/c_api/c_api_function.cc
230 строк
8 KB
mozga
[Master] Clang-formatter: only src/ directory (#20571)
13 сен 2021, 16:28
Не верифицирован
13 сен 2021, 16:28
e359bcd
Код
Авторство
О чём код?
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /*! * \file custom.cc * \brief * \author Junyuan Xie */ #include <mxnet/c_api.h> #include <mxnet/base.h> #include <mxnet/ndarray.h> #include <mxnet/imperative.h> #include "./c_api_common.h" #include "../operator/operator_common.h" #include "../operator/custom/custom-inl.h" namespace mxnet { namespace custom_function { struct CustomFunctionParam { size_t num_args, num_outs; std::shared_ptr<MXCallbackList> info; std::vector<mxnet::TShape> out_shapes; std::vector<int> out_dtypes; }; std::vector<nnvm::NodeEntry> Gradient(const nnvm::ObjectPtr& n, const std::vector<nnvm::NodeEntry>& out_grads) { const CustomFunctionParam& params = nnvm::get<CustomFunctionParam>(n->attrs.parsed); nnvm::ObjectPtr g = nnvm::Node::Create(); g->attrs.op = nnvm::Op::Get("_backward_CustomFunction"); g->attrs.name = n->attrs.name + "_backward"; g->attrs.parsed = params; g->control_deps.emplace_back(n); g->inputs = out_grads; std::vector<nnvm::NodeEntry> ret; for (uint32_t i = 0; i < g->num_outputs(); ++i) { ret.emplace_back(g, i, 0); } return ret; } OpStatePtr CreateState(const nnvm::NodeAttrs& attrs, Context ctx, const mxnet::ShapeVector& ishape, const std::vector<int>& itype) { LOG(FATAL) << "Not reached"; return OpStatePtr::Create<void*>(nullptr); } void Forward(const OpStatePtr& state, const OpContext& ctx, const std::vector<NDArray>& inputs, const std::vector<OpReqType>& req, const std::vector<NDArray>& outputs) { LOG(FATAL) << "Not reached"; } void Backward(const OpStatePtr& state, const OpContext& ctx, const std::vector<NDArray>& inputs, const std::vector<OpReqType>& req, const std::vector<NDArray>& outputs) { const CustomFunctionParam& params = state.get_state<CustomFunctionParam>(); std::vector<NDArrayHandle> ptrs; std::vector<NDArray> cpys; std::vector<int> tags; std::unordered_set<int> input_tags({0}); std::unordered_set<int> output_tags({1}); auto dev_id = ctx.run_ctx.ctx.dev_id; for (const auto& i : inputs) { NDArray* nd = new NDArray(i.data(), dev_id); ptrs.push_back(reinterpret_cast<NDArrayHandle>(nd)); cpys.push_back(*nd); tags.push_back(0); } for (const auto& i : outputs) { NDArray* nd = new NDArray(i.data(), dev_id); ptrs.push_back(reinterpret_cast<NDArrayHandle>(nd)); cpys.push_back(*nd); tags.push_back(1); } op::custom::CustomOperator::Get()->Push( [=]() { CHECK(reinterpret_cast<CustomFunctionBwdFunc>( params.info->callbacks[kCustomFunctionBackward])( inputs.size(), outputs.size(), const_cast<NDArrayHandle*>(ptrs.data()), reinterpret_cast<const int*>(req.data()), ctx.is_train, params.info->contexts[kCustomFunctionBackward])); }, ctx, false, ctx.is_train, cpys, tags, output_tags, outputs); } inline bool InferStorageType(const nnvm::NodeAttrs& attrs, const int dev_mask, DispatchMode* dispatch_mode, std::vector<int>* iattr, std::vector<int>* oattr) { using namespace op; for (size_t i = 0; i < iattr->size(); ++i) { STORAGE_TYPE_ASSIGN_CHECK(*iattr, i, kDefaultStorage); } for (size_t i = 0; i < oattr->size(); ++i) { STORAGE_TYPE_ASSIGN_CHECK(*oattr, i, kDefaultStorage); } DISPATCH_MODE_ASSIGN_CHECK(dispatch_mode, 0, DispatchMode::kFComputeEx); return true; } NNVM_REGISTER_OP(_CustomFunction) .set_num_inputs([](const NodeAttrs& attrs) { const CustomFunctionParam& params = nnvm::get<CustomFunctionParam>(attrs.parsed); return params.num_args; }) .set_num_outputs([](const NodeAttrs& attrs) { const CustomFunctionParam& params = nnvm::get<CustomFunctionParam>(attrs.parsed); return params.num_outs; }) .set_attr<mxnet::FInferShape>( "FInferShape", [](const NodeAttrs& attrs, mxnet::ShapeVector* in_shape, mxnet::ShapeVector* out_shape) { const CustomFunctionParam& params = nnvm::get<CustomFunctionParam>(attrs.parsed); *out_shape = params.out_shapes; return true; }) .set_attr<nnvm::FInferType>( "FInferType", [](const NodeAttrs& attrs, std::vector<int>* in_type, std::vector<int>* out_type) { const CustomFunctionParam& params = nnvm::get<CustomFunctionParam>(attrs.parsed); *out_type = params.out_dtypes; return true; }) .set_attr<FCreateOpState>("FCreateOpState", CreateState) .set_attr<nnvm::FGradient>("FGradient", Gradient) .set_attr<FStatefulComputeEx>("FStatefulComputeEx<cpu>", Forward) .set_attr<FStatefulComputeEx>("FStatefulComputeEx<gpu>", Forward) .set_attr<FInferStorageType>("FInferStorageType", InferStorageType); NNVM_REGISTER_OP(_backward_CustomFunction) .set_num_inputs([](const NodeAttrs& attrs) { const CustomFunctionParam& params = nnvm::get<CustomFunctionParam>(attrs.parsed); return params.num_outs; }) .set_num_outputs([](const NodeAttrs& attrs) { const CustomFunctionParam& params = nnvm::get<CustomFunctionParam>(attrs.parsed); return params.num_args; }) .set_attr<bool>("TIsBackward", true) .set_attr<bool>("TIsLayerOpBackward", true) .set_attr<FExecType>("FExecType", [](const NodeAttrs& attrs) { return ExecType::kAsync; }) .set_attr<FStatefulComputeEx>("FStatefulComputeEx<cpu>", Backward) .set_attr<FStatefulComputeEx>("FStatefulComputeEx<gpu>", Backward) .set_attr<FInferStorageType>("FInferStorageType", InferStorageType); } // namespace custom_function } // namespace mxnet int MXCustomFunctionRecord(int num_inputs, NDArrayHandle* inputs, int num_outputs, NDArrayHandle* outputs, MXCallbackList* callbacks) { using namespace mxnet; using namespace mxnet::custom_function; API_BEGIN(); CHECK(Imperative::Get()->is_recording()); auto state = OpStatePtr::Create<CustomFunctionParam>(); CustomFunctionParam& params = state.get_state<CustomFunctionParam>(); params.num_args = num_inputs; params.num_outs = num_outputs; params.info.reset(callbacks, [](MXCallbackList* ptr) { reinterpret_cast<CustomFunctionDelFunc>(ptr->callbacks[kCustomFunctionDelete])( ptr->contexts[kCustomFunctionDelete]); }); std::vector<NDArray*> ndinputs, ndoutputs; ndinputs.reserve(num_inputs); ndoutputs.reserve(num_outputs); params.out_shapes.reserve(num_outputs); params.out_dtypes.reserve(num_outputs); for (int i = 0; i < num_inputs; ++i) { ndinputs.emplace_back(reinterpret_cast<NDArray*>(inputs[i])); } for (int i = 0; i < num_outputs; ++i) { NDArray* arr = reinterpret_cast<NDArray*>(outputs[i]); ndoutputs.emplace_back(arr); params.out_shapes.emplace_back(arr->shape()); params.out_dtypes.emplace_back(arr->dtype()); } nnvm::NodeAttrs attrs; attrs.op = nnvm::Op::Get("_CustomFunction"); attrs.parsed = params; Imperative::Get()->RecordOp(std::move(attrs), ndinputs, ndoutputs, state); API_END(); }