Skip to content
This repository has been archived by the owner on Nov 17, 2023. It is now read-only.

[2.0] Add cpp-package #20131

Merged
merged 48 commits into from
May 24, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
c0c4a0e
MXNet2.0: Add cpp-package
barry-jin Apr 6, 2021
b60808f
add tests
barry-jin Apr 8, 2021
ce056a0
switch to python3
barry-jin Apr 8, 2021
bc62d6b
update OpWrapperGenerator.py
barry-jin Apr 12, 2021
9fab1a9
Merge remote-tracking branch 'upstream/master' into cpp-package
barry-jin Apr 15, 2021
b6a16d9
test: test cpp-package on gpu
barry-jin Apr 15, 2021
0b90b83
test:update ci_test_cpp
barry-jin Apr 16, 2021
b3d121e
add softmaxoutput cuda support
barry-jin Apr 16, 2021
b3075a9
update build
barry-jin Apr 16, 2021
c6a40a2
update symbol
barry-jin Apr 17, 2021
64d1111
Revert "update symbol"
barry-jin Apr 17, 2021
b91d00e
update executor
barry-jin Apr 19, 2021
b12fb9a
update runtime_functions.sh
barry-jin Apr 19, 2021
43dc452
update cpp-package gpu build
barry-jin Apr 20, 2021
ec76a6c
update libcuda.so.1 sym link
barry-jin Apr 21, 2021
2271657
test: linked libraries
barry-jin Apr 22, 2021
1993a48
update
barry-jin Apr 22, 2021
b084c15
export LIBRARY_PATH
barry-jin Apr 22, 2021
fedef00
pack build/cpp-package/examples
barry-jin Apr 22, 2021
730d5eb
link libcuda.so.1
barry-jin Apr 22, 2021
21007f4
update jenkins
barry-jin Apr 22, 2021
e2aaec1
update dockerfile
barry-jin Apr 22, 2021
c06334b
turn on use_nvidia
barry-jin Apr 27, 2021
992d3d6
fix sanity
barry-jin Apr 27, 2021
8e4c0ba
fix build
barry-jin Apr 28, 2021
b1bd450
turn off use_nvidia
barry-jin Apr 29, 2021
64e2d16
update runtime_function.sh
barry-jin Apr 29, 2021
0ba0a4d
fix mlp
barry-jin Apr 29, 2021
7e9256a
fix gradient vanish
barry-jin Apr 30, 2021
f1ff96c
update cpp tests
barry-jin Apr 30, 2021
6540581
add more tests
barry-jin Apr 30, 2021
d055afd
add more tests
barry-jin Apr 30, 2021
cf104e5
turn on MXNET_USE_CPU
barry-jin Apr 30, 2021
ad4c370
fix sentiment inference
barry-jin Apr 30, 2021
887bb5a
fix cpu tests
barry-jin May 3, 2021
65c5d12
Revert "fix cpu tests"
barry-jin May 4, 2021
63fc6ad
update ci test
barry-jin May 4, 2021
1f20a20
update
barry-jin May 4, 2021
c6fc5cb
add back cpp doc
barry-jin May 4, 2021
d09dfec
add cross-compilation instructions
barry-jin May 5, 2021
f8350b3
add multi_threaded_inference_test
barry-jin May 7, 2021
f016683
update test script
barry-jin May 7, 2021
748941f
fix multithreaded docs
barry-jin May 7, 2021
d82e085
Update doc and add cpp-package sanity check
barry-jin May 10, 2021
605e7ac
fix sanity
barry-jin May 10, 2021
e49df4a
update
barry-jin May 10, 2021
6bddda2
update
barry-jin May 13, 2021
e9d8b45
add module api to amp list
barry-jin May 14, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
update symbol
  • Loading branch information
barry-jin committed Apr 17, 2021
commit c6a40a2fc2326878039f3cc7edc20be5a134e4f6
11 changes: 3 additions & 8 deletions cpp-package/example/inference/imagenet_inference.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,18 +210,13 @@ Predictor::Predictor(const std::string& model_json_file,
Shape label_shape(input_shape_[0]);
args_map_["softmax_label"] = NDArray(label_shape, global_ctx_, false);
std::vector<NDArray> arg_arrays;
std::vector<NDArray> grad_arrays;
std::vector<OpReqType> grad_reqs;
std::vector<NDArray> aux_arrays;

bool require_grad;
// infer and create ndarrays according to the given input ndarrays.
net_.InferExecutorArrays(global_ctx_, &arg_arrays, &grad_arrays, &grad_reqs,
&aux_arrays, args_map_, std::map<std::string, NDArray>(),
net_.InferExecutorArrays(global_ctx_, &arg_arrays, require_grad, args_map_, std::map<std::string, NDArray>(),
std::map<std::string, OpReqType>(), aux_map_);
for (auto& i : grad_reqs) i = OpReqType::kNullOp;

// Create an executor after binding the model to input parameters.
executor_ = new Executor(net_, global_ctx_, arg_arrays, grad_arrays, grad_reqs, aux_arrays);
executor_ = new Executor(net_, global_ctx_, arg_arrays, false);
}

/*
Expand Down
8 changes: 4 additions & 4 deletions cpp-package/example/inference/sentiment_analysis_rnn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,18 +146,18 @@ Predictor::Predictor(const std::string& model_json,
highest_bucket_key = *(std::max_element(bucket_keys.begin(), bucket_keys.end()));
args_map["data0"] = NDArray(Shape(highest_bucket_key, 1), global_ctx, false);
args_map["data1"] = NDArray(Shape(1), global_ctx, false);
bool require_grad;

net.InferExecutorArrays(global_ctx, &arg_arrays, &grad_arrays, &grad_reqs,
&aux_arrays, args_map, std::map<std::string, NDArray>(),
net.InferExecutorArrays(global_ctx, &arg_arrays, require_grad, args_map, std::map<std::string, NDArray>(),
std::map<std::string, OpReqType>(), aux_map);
Executor *master_executor = net.Bind(global_ctx, arg_arrays, grad_arrays, grad_reqs, aux_arrays,
Executor *master_executor = net.Bind(global_ctx, arg_arrays, require_grad,
std::map<std::string, Context>(), nullptr);
executor_buckets[highest_bucket_key] = master_executor;

for (int bucket : bucket_keys) {
if (executor_buckets.find(bucket) == executor_buckets.end()) {
arg_arrays[0] = NDArray(Shape(bucket, 1), global_ctx, false);
Executor *executor = net.Bind(global_ctx, arg_arrays, grad_arrays, grad_reqs, aux_arrays,
Executor *executor = net.Bind(global_ctx, arg_arrays, require_grad,
std::map<std::string, Context>(), master_executor);
executor_buckets[bucket] = executor;
}
Expand Down
3 changes: 1 addition & 2 deletions cpp-package/example/mlp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,7 @@ void MLP(int max_epoch) {
std::vector<NDArray> aux_states;

std::cout << "make the Executor" << std::endl;
Executor* exe = new Executor(sym_out, ctx_dev, in_args, arg_grad_store,
grad_req_type, aux_states);
Executor* exe = new Executor(sym_out, ctx_dev, in_args, true);

std::cout << "Training" << std::endl;
mx_float learning_rate = 0.0001;
Expand Down
5 changes: 1 addition & 4 deletions cpp-package/include/mxnet-cpp/executor.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,7 @@ class Executor {
public:
Executor(const Symbol &symbol, Context context,
const std::vector<NDArray> &arg_arrays,
const std::vector<NDArray> &grad_arrays,
const std::vector<OpReqType> &grad_reqs,
const std::vector<NDArray> &aux_arrays,
bool require_grad,
const std::map<std::string, Context> &group_to_ctx =
std::map<std::string, Context>(),
Executor *shared_exec = nullptr);
Expand All @@ -75,7 +73,6 @@ class Executor {
});
int out_size = 0;
NDArrayHandle *out_array = nullptr;
bool out_initialized = false;
CHECK_EQ(MXInvokeCachedOp(handle_, arg_handles.size(), arg_handles.data(),
device_type, device_id, &out_size, &out_array, nullptr),
0);
Expand Down
52 changes: 2 additions & 50 deletions cpp-package/include/mxnet-cpp/executor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,66 +37,18 @@ namespace mxnet {
namespace cpp {
inline Executor::Executor(const Symbol &symbol, Context context,
const std::vector<NDArray> &arg_arrays,
const std::vector<NDArray> &grad_arrays,
const std::vector<OpReqType> &grad_reqs,
const std::vector<NDArray> &aux_arrays,
bool require_grad,
const std::map<std::string, Context> &group_to_ctx,
Executor *shared_exec) {
this->arg_arrays = arg_arrays;
this->grad_arrays = grad_arrays;
this->aux_arrays = aux_arrays;
this->symbol_ = symbol;
this->require_grad = require_grad;
this->device_type = context.GetDeviceType();
this->device_id = context.GetDeviceId();

std::vector<NDArrayHandle> arg_handles;
std::vector<NDArrayHandle> grad_handles;
std::vector<NDArrayHandle> aux_handles;

for (const auto &array : arg_arrays) {
arg_handles.push_back(array.GetHandle());
}
for (const auto &array : grad_arrays) {
grad_handles.push_back(array.GetHandle());
}

this->require_grad = false;
std::vector<mx_uint> grad_reqs_uint;
for (auto s : grad_reqs) {
if (s != OpReqType::kNullOp) {
this->require_grad = true;
}
grad_reqs_uint.push_back(s);
}
CHECK_EQ(MXAutogradMarkVariables(arg_handles.size(), arg_handles.data(),
grad_reqs_uint.data(), grad_handles.data()),0);
// std::vector<const char *> map_keys;
// std::vector<int> dev_types, dev_ids;
// for (const auto &s : group_to_ctx) {
// map_keys.push_back(s.first.c_str());
// dev_types.push_back(s.second.GetDeviceType());
// dev_ids.push_back(s.second.GetDeviceId());
// }

CHECK_EQ(MXCreateCachedOp(symbol.GetHandle(), 0, nullptr, nullptr, &handle_, false), 0);
}

inline mx_uint GradType2Int(OpReqType t) {
if (t == OpReqType::kNullOp) {
return 0;
} else if (t == OpReqType::kWriteTo) {
return 1;
} else if (t == OpReqType::kWriteInplace) {
return 2;
} else if (t == OpReqType::kAddTo) {
return 3;
} else {
LOG(FATAL) << "unknown grad type " << t;
}
LOG(FATAL) << "should not reach here ";
return 0;
}

} // namespace cpp
} // namespace mxnet

Expand Down
16 changes: 3 additions & 13 deletions cpp-package/include/mxnet-cpp/symbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,6 @@ class Symbol {
* some known arrays.
* \param context the context of all the infered arrays
* \param arg_arrays infered input arguments arrays.
* \param arad_arrays infered arrays to store the gradient output of the input
* arguments.
* \param aux_arrays infered arrays that is used as internal state in op.
* \param args_map map of some given arguments arrays.
* \param args_grad_store map of some gradient given store arrays.
* \param args_req_type map of some given type of gradient saving. Can only be
Expand All @@ -215,8 +212,7 @@ class Symbol {
*/
void InferExecutorArrays(
const Context &context, std::vector<NDArray> *arg_arrays,
std::vector<NDArray> *grad_arrays, std::vector<OpReqType> *grad_reqs,
std::vector<NDArray> *aux_arrays,
bool &require_grad,
const std::map<std::string, NDArray> &args_map,
const std::map<std::string, NDArray> &arg_grad_store =
std::map<std::string, NDArray>(),
Expand Down Expand Up @@ -267,21 +263,15 @@ class Symbol {
*
* \param context the context of binding.
* \param arg_arrays the NDArray that stores the input arguments to the symbol.
* \param grad_arrays NDArray that is used to store the gradient output of the
*input arguments.
* \param grad_reqs requirment type of gradient saving. Can only be in
*{kNullOp, kAddTo, kWriteTo}.
* \param aux_arrays NDArray that is used as internal state in op
* \param require_grad if require to do backward propogation.
* \param group_to_ctx dict of string to mx.Context
* \param shared_exec Executor to share memory with. This is intended for
*runtime reshaping, variable length sequencesn etc. The returned executor
*shares state with shared_exec, and should not be used in parallel with it.
* \return a new executor, which need to be free manually.
*/
Executor *Bind(const Context &context, const std::vector<NDArray> &arg_arrays,
const std::vector<NDArray> &grad_arrays,
const std::vector<OpReqType> &grad_reqs,
const std::vector<NDArray> &aux_arrays,
bool require_grad,
const std::map<std::string, Context> &group_to_ctx =
std::map<std::string, Context>(),
Executor *shared_exec = nullptr);
Expand Down
115 changes: 71 additions & 44 deletions cpp-package/include/mxnet-cpp/symbol.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,16 +287,28 @@ inline void Symbol::InferShape(
}
}

inline std::map<std::string, std::vector<mx_uint> > GetDict(const std::vector<std::string> &names,
const std::vector<std::vector<mx_uint> > &shapes) {
std::map<std::string, std::vector<mx_uint> > ret;
CHECK_EQ(names.size(), shapes.size())
<< "names size not equal to shapes size";
for (size_t i = 0; i < names.size(); ++i) {
ret[names[i]] = shapes[i];
}
return ret;
}

inline void Symbol::InferExecutorArrays(
const Context &context, std::vector<NDArray> *arg_arrays,
std::vector<NDArray> *grad_arrays, std::vector<OpReqType> *grad_reqs,
std::vector<NDArray> *aux_arrays,
bool &require_grad,
const std::map<std::string, NDArray> &args_map,
const std::map<std::string, NDArray> &arg_grad_store,
const std::map<std::string, OpReqType> &grad_req_type,
const std::map<std::string, NDArray> &aux_map) const {

const auto arg_name_list = ListArguments();
const auto input_name_list = ListInputs();
const auto aux_name_list = ListAuxiliaryStates();
std::vector<std::vector<mx_uint> > in_shapes, aux_shapes, out_shapes;
std::map<std::string, std::vector<mx_uint> > arg_shapes;

Expand All @@ -308,44 +320,66 @@ inline void Symbol::InferExecutorArrays(
}

InferShape(arg_shapes, &in_shapes, &aux_shapes, &out_shapes);
std::map<std::string, std::vector<mx_uint> > inshape_map = GetDict(arg_name_list, in_shapes);
std::map<std::string, std::vector<mx_uint> > auxshape_map = GetDict(aux_name_list, aux_shapes);

for (size_t i = 0; i < in_shapes.size(); ++i) {
const auto &shape = in_shapes[i];
const auto &arg_name = arg_name_list[i];
auto iter_arg = args_map.find(arg_name);
for (size_t i = 0; i < input_name_list.size(); ++i) {
const auto &input_name = input_name_list[i];
std::vector<mx_uint> shape;
auto iter_arg = args_map.find(input_name);
if (iter_arg != args_map.end()) {
arg_arrays->push_back(iter_arg->second);
arg_arrays->push_back((iter_arg->second).Copy(context));
} else {
arg_arrays->push_back(NDArray(shape, context, false));
NDArray::SampleGaussian(0, 1, &arg_arrays->back());
}
auto iter_grad = arg_grad_store.find(arg_name);
if (iter_grad != arg_grad_store.end()) {
grad_arrays->push_back(iter_grad->second);
} else {
grad_arrays->push_back(NDArray(shape, context, false));
auto iter_inshape = inshape_map.find(input_name);
if (iter_inshape != inshape_map.end()) {
shape = iter_inshape->second;
arg_arrays->push_back(NDArray(shape, context, false));
NDArray::SampleGaussian(0, 1, &arg_arrays->back());
} else {
auto iter_aux = arg_grad_store.find(input_name);
if (iter_aux != arg_grad_store.end()) {
arg_arrays->push_back((iter_aux->second).Copy(context));
} else {
auto iter_auxshape = auxshape_map.find(input_name);
CHECK(iter_auxshape != auxshape_map.end())
<< "Can not find name in args array and aux array";
shape = iter_auxshape->second;
arg_arrays->push_back(NDArray(shape, context, false));
NDArray::SampleGaussian(0, 1, &arg_arrays->back());
}
}
}
auto iter_req = grad_req_type.find(arg_name);
auto iter_req = grad_req_type.find(input_name);
auto req = OpReqType::kNullOp;
if (iter_req != grad_req_type.end()) {
grad_reqs->push_back(iter_req->second);
} else if (arg_name.rfind("data") != std::string::npos
|| arg_name.rfind("label") != std::string::npos) {
grad_reqs->push_back(OpReqType::kNullOp);
req = iter_req->second;
} else if (input_name.rfind("data") != std::string::npos
|| input_name.rfind("label") != std::string::npos) {
req = OpReqType::kNullOp;
} else {
grad_reqs->push_back(OpReqType::kWriteTo);
req = OpReqType::kWriteTo;
}
}

const auto aux_name_list = ListAuxiliaryStates();
for (size_t i = 0; i < aux_shapes.size(); ++i) {
const auto &shape = aux_shapes[i];
const auto &aux_name = aux_name_list[i];
auto iter_aux = aux_map.find(aux_name);
if (iter_aux != aux_map.end()) {
aux_arrays->push_back(iter_aux->second);
if (req != OpReqType::kNullOp) {
require_grad = true;
std::vector<NDArrayHandle> arg_handles;
std::vector<NDArrayHandle> grad_handles;
std::vector<mx_uint> grad_reqs_uint;
auto iter_grad = arg_grad_store.find(input_name);
if (iter_grad != arg_grad_store.end()) {
arg_handles.push_back(&arg_arrays->back());
grad_reqs_uint.push_back(req);
grad_handles.push_back(((iter_grad->second).Copy(context)).GetHandle());
CHECK_EQ(MXAutogradMarkVariables(1, arg_handles.data(),
grad_reqs_uint.data(),
grad_handles.data()),0);
} else {
aux_arrays->push_back(NDArray(shape, context, false));
NDArray::SampleGaussian(0, 1, &aux_arrays->back());
arg_handles.push_back(&arg_arrays->back());
grad_reqs_uint.push_back(req);
grad_handles.push_back(NDArray(shape, context, false).GetHandle());
CHECK_EQ(MXAutogradMarkVariables(1, arg_handles.data(),
grad_reqs_uint.data(),
grad_handles.data()),0);
}
}
}
}
Expand Down Expand Up @@ -385,27 +419,20 @@ inline Executor *Symbol::SimpleBind(
const std::map<std::string, OpReqType> &grad_req_type,
const std::map<std::string, NDArray> &aux_map) {
std::vector<NDArray> arg_arrays;
std::vector<NDArray> grad_arrays;
std::vector<OpReqType> grad_reqs;
std::vector<NDArray> aux_arrays;
bool require_grad = false;

InferExecutorArrays(context, &arg_arrays, &grad_arrays, &grad_reqs,
&aux_arrays, args_map, arg_grad_store, grad_req_type,
InferExecutorArrays(context, &arg_arrays, require_grad, args_map, arg_grad_store, grad_req_type,
aux_map);

return new Executor(*this, context, arg_arrays, grad_arrays, grad_reqs,
aux_arrays);
return new Executor(*this, context, arg_arrays, require_grad);
}

inline Executor *Symbol::Bind(const Context &context,
const std::vector<NDArray> &arg_arrays,
const std::vector<NDArray> &grad_arrays,
const std::vector<OpReqType> &grad_reqs,
const std::vector<NDArray> &aux_arrays,
bool require_grad,
const std::map<std::string, Context> &group_to_ctx,
Executor *shared_exec) {
return new Executor(*this, context, arg_arrays, grad_arrays, grad_reqs,
aux_arrays, group_to_ctx, shared_exec);
return new Executor(*this, context, arg_arrays, require_grad, group_to_ctx, shared_exec);
}
inline Symbol operator+(mx_float lhs, const Symbol &rhs) { return rhs + lhs; }
inline Symbol operator-(mx_float lhs, const Symbol &rhs) {
Expand Down