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

Commit 2721518

Browse files
authored
[v1.8.x] Backport extension bug fixes to v1.8.x (#19469) (#19504)
* Extension bug fixes (#19469) * initial commit * syntax fix * spacing * added test case * fixed indentation * pinned h5py to <3 * fixed h5py
1 parent 2e33e96 commit 2721518

7 files changed

Lines changed: 123 additions & 86 deletions

File tree

ci/docker/install/centos7_python.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,4 @@ yum -y install python36u
3030
curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py"
3131
python3.6 get-pip.py
3232
# Restrict numpy version to < 1.19.0 due to https://github.com/apache/incubator-mxnet/issues/18600
33-
pip3 install nose pylint 'numpy>1.16.0,<1.19.0' nose-timer requests h5py scipy==1.2.3
33+
pip3 install nose pylint 'numpy>1.16.0,<1.19.0' nose-timer requests 'h5py<3' scipy==1.2.3

ci/docker/install/requirements

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ boto3==1.9.229
2222
cpplint==1.3.0
2323
Cython==0.29.7
2424
decorator==4.4.0
25-
h5py==2.8.0rc1
25+
h5py<3
2626
mock==2.0.0
2727
nose==1.3.7
2828
nose-timer==0.7.3

ci/docker/install/ubuntu_publish.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ apt-get install -y python python-pip python3 python3-pip
8181
python3 -m pip install --upgrade 'pip<19'
8282

8383
# Restrict numpy version to <1.18 due to use of Python 3.4 on Ubuntu 14.04
84-
python3 -m pip install --upgrade --ignore-installed nose cpplint==1.3.0 pylint==2.3.1 'numpy>1.16.0,<1.18' nose-timer 'requests<2.19.0,>=2.18.4' h5py==2.8.0rc1 scipy==1.0.1 boto3
84+
python3 -m pip install --upgrade --ignore-installed nose cpplint==1.3.0 pylint==2.3.1 'numpy>1.16.0,<1.18' nose-timer 'requests<2.19.0,>=2.18.4' 'h5py<3' scipy==1.0.1 boto3
8585

8686
# CMake 3.13.2+ is required
8787
mkdir /opt/cmake && cd /opt/cmake

python/mxnet/gluon/block.py

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -957,14 +957,35 @@ def _build_cache(self, *args):
957957

958958
arg_dict, aux_dict = dict(), dict()
959959
if self._backend:
960-
ctx = args[0].context
960+
# set context for inputs
961+
_, _, ctx_set, _ = _gather_type_ctx_info(list(args))
962+
ctx = ctx_set.pop() if len(ctx_set) > 0 else None
961963
# get list of params in the order of out.list_arguments
962-
arg_dict.update({name:args[data_names[name]] if name in data_names.keys() else params[name].data()
963-
for name in out.list_arguments()})
964-
aux_dict.update({name:args[data_names[name]] if name in data_names.keys() else params[name].data()
965-
for name in out.list_auxiliary_states()})
966-
# Partition the graph.
967-
out = out.optimize_for(self._backend, arg_dict, aux_dict, ctx, **self._backend_opts)
964+
input_shapes = dict()
965+
for name in out.list_arguments():
966+
if name in data_names.keys() and data_names[name] < len(args):
967+
if isinstance(args[data_names[name]], NDArray):
968+
arg_dict[name] = args[data_names[name]]
969+
elif (isinstance(args[data_names[name]], symbol.Symbol) and
970+
'__shape__' in args[data_names[name]].list_attr()):
971+
shape_str = args[data_names[name]].list_attr()['__shape__']
972+
input_shapes[name] = tuple(map(int, shape_str.strip('()').split(',')))
973+
elif name in params:
974+
arg_dict[name] = params[name].data()
975+
976+
for name in out.list_auxiliary_states():
977+
if name in data_names.keys() and data_names[name] < len(args):
978+
if isinstance(args[data_names[name]], NDArray):
979+
aux_dict[name] = args[data_names[name]]
980+
elif (isinstance(args[data_names[name]], symbol.Symbol) and
981+
'__shape__' in args[data_names[name]].list_attr()):
982+
shape_str = args[data_names[name]].list_attr()['__shape__']
983+
input_shapes[name] = tuple(map(int, shape_str.strip('()').split(',')))
984+
elif name in params:
985+
aux_dict[name] = params[name].data()
986+
987+
# Partition the graph
988+
out = out.optimize_for(self._backend, arg_dict, aux_dict, ctx, input_shapes, **self._backend_opts)
968989

969990
#update cached graph with partitioned graph
970991
self._cached_graph = data, out
@@ -1000,7 +1021,7 @@ def _build_cache(self, *args):
10001021
'Please check the backend.')
10011022

10021023
param = Parameter(name, dtype=param_data.dtype)
1003-
param._load_init(param_data, args[0].context)
1024+
param._load_init(param_data, param_data.context)
10041025
pair = (False, param)
10051026

10061027
self._cached_op_args.append(pair)
@@ -1103,14 +1124,11 @@ def optimize_for(self, x, *args, backend=None, backend_opts=None, clear=True, **
11031124

11041125
# do part of forward API call
11051126
has_symbol, has_ndarray, ctx_set, _ = _gather_type_ctx_info([x] + list(args))
1106-
if has_symbol:
1107-
raise ValueError('Inputs must be NDArrays for the optimize_for API'
1108-
' Please check the type of the args.\n')
11091127
if not has_symbol and not has_ndarray:
1110-
raise ValueError('In HybridBlock, there must be one NDArray as input.'
1128+
raise ValueError('In HybridBlock, there must be one NDArray or one Symbol in the input.'
11111129
' Please check the type of the args.\n')
11121130
if len(ctx_set) > 1:
1113-
raise ValueError('Find multiple contexts in the input, '
1131+
raise ValueError('Found multiple contexts in the input, '
11141132
'After hybridized, the HybridBlock only supports one input '
11151133
'context. You can print the ele.ctx in the '
11161134
'input arguments to inspect their contexts. '

src/c_api/c_api.cc

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,50 +1376,54 @@ void registerPasses(void *lib, int verbose, mxnet::ext::msgSize_t msgSize,
13761376

13771377
// convert input args
13781378
for (size_t i=0; i < in_arg_names.size(); i++) {
1379-
arg_names.push_back(in_arg_names[i].c_str());
1380-
const NDArray &in_arg = *(in_args_ptr[i]);
1379+
if (in_args_ptr[i] != nullptr) {
1380+
arg_names.push_back(in_arg_names[i].c_str());
1381+
const NDArray &in_arg = *(in_args_ptr[i]);
13811382

13821383
#if MXNET_USE_MKLDNN == 1
1383-
// reorder data if in MKLDNN format
1384-
if (in_arg.IsMKLDNNData()) {
1385-
in_arg.Reorder2DefaultAsync();
1386-
in_arg.WaitToRead();
1387-
}
1384+
// reorder data if in MKLDNN format
1385+
if (in_arg.IsMKLDNNData()) {
1386+
in_arg.Reorder2DefaultAsync();
1387+
in_arg.WaitToRead();
1388+
}
13881389
#endif
13891390

1390-
// pull out parts of NDArray to send to backend
1391-
arg_data.push_back(in_arg.data().dptr_);
1392-
arg_shapes.push_back(in_arg.shape().data());
1393-
arg_dims.push_back(in_arg.shape().ndim());
1394-
arg_types.push_back(in_arg.dtype());
1395-
arg_verIDs.push_back(in_arg.version());
1396-
const char* arg_ctx_str = in_arg.ctx().dev_mask() == Context::kCPU ? "cpu" : "gpu";
1397-
arg_dev_type.push_back(arg_ctx_str);
1398-
arg_dev_id.push_back(in_arg.ctx().real_dev_id());
1391+
// pull out parts of NDArray to send to backend
1392+
arg_data.push_back(in_arg.data().dptr_);
1393+
arg_shapes.push_back(in_arg.shape().data());
1394+
arg_dims.push_back(in_arg.shape().ndim());
1395+
arg_types.push_back(in_arg.dtype());
1396+
arg_verIDs.push_back(in_arg.version());
1397+
const char* arg_ctx_str = in_arg.ctx().dev_mask() == Context::kCPU ? "cpu" : "gpu";
1398+
arg_dev_type.push_back(arg_ctx_str);
1399+
arg_dev_id.push_back(in_arg.ctx().real_dev_id());
1400+
}
13991401
}
14001402

14011403
// convert input aux
14021404
for (size_t i=0; i < in_aux_names.size(); i++) {
1403-
aux_names.push_back(in_aux_names[i].c_str());
1404-
const auto &in_aux = *(in_aux_ptr[i]);
1405+
if (in_aux_ptr[i] != nullptr) {
1406+
aux_names.push_back(in_aux_names[i].c_str());
1407+
const auto &in_aux = *(in_aux_ptr[i]);
14051408

14061409
#if MXNET_USE_MKLDNN == 1
1407-
// reorder data if in MKLDNN format
1408-
if (in_aux.IsMKLDNNData()) {
1409-
in_aux.Reorder2DefaultAsync();
1410-
in_aux.WaitToRead();
1411-
}
1410+
// reorder data if in MKLDNN format
1411+
if (in_aux.IsMKLDNNData()) {
1412+
in_aux.Reorder2DefaultAsync();
1413+
in_aux.WaitToRead();
1414+
}
14121415
#endif
14131416

1414-
// pull out parts of NDArray to send to backend
1415-
aux_data.push_back(in_aux.data().dptr_);
1416-
aux_shapes.push_back(in_aux.shape().data());
1417-
aux_dims.push_back(in_aux.shape().ndim());
1418-
aux_types.push_back(in_aux.dtype());
1419-
aux_verIDs.push_back(in_aux.version());
1420-
const char* aux_ctx_str = in_aux.ctx().dev_mask() == Context::kCPU ? "cpu" : "gpu";
1421-
aux_dev_type.push_back(aux_ctx_str);
1422-
aux_dev_id.push_back(in_aux.ctx().real_dev_id());
1417+
// pull out parts of NDArray to send to backend
1418+
aux_data.push_back(in_aux.data().dptr_);
1419+
aux_shapes.push_back(in_aux.shape().data());
1420+
aux_dims.push_back(in_aux.shape().ndim());
1421+
aux_types.push_back(in_aux.dtype());
1422+
aux_verIDs.push_back(in_aux.version());
1423+
const char* aux_ctx_str = in_aux.ctx().dev_mask() == Context::kCPU ? "cpu" : "gpu";
1424+
aux_dev_type.push_back(aux_ctx_str);
1425+
aux_dev_id.push_back(in_aux.ctx().real_dev_id());
1426+
}
14231427
}
14241428

14251429
// convert graph to string

src/operator/subgraph/partitioner/custom_subgraph_property.h

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -208,26 +208,28 @@ class CustomSubgraphProperty: public SubgraphProperty {
208208
arg_dev_type.clear();
209209
arg_dev_id.clear();
210210
for (size_t i=0; i < in_arg_names.size(); i++) {
211-
arg_names.push_back(in_arg_names[i].c_str());
212-
const NDArray &in_arg = *(in_args_ptr[i]);
211+
if (in_args_ptr[i] != nullptr) {
212+
arg_names.push_back(in_arg_names[i].c_str());
213+
const NDArray &in_arg = *(in_args_ptr[i]);
213214

214215
#if MXNET_USE_MKLDNN == 1
215-
// reorder data if in MKLDNN format
216-
if (in_arg.IsMKLDNNData()) {
217-
in_arg.Reorder2DefaultAsync();
218-
in_arg.WaitToRead();
219-
}
216+
// reorder data if in MKLDNN format
217+
if (in_arg.IsMKLDNNData()) {
218+
in_arg.Reorder2DefaultAsync();
219+
in_arg.WaitToRead();
220+
}
220221
#endif
221222

222-
// pull out parts of NDArray to send to backend
223-
arg_data.push_back(in_arg.data().dptr_);
224-
arg_shapes.push_back(in_arg.shape().data());
225-
arg_dims.push_back(in_arg.shape().ndim());
226-
arg_types.push_back(in_arg.dtype());
227-
arg_verIDs.push_back(in_arg.version());
228-
const char* arg_ctx_str = in_arg.ctx().dev_mask() == Context::kCPU ? "cpu" : "gpu";
229-
arg_dev_type.push_back(arg_ctx_str);
230-
arg_dev_id.push_back(in_arg.ctx().real_dev_id());
223+
// pull out parts of NDArray to send to backend
224+
arg_data.push_back(in_arg.data().dptr_);
225+
arg_shapes.push_back(in_arg.shape().data());
226+
arg_dims.push_back(in_arg.shape().ndim());
227+
arg_types.push_back(in_arg.dtype());
228+
arg_verIDs.push_back(in_arg.version());
229+
const char* arg_ctx_str = in_arg.ctx().dev_mask() == Context::kCPU ? "cpu" : "gpu";
230+
arg_dev_type.push_back(arg_ctx_str);
231+
arg_dev_id.push_back(in_arg.ctx().real_dev_id());
232+
}
231233
}
232234

233235
// convert input aux
@@ -240,26 +242,28 @@ class CustomSubgraphProperty: public SubgraphProperty {
240242
aux_dev_type.clear();
241243
aux_dev_id.clear();
242244
for (size_t i=0; i < in_aux_names.size(); i++) {
243-
aux_names.push_back(in_aux_names[i].c_str());
244-
const auto &in_aux = *(in_aux_ptr[i]);
245+
if (in_aux_ptr[i] != nullptr) {
246+
aux_names.push_back(in_aux_names[i].c_str());
247+
const auto &in_aux = *(in_aux_ptr[i]);
245248

246249
#if MXNET_USE_MKLDNN == 1
247-
// reorder data if in MKLDNN format
248-
if (in_aux.IsMKLDNNData()) {
249-
in_aux.Reorder2DefaultAsync();
250-
in_aux.WaitToRead();
251-
}
250+
// reorder data if in MKLDNN format
251+
if (in_aux.IsMKLDNNData()) {
252+
in_aux.Reorder2DefaultAsync();
253+
in_aux.WaitToRead();
254+
}
252255
#endif
253256

254-
// pull out parts of NDArray to send to backend
255-
aux_data.push_back(in_aux.data().dptr_);
256-
aux_shapes.push_back(in_aux.shape().data());
257-
aux_dims.push_back(in_aux.shape().ndim());
258-
aux_types.push_back(in_aux.dtype());
259-
aux_verIDs.push_back(in_aux.version());
260-
const char* aux_ctx_str = in_aux.ctx().dev_mask() == Context::kCPU ? "cpu" : "gpu";
261-
aux_dev_type.push_back(aux_ctx_str);
262-
aux_dev_id.push_back(in_aux.ctx().real_dev_id());
257+
// pull out parts of NDArray to send to backend
258+
aux_data.push_back(in_aux.data().dptr_);
259+
aux_shapes.push_back(in_aux.shape().data());
260+
aux_dims.push_back(in_aux.shape().ndim());
261+
aux_types.push_back(in_aux.dtype());
262+
aux_verIDs.push_back(in_aux.version());
263+
const char* aux_ctx_str = in_aux.ctx().dev_mask() == Context::kCPU ? "cpu" : "gpu";
264+
aux_dev_type.push_back(aux_ctx_str);
265+
aux_dev_id.push_back(in_aux.ctx().real_dev_id());
266+
}
263267
}
264268

265269
// remove all graph attrs, some cannot be saved to json
@@ -285,13 +289,17 @@ class CustomSubgraphProperty: public SubgraphProperty {
285289
for (unsigned oid = 0; oid < node->num_outputs(); oid++) {
286290
const uint32_t out_entry_id = indexed_graph.entry_id(nid, oid);
287291
mxnet::TShape& shape = shapes[out_entry_id];
288-
ss << shape;
292+
if (shape.ndim() == -1)
293+
ss << "[None]";
294+
else
295+
ss << shape;
289296
if (oid < node->num_outputs()-1) ss << ",";
290297
}
291298
ss << "]";
292299
node->attrs.dict[MX_STR_SHAPE] = ss.str();
293300
}
294301
}
302+
295303
// set dtype attrs for each node in the graph
296304
if (g.HasAttr("dtype")) {
297305
std::vector<int> dtypes = g.GetAttr<std::vector<int> >("dtype");

tests/python/unittest/test_extensions.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -166,16 +166,23 @@ def test_subgraph():
166166
# check that result matches one executed by MXNet
167167
assert_almost_equal(out[0].asnumpy(), out4[0].asnumpy(), rtol=1e-3, atol=1e-3)
168168

169-
# Gluon Hybridize partitioning with shapes/types
169+
# Gluon Hybridize partitioning with sym.var
170170
sym_block2 = nn.SymbolBlock(sym, [a,b])
171171
sym_block2.initialize()
172+
a_var = mx.sym.var('a',shape=(3,2))
173+
b_var = mx.sym.var('b',shape=(3,2))
174+
sym_block2.optimize_for(a_var, b_var, backend='myProp')
175+
176+
# Gluon Hybridize partitioning with shapes/types
177+
sym_block3 = nn.SymbolBlock(sym, [a,b])
178+
sym_block3.initialize()
172179
a_data = mx.nd.ones((3,2))
173180
b_data = mx.nd.ones((3,2))
174-
sym_block2.optimize_for(a_data, b_data, backend='myProp')
175-
sym_block2.export('optimized')
176-
sym_block3 = nn.SymbolBlock.imports('optimized-symbol.json',['a','b'],
181+
sym_block3.optimize_for(a_data, b_data, backend='myProp')
182+
sym_block3.export('optimized')
183+
sym_block4 = nn.SymbolBlock.imports('optimized-symbol.json',['a','b'],
177184
'optimized-0000.params')
178185

179-
out5 = sym_block3(a_data, b_data)
186+
out5 = sym_block4(a_data, b_data)
180187
# check that result matches one executed by MXNet
181188
assert_almost_equal(out[0].asnumpy(), out5[0].asnumpy(), rtol=1e-3, atol=1e-3)

0 commit comments

Comments
 (0)