深度学习 AMI
开发人员指南
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

将 Elastic Inference 与 MXNet 结合使用

(EI) 仅适用于已通过 Elastic Inference Accelerator 启动的实例。

查看选择 DLAMI 的实例类型以选择所需的实例类型,并查看 Elastic Inference 先决条件以了解与 Elastic Inference 相关的说明。有关如何使用 Elastic Inference Accelerator 启动 DLAMI 的详细说明,请参阅 文档。

要使用现有 MXNet 推理脚本,请在代码中进行一项更改。无论您在哪个位置设置上下文以绑定模型,如 mx.cpu()mx.gpu(),都请更新此项以改用 mx.eia()。下面是具有此项修改的示例(与教程将 Elastic Inference 与 MXNet 结合使用相比,其中的示例在本地 CPU 上运行)。

激活 MXNet EI 环境

  1. 使用 Conda 控制台登录到您的 Deep Learning AMI 以开始以下教程。根据您的 Python 版本,请执行下列操作之一:

    • 适用于 Python 3 的选项 - 激活 Python 3 MXNet EI 环境。

      $ source activate amazonei_mxnet_p36
    • 适用于 Python 2 的选项 - 激活 Python 2 MXNet EI 环境。

      $ source activate amazonei_mxnet_p27
  2. 本指南的剩余部分假定您使用的是 amazonei_mxnet_p36 环境。

注意

如果您正在各种 MXNet 或 TensorFlow Elastic Inference 环境之间切换,则必须停止,然后启动您的实例以重新挂载 Elastic Inference Accelerator。重启是不够的,因为该过程需要完全关闭。

将 EI 与 MXNet 结合使用

启用了 EI 的 MXNet 版本可让您无缝地将 EI 与对 MXNet 代码进行的几项更改结合使用。您可以将 EI 与以下任一 MXNet API 结合使用:

  • MXNet Python Symbol API

  • MXNet Python Module API

将 EI 与 MXNet Symbol API 结合使用

mx.eia() 作为调用中的上下文传递给 simple_bind()bind() 方法。有关 MXNet Symbol API 的信息,请参阅 https://mxnet.incubator.apache.org/api/python/symbol/symbol.html

EI 环境未使用 CUDA 进行编译,因此 GPU 上下文调用失败。在您的代码中检查此项以确保您不会意外使用 GPU 上下文。例如,在使用 EI 时,NDArray 计算应由 mx.cpu() 上下文处理。您仅将 mx.eia() 上下文与绑定调用结合使用。以下示例使用 mx.eia() 上下文调用 simple_bind() 方法。

import mxnet as mx data = mx.sym.var('data', shape=(1,)) sym = mx.sym.exp(data) # Pass mx.eia() as context during simple bind operation executor = sym.simple_bind(ctx=mx.eia(), grad_req='null') for i in range(10): # Forward call is performed on remote accelerator executor.forward() print('Inference %d, output = %s' % (i, executor.outputs[0]))

以下示例调用 bind() 方法。

import mxnet as mx a = mx.sym.Variable('a') b = mx.sym.Variable('b') c = 2 * a + b # Even for execution of inference workloads on eia, # context for input ndarrays to be mx.cpu() a_data = mx.nd.array([1,2], ctx=mx.cpu()) b_data = mx.nd.array([2,3], ctx=mx.cpu()) # Then in the bind call, use the mx.eia() context e = c.bind(mx.eia(), {'a': a_data, 'b': b_data}) # Forward call is performed on remote accelerator e.forward()

将 EI 与 Symbol API 和 ResNet-50 模型结合使用

以下示例通过 Symbol API 在预训练的实际模型 (Resnet-50) 上调用 bind() 方法。

  1. 使用您的首选文本编辑器创建具有以下内容的名为 mxnet_resnet50.py 的脚本。此脚本下载 ResNet-50 模型文件(resnet-50-0000.params 和 resnet-50-symbol.json)。该脚本还下载标签列表 (synset.txt)。下载一张猫的图片,从预训练模型中获得预测结果,然后在标签列表中的结果中查找,并返回一个预测结果。

    import mxnet as mx import numpy as np path='http://data.mxnet.io/models/imagenet/' [mx.test_utils.download(path+'resnet/50-layers/resnet-50-0000.params'), mx.test_utils.download(path+'resnet/50-layers/resnet-50-symbol.json'), mx.test_utils.download(path+'synset.txt')] ctx = mx.eia() with open('synset.txt', 'r') as f: labels = [l.rstrip() for l in f] sym, args, aux = mx.model.load_checkpoint('resnet-50', 0) fname = mx.test_utils.download('https://github.com/dmlc/web-data/blob/master/mxnet/doc/tutorials/python/predict_image/cat.jpg?raw=true') img = mx.image.imread(fname) # convert into format (batch, RGB, width, height) img = mx.image.imresize(img, 224, 224) # resize img = img.transpose((2, 0, 1)) # Channel first img = img.expand_dims(axis=0) # batchify img = img.astype(dtype='float32') args['data'] = img softmax = mx.nd.random_normal(shape=(1,)) args['softmax_label'] = softmax exe = sym.bind(ctx=ctx, args=args, aux_states=aux, grad_req='null') exe.forward() prob = exe.outputs[0].asnumpy() # print the top-5 prob = np.squeeze(prob) a = np.argsort(prob)[::-1] for i in a[0:5]: print('probability=%f, class=%s' %(prob[i], labels[i]))
  2. 然后运行该脚本,您应看到类似于以下输出的某些内容。MXNet 将优化 Elastic Inference 的模型图形,在 Elastic Inference Accelerator 上加载该图形,然后对它运行推理:

    (amazonei_mxnet_p36) ubuntu@ip-172-31-42-83:~$ python mxnet_resnet50.py [23:12:03] src/nnvm/legacy_json_util.cc:209: Loading symbol saved by previous version v0.8.0. Attempting to upgrade... [23:12:03] src/nnvm/legacy_json_util.cc:217: Symbol successfully upgraded! Using Amazon Elastic Inference Client Library Version: 1.2.8 Number of Elastic Inference Accelerators Available: 1 Elastic Inference Accelerator ID: eia-95ae5a472b2241769656dbb5d344a80e Elastic Inference Accelerator Type: eia1.large probability=0.418679, class=n02119789 kit fox, Vulpes macrotis probability=0.293495, class=n02119022 red fox, Vulpes vulpes probability=0.029321, class=n02120505 grey fox, gray fox, Urocyon cinereoargenteus probability=0.026230, class=n02124075 Egyptian cat probability=0.022557, class=n02085620 Chihuahua

将 EI 与 Module API 和 ResNet-152 模型结合使用

以下示例在预训练的实际模型 (Resnet-152) 上将 EI 与 Module API 结合使用。

  1. 以下脚本下载两个 ResNet-152 模型文件(resnet-152-0000.params 和 resnet-152-symbol.json)和一个标签列表 (synset.txt)。该脚本还下载一张猫的图片,从预训练模型中获得一个预测结果,然后在标签列表中的结果中查找,并返回一个预测结果。使用您的首选文本编辑器来使用以下内容创建脚本。

    import mxnet as mx import numpy as np from collections import namedtuple Batch = namedtuple('Batch', ['data']) path='http://data.mxnet.io/models/imagenet/' [mx.test_utils.download(path+'resnet/152-layers/resnet-152-0000.params'), mx.test_utils.download(path+'resnet/152-layers/resnet-152-symbol.json'), mx.test_utils.download(path+'synset.txt')] ctx = mx.eia() sym, arg_params, aux_params = mx.model.load_checkpoint('resnet-152', 0) mod = mx.mod.Module(symbol=sym, context=ctx, label_names=None) mod.bind(for_training=False, data_shapes=[('data', (1,3,224,224))], label_shapes=mod._label_shapes) mod.set_params(arg_params, aux_params, allow_missing=True) with open('synset.txt', 'r') as f: labels = [l.rstrip() for l in f] fname = mx.test_utils.download('https://github.com/dmlc/web-data/blob/master/mxnet/doc/tutorials/python/predict_image/cat.jpg?raw=true') img = mx.image.imread(fname) # convert into format (batch, RGB, width, height) img = mx.image.imresize(img, 224, 224) # resize img = img.transpose((2, 0, 1)) # Channel first img = img.expand_dims(axis=0) # batchify mod.forward(Batch([img])) prob = mod.get_outputs()[0].asnumpy() # print the top-5 prob = np.squeeze(prob) a = np.argsort(prob)[::-1] for i in a[0:5]: print('probability=%f, class=%s' %(prob[i], labels[i]))
  2. 然后运行该脚本,您应看到类似于 Symbol API ResNet-50 示例输出的结果。

使用启用了 EI 的 MXNet 时的注意事项

  • MXNet EI 通过 MKLDNN 构建,因此,支持使用 mx.cpu() 上下文时的所有操作。MXNet EI 不支持 mx.gpu() 上下文,这意味着无法在已挂载的 GPU 上执行任何操作。任何使用 GPU 上下文的尝试都会引发错误。

  • MXNet Imperative 模式或 MXNet Gluon API 目前均不支持 EI,但可将 Gluon 模型以符号形式进行混合并导出

  • 您不能通过编写如下所示的某些内容来在远程加速器上分配 NDArray 的内存:x = mx.nd.array([[1, 2], [3, 4]], ctx=mx.eia())。这会引发错误。相反,您应使用 x = mx.nd.array([[1, 2], [3, 4]], ctx=mx.cpu())。MXNet 会根据需要将您的数据自动传输到加速器,因此无需担心这一点。示例错误消息:

    >>> mx.nd.array([1,2],ctx=mx.eia()) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/ec2-user/.local/lib/python3.6/site-packages/mxnet/ndarray/utils.py", line 146, in array return _array(source_array, ctx=ctx, dtype=dtype) File "/home/ec2-user/.local/lib/python3.6/site-packages/mxnet/ndarray/ndarray.py", line 2434, in array arr = empty(source_array.shape, ctx, dtype) File "/home/ec2-user/.local/lib/python3.6/site-packages/mxnet/ndarray/ndarray.py", line 3820, in empty return NDArray(handle=_new_alloc_handle(shape, ctx, False, dtype)) File "/home/ec2-user/.local/lib/python3.6/site-packages/mxnet/ndarray/ndarray.py", line 139, in _new_alloc_handle ctypes.byref(hdl))) File "/home/ec2-user/.local/lib/python3.6/site-packages/mxnet/base.py", line 252, in check_call raise MXNetError(py_str(_LIB.MXGetLastError())) mxnet.base.MXNetError: [21:51:47] src/storage/storage.cc:145: Unimplemented device 6 Stack trace returned 10 entries: [bt] (0) /home/ec2-user/.local/lib/python3.6/site-packages/mxnet/libmxnet.so(dmlc::StackTrace()+0x44) [0x7fc9ac6a8b34] [bt] (1) /home/ec2-user/.local/lib/python3.6/site-packages/mxnet/libmxnet.so(dmlc::LogMessageFatal::~LogMessageFatal()+0x21) [0x7fc9ac6a8f11] [bt] (2) /home/ec2-user/.local/lib/python3.6/site-packages/mxnet/libmxnet.so(+0x366e697) [0x7fc9af789697] [bt] (3) /home/ec2-user/.local/lib/python3.6/site-packages/mxnet/libmxnet.so(+0x367031f) [0x7fc9af78b31f] [bt] (4) /home/ec2-user/.local/lib/python3.6/site-packages/mxnet/libmxnet.so(mxnet::StorageImpl::Alloc(mxnet::Storage::Handle*)+0x3f) [0x7fc9af78c22f] [bt] (5) /home/ec2-user/.local/lib/python3.6/site-packages/mxnet/libmxnet.so(+0x595cf9) [0x7fc9ac6b0cf9] [bt] (6) /home/ec2-user/.local/lib/python3.6/site-packages/mxnet/libmxnet.so(mxnet::NDArray::NDArray(nnvm::TShape const, mxnet::Context, bool, int)+0x7fa) [0x7fc9ac6bc76a] [bt] (7) /home/ec2-user/.local/lib/python3.6/site-packages/mxnet/libmxnet.so(MXNDArrayCreateEx+0x17d) [0x7fc9aef87e7d] [bt] (8) /usr/lib64/libffi.so.6(ffi_call_unix64+0x4c) [0x7fca559bbcec] [bt] (9) /usr/lib64/libffi.so.6(ffi_call+0x1f5) [0x7fca559bb615]
  • 当您使用 Symbol API 或 Module API 时,请勿调用 backward() 方法或使用 for_training=True 调用 bind()。这会引发错误。由于 for_training 的默认值为 True,请务必手动设置 for_training=False。示例错误:

    Traceback (most recent call last): File "test.py", line 16, in <module> label_shapes=mod._label_shapes) File "/home/ec2-user/.local/lib/python3.6/site-packages/mxnet/module/module.py", line 402, in bind raise ValueError("for training cannot be set to true with EIA context") ValueError: for training cannot be set to true with EIA context
  • 由于不允许训练,因此,没有必要初始化优化器来进行推理。

  • 模型并行不支持 group2ctxs。如果您尝试创建以下 Module 对象,则会收到错误 Maximum one EI device can be attached to an instancemod = mx.mod.Module(c, context=[mx.eia(0), mx.eia(1)], data_names=['a', 'b'], label_names=None, group2ctxs={'dev1': mx.eia(2), 'dev2': mx.eia(3)}) 示例错误:

    Traceback (most recent call last): File "test2.py", line 14, in <module> mod = mx.mod.Module(symbol=sym, context=ctx, label_names=None, group2ctxs={'dev1': mx.eia(2), 'dev2':mx.eia(3)}) File "/home/ec2-user/.local/lib/python3.6/site-packages/mxnet/module/module.py", line 82, in __init__ raise ValueError("Maximum one EIA device can be attached to an instance") ValueError: Maximum one EIA device can be attached to an instance
  • 不支持多个上下文。也就是说,您无法使用数据并行。只能将一台 EI 设备挂载到一个实例。示例错误:

    Traceback (most recent call last): File "test3.py", line 14, in <module> mod = mx.mod.Module(symbol=sym, context=ctx, label_names=None) File "/home/ec2-user/.local/lib/python3.6/site-packages/mxnet/module/module.py", line 82, in __init__ raise ValueError("Maximum one EIA device can be attached to an instance") ValueError: Maximum one EIA device can be attached to an instance
  • MXNet version <= MXNet_EIA version 上训练的模型正常运行,但在 MXNet version >= MXNet_EIA 版本上训练的模型会导致未定义的行为。

  • 不同大小的 EI 加速器具有不同数量的 GPU 内存。如果您的模型需要的 GPU 内存量超过了加速器中可用的 GPU 内存量,您将收到一条类似于以下日志的消息。如果出现此消息,您应使用较大的加速器大小。停止并重启您的实例。

    [Tue Nov 27 00:13:27 2018, 717139us] [Execution Engine][MXNet][3] Failed - Last Error: EI Error Code: [12, 5, 13] EI Error Description: Internal error EI Request ID: MX-A830D1C2-D6F7-4264-8B9C-7D6402E26C06 -- EI Accelerator ID: eia-2e1e793895b040f989d2309c4b9f1e66 EI Client Version: 1.2.8 Traceback (most recent call last): File "test.py", line 30, in module prob = mod.get_outputs()[0].asnumpy() File "/home/ec2-user/anaconda3/envs/amazonei_mxnet_p36/lib/python3.6/site-packages/mxnet/ndarray/ndarray.py", line 1972, in asnumpy ctypes.c_size_t(data.size))) File "/home/ec2-user/anaconda3/envs/amazonei_mxnet_p36/lib/python3.6/site-packages/mxnet/base.py", line 252, in check_call raise MXNetError(py_str(_LIB.MXGetLastError())) mxnet.base.MXNetError: [00:13:27] src/operator/subgraph/eia/eia_subgraph_op.cc:147: Last Error: EI Error Code: [12, 5, 13] EI Error Description: Internal error EI Request ID: MX-A830D1C2-D6F7-4264-8B9C-7D6402E26C06 -- EI Accelerator ID: eia-2e1e793895b040f989d2309c4b9f1e66 EI Client Version: 1.2.8
  • 通过使用 Module API 或 Symbol API 显式调用 reshape,或者在不同的前向传递中使用输入 ndarrays 的不同形状来隐式调用它可能导致 OOM 错误。在进行调整之前,不会在加速器上清理模型,直到会话被销毁。

更多模型和资源

下面提供了有关试用 EI 的更多预训练模型和示例。

  1. MXNet ImageNet 模型 - 可通过更新第 6 行上的 path 变量将此处找到的多个基于 ImageNet 的模型放入之前的示例中。

  2. MXNet Model Zoo - 这些 Gluon 模型可导出为符号格式并用于 EI。

  3. 带 MXNet 的开放神经网络交换 (ONNX) 模型 - MXNet 本机支持 ONNX 模型格式,因此,您可以将 EI 与从其他框架中导出的 ONNX 模型结合使用。

有关更多教程和示例,请参阅该框架的官方 Python 文档、适用于 MXNet 的 Python APIApache MXNet 网站。