You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mxnet.apache.org by an...@apache.org on 2018/06/13 21:32:36 UTC

[incubator-mxnet] 06/12: [MXNET-365] handle inplace in mkldnn FallBackCompute (#10591)

This is an automated email from the ASF dual-hosted git repository.

anirudh2290 pushed a commit to branch v1.2.0
in repository https://gitbox.apache.org/repos/asf/incubator-mxnet.git

commit 18d239cc6776ab8bdc2aae7cf575a8cd85f7caf3
Author: Ashok Emani <as...@intel.com>
AuthorDate: Fri May 11 02:31:28 2018 -0700

    [MXNET-365] handle inplace in mkldnn FallBackCompute (#10591)
    
    * handle inplace in mkldnn FallBackCompute
    
    * add comments
    
    * handle kAddTo in mkldnn FallBackCompute
    
    * add PR feedback
    
    * add unittest for mkldnn inplace sum with cpu data
    
    * add back mkldnn engine threading unittest
    
    * separate mkldnn install test and fix pylint issue
    
    * remove --build from mkldnn jenkins test
    
    * update mkldnn unittests
    
    * update comments for mkldnn test
    
    * remove python test doc string so unittest name is used
---
 Jenkinsfile                             |   2 +-
 src/operator/nn/mkldnn/mkldnn_base.cc   |  13 +++-
 tests/python/mkl/test_mkldnn.py         | 132 ++++++++++++--------------------
 tests/python/mkl/test_mkldnn_install.py |  56 ++++++++++++++
 4 files changed, 113 insertions(+), 90 deletions(-)

diff --git a/Jenkinsfile b/Jenkinsfile
index 7167f14..eb2160f 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -109,7 +109,7 @@ def python3_ut(docker_container_name) {
 
 def python3_ut_mkldnn(docker_container_name) {
   timeout(time: max_time, unit: 'MINUTES') {
-    sh "ci/build.py --build --platform ${docker_container_name} /work/runtime_functions.sh unittest_ubuntu_python3_cpu_mkldnn"
+    sh "ci/build.py --platform ${docker_container_name} /work/runtime_functions.sh unittest_ubuntu_python3_cpu_mkldnn"
   }
 }
 
diff --git a/src/operator/nn/mkldnn/mkldnn_base.cc b/src/operator/nn/mkldnn/mkldnn_base.cc
index 684abd2..8792cbc 100644
--- a/src/operator/nn/mkldnn/mkldnn_base.cc
+++ b/src/operator/nn/mkldnn/mkldnn_base.cc
@@ -293,10 +293,15 @@ void FallBackCompute(FCompute fn, const nnvm::NodeAttrs &attrs,
 
   std::vector<TBlob> out_blobs(outputs.size());
   for (size_t i = 0; i < out_blobs.size(); i++) {
-    if (req[i] == kWriteTo)
-      const_cast<NDArray &>(outputs[i]).InvalidateMKLDNNData();
-    CHECK(outputs[i].IsDefaultData());
-    out_blobs[i] = outputs[i].data();
+    NDArray output = outputs[i];
+    // ensure output does not use mkldnn mem.
+    // for inplace, we already converted & copied input above.
+    if ((req[i] == kWriteTo) || (req[i] == kWriteInplace))
+      const_cast<NDArray &>(output).InvalidateMKLDNNData();
+    else if (req[i] == kAddTo)
+      output = outputs[i].Reorder2Default();
+    CHECK(output.IsDefaultData());
+    out_blobs[i] = output.data();
   }
   fn(attrs, ctx, in_blobs, req, out_blobs);
 }
diff --git a/tests/python/mkl/test_mkldnn.py b/tests/python/mkl/test_mkldnn.py
index dc9e914..2caf7af 100644
--- a/tests/python/mkl/test_mkldnn.py
+++ b/tests/python/mkl/test_mkldnn.py
@@ -18,57 +18,19 @@
 """
 MKL-DNN related test cases
 """
-
-import mxnet as mx
+import sys
+import os
 import numpy as np
-import sys,os,logging
+import mxnet as mx
+from mxnet.test_utils import assert_almost_equal
 from mxnet import gluon
 from mxnet.gluon import nn
 curr_path = os.path.dirname(os.path.abspath(os.path.expanduser(__file__)))
 sys.path.append(os.path.join(curr_path, '../unittest/'))
-from common import setup_module, with_seed
-from nose.tools import raises
-from mxnet.test_utils import assert_almost_equal
-
-
-def test_mkldnn_install():
-    """
-    This test will verify that MXNet is built/installed correctly when
-    compiled with Intel MKL-DNN library. The method will try to import
-    the mxnet module and see if the mkldnn library is mapped to this
-    process's address space.
-    """
-    logging.basicConfig(level=logging.INFO)
-
-    if not sys.platform.startswith('linux'):
-        logging.info("Bypass mkldnn install test for non-Linux OS")
-        return
-
-    try:
-        #pylint: disable=unused-variable
-        import mxnet as mx
-    except (ImportError, OSError) as e:
-        assert 0, "Import mxnet error: %s. Please double check your build/" \
-            "install steps or environment variable settings" % str(e)
-
-    pid = os.getpid()
-    rc = os.system("cat /proc/" + str(pid) +
-                   "/maps | grep libmkldnn > /dev/null")
-
-    if rc == 0:
-        logging.info("MXNet is built/installed correctly with MKL-DNN")
-    else:
-        assert 0, "MXNet is built/installed incorrectly with MKL-DNN, please " \
-            "double check your build/install steps or environment " \
-            "variable settings"
+from common import with_seed
 
 
 def test_mkldnn_model():
-    """
-    This test will run a sample model for couple of iterations.
-    """
-
-    import mxnet as mx
     model = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data",
                          "test_mkldnn_test_mkldnn_model_model1.json")
     shape = (32, 3, 300, 300)
@@ -96,17 +58,19 @@ def test_mkldnn_model():
     except:  # pylint: disable=bare-except
         assert 0, "test_mkldnn_model exception in bind and execution"
 
-def test_mkldnn_engine_threading():
-    """
-    This test will trigger mkldnn engine on different thread of execution.
-    The test will first kickoff simple model calculation, and then uses a
-    gluon data iterator to trigger different thread context, and executes
-    the model on this new thread.
-    """
+def test_mkldnn_ndarray_slice():
+    ctx = mx.cpu()
+    net = gluon.nn.HybridSequential()
+    with net.name_scope():
+        net.add(gluon.nn.Conv2D(channels=32, kernel_size=3, activation=None))
+    net.collect_params().initialize(ctx=ctx)
+    x = mx.nd.array(np.ones([32, 3, 224, 224]), ctx)
+    y = net(x)
 
-    import mxnet as mx
-    from mxnet import gluon, nd
+    # trigger computation on ndarray slice
+    assert_almost_equal(y[0].asnumpy()[0, 0, 0], 0.3376348)
 
+def test_mkldnn_engine_threading():
     net = gluon.nn.HybridSequential()
     with net.name_scope():
         net.add(gluon.nn.Conv2D(channels=32, kernel_size=3, activation=None))
@@ -121,47 +85,30 @@ def test_mkldnn_engine_threading():
 
     X = (32, 3, 32, 32)
     # trigger mkldnn execution thread
-    y = net(nd.array(np.ones(X))).asnumpy()
+    y = net(mx.nd.array(np.ones(X))).asnumpy()
 
     # Use Gluon dataloader to trigger different thread.
     # below line triggers different execution thread
     for _ in loader:
-        y = net(nd.array(np.ones(X))).asnumpy()
-        # output should have 0.3376348
-        assert_almost_equal(y[0, 0, 0, 0], 0.3376348)
+        y = net(mx.nd.array(np.ones(X))).asnumpy()
+        # output should be 016711406 (non-mkldnn mode output) 
+        assert_almost_equal(y[0, 0, 0, 0], 0.016711406)
         break
 
-def test_mkldnn_ndarray_slice():
-    """
-    This test will trigger gluon computation on mkldnn with ndarray slice
-    """
-
-    import mxnet as mx
-    from mxnet import gluon
-    ctx = mx.cpu()
-    net = gluon.nn.HybridSequential()
-    with net.name_scope():
-        net.add(gluon.nn.Conv2D(channels=32, kernel_size=3, activation=None))
-        net.collect_params().initialize(ctx=ctx)
-        x = mx.nd.array(np.ones([32, 3, 224, 224]), ctx)
-        y = net(x)
-
-        # trigger computation on ndarray slice
-        assert_almost_equal(y[0].asnumpy()[0, 0, 0], 0.3376348)
 
 @with_seed()
 def test_reshape_before_conv():
-    """
-    This test will test gluon Conv2d computation on mkldnn with ndarray reshape
-    """
     class Net(gluon.HybridBlock):
+        """
+        test Net
+        """
         def __init__(self, **kwargs):
             super(Net, self).__init__(**kwargs)
             with self.name_scope():
                 self.conv0 = nn.Conv2D(10, (3, 3))
                 self.conv1 = nn.Conv2D(5, (3, 3))
 
-        def hybrid_forward(self, F, x):
+        def hybrid_forward(self, F, x, *args, **kwargs):
             x_reshape = x.reshape((0, 0, 20, 5))
             y = self.conv0(x_reshape)
             y_reshape = y.reshape((0, 0, 9, 6))
@@ -185,17 +132,17 @@ def test_reshape_before_conv():
 
 @with_seed()
 def test_slice_before_conv():
-    """
-    This test will test gluon Conv2d computation on mkldnn with ndarray slice
-    """
     class Net(gluon.HybridBlock):
+        """
+        test Net
+        """
         def __init__(self, **kwargs):
             super(Net, self).__init__(**kwargs)
             with self.name_scope():
                 self.conv0 = nn.Conv2D(4, (3, 3))
                 self.conv1 = nn.Conv2D(4, (3, 3))
 
-        def hybrid_forward(self, F, x):
+        def hybrid_forward(self, F, x, *args, **kwargs):
             x_slice = x.slice(begin=(0, 0, 0, 0), end=(2, 4, 10, 10))
             y = self.conv0(x_slice)
             y_slice = y.slice(begin=(1, 0, 2, 2), end=(2, 1, 7, 7))
@@ -219,17 +166,17 @@ def test_slice_before_conv():
 
 @with_seed()
 def test_slice_reshape_before_conv():
-    """
-    This test will test gluon Conv2d computation on mkldnn with ndarray reshape and slice
-    """
     class Net(gluon.HybridBlock):
+        """
+        test Net
+        """
         def __init__(self, **kwargs):
             super(Net, self).__init__(**kwargs)
             with self.name_scope():
                 self.conv0 = nn.Conv2D(4, (3, 3))
                 self.conv1 = nn.Conv2D(4, (3, 3))
 
-        def hybrid_forward(self, F, x):
+        def hybrid_forward(self, F, x, *args, **kwargs):
             x_slice = x.slice(begin=(0, 0, 0, 0), end=(2, 4, 8, 9))
             y = self.conv0(x_slice)
             y_reshape = y.reshape((0, 0, 14, 3))
@@ -251,5 +198,20 @@ def test_slice_reshape_before_conv():
     mx.test_utils.assert_almost_equal(out1.asnumpy(), out2.asnumpy(), rtol=1e-5, atol=1e-6)
 
 
+def test_mkldnn_sum_inplace_with_cpu_layout():
+
+    x_shape = (32, 3, 224, 224)
+    x_npy = np.ones(x_shape)
+    y_shape = (32, 32, 222, 222)
+    y_npy = np.ones(y_shape)
+    x = mx.sym.Variable("x")
+    y = mx.sym.Variable("y")
+    z = mx.symbol.Convolution(data=x, num_filter=32, kernel=(3, 3))
+    z = mx.sym.add_n(z, y)
+    exe = z.simple_bind(ctx=mx.cpu(), x=x_shape, y=y_shape)
+    out = exe.forward(is_train=False, x=x_npy, y=y_npy)[0]
+    assert_almost_equal(out[0].asnumpy()[0, 0, 0], 1.0)
+
+
 if __name__ == '__main__':
     test_mkldnn_install()
diff --git a/tests/python/mkl/test_mkldnn_install.py b/tests/python/mkl/test_mkldnn_install.py
new file mode 100644
index 0000000..c2f26df
--- /dev/null
+++ b/tests/python/mkl/test_mkldnn_install.py
@@ -0,0 +1,56 @@
+# 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.
+
+"""
+MKL-DNN related test cases
+"""
+
+import sys
+import os
+import logging
+
+
+def test_mkldnn_install():
+    """
+    This test will verify that MXNet is built/installed correctly when
+    compiled with Intel MKL-DNN library. The method will try to import
+    the mxnet module and see if the mkldnn library is mapped to this
+    process's address space.
+    """
+    logging.basicConfig(level=logging.INFO)
+
+    if not sys.platform.startswith('linux'):
+        logging.info("Bypass mkldnn install test for non-Linux OS")
+        return
+
+    try:
+        #pylint: disable=unused-variable
+        import mxnet as mx
+    except (ImportError, OSError) as e:
+        assert 0, "Import mxnet error: %s. Please double check your build/" \
+            "install steps or environment variable settings" % str(e)
+
+    pid = os.getpid()
+    rc = os.system("cat /proc/" + str(pid) +
+                   "/maps | grep libmkldnn > /dev/null")
+
+    if rc == 0:
+        logging.info("MXNet is built/installed correctly with MKL-DNN")
+    else:
+        assert 0, "MXNet is built/installed incorrectly with MKL-DNN, please " \
+            "double check your build/install steps or environment " \
+            "variable settings"

-- 
To stop receiving notification emails like this one, please contact
anirudh2290@apache.org.