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

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


The following commit(s) were added to refs/heads/master by this push:
     new 52d809c  Fix for issue #8491, elemwise_mul nan behavior (#8492)
52d809c is described below

commit 52d809c9288e70927534dc783c439dfd65df7de7
Author: Chris Olivier <cjolivie...@gmail.com>
AuthorDate: Fri Nov 3 20:29:06 2017 -0700

    Fix for issue #8491, elemwise_mul nan behavior (#8492)
    
    * Fix for issue #8491, elemwise_mul nan behavior
    https://github.com/apache/incubator-mxnet/issues/8491
    
    * Also make nan * 0 -> dense
    
    * Also make nan * 0 -> dense
    
    * Add Scala package dev tools for deploy (#8498)
    
    * [scala] do not print op definition during compiling by default
    
    * [scala] add dev tools for changing artifactId
    
    * [scala] add scala make clean
    
    * Getting read of maybe_uninitialized warnings (#8318)
    
    * Fix of log10_grad, log2_grad (#8502)
    
    * add default hash to ndarray (#8476)
    
    * bump up version (#8488)
    
    * fix makenonlossgrad bug (#8508)
    
    * fix expand_dims if axis< 0 (#8489)
    
    * fix expand_dims if axis< 0
    
    * Update test_operator.py
    
    * Correct Initialization Description in Finetune Tutorial. (#8517)
    
    * Trigger rebuild
---
 src/operator/tensor/elemwise_binary_op.cc       | 45 ------------------------
 src/operator/tensor/elemwise_binary_op.h        | 46 ++++++++++++++++++++++++-
 src/operator/tensor/elemwise_binary_op_basic.cc |  7 ++--
 tests/python/unittest/test_sparse_operator.py   | 11 ++++--
 4 files changed, 57 insertions(+), 52 deletions(-)

diff --git a/src/operator/tensor/elemwise_binary_op.cc 
b/src/operator/tensor/elemwise_binary_op.cc
index 00c5e10..931132b 100644
--- a/src/operator/tensor/elemwise_binary_op.cc
+++ b/src/operator/tensor/elemwise_binary_op.cc
@@ -86,50 +86,5 @@ bool ElemwiseBinaryOp::BackwardUseInStorageType(const 
nnvm::NodeAttrs& attrs,
   return true;
 }
 
-bool ElemwiseBinaryOp::AllowLRDenseInputWithSparseOutputStorageType(const 
nnvm::NodeAttrs& attrs,
-                                                                    const int 
dev_mask,
-                                                                    
DispatchMode* dispatch_mode,
-                                                                    
std::vector<int> *in_attrs,
-                                                                    
std::vector<int> *out_attrs) {
-  CHECK_EQ(in_attrs->size(), 2U) << " in operator " << attrs.name;
-  CHECK_EQ(out_attrs->size(), 1U) << " in operator " << attrs.name;
-  const auto& lhs_stype = in_attrs->at(0);
-  const auto& rhs_stype = in_attrs->at(1);
-  auto& out_stype = out_attrs->at(0);
-  bool dispatched = false;
-  const bool invalid_ctx = dev_mask != mshadow::cpu::kDevMask;
-  const auto dispatch_ex = invalid_ctx ? DispatchMode::kFComputeFallback :
-                           DispatchMode::kFComputeEx;
-  if (!dispatched && lhs_stype == kDefaultStorage && rhs_stype == 
kDefaultStorage) {
-    // dns, dns -> dns
-    dispatched = storage_type_assign(&out_stype, kDefaultStorage,
-                                     dispatch_mode, DispatchMode::kFCompute);
-  }
-  if (!dispatched) {
-    if ((lhs_stype == kRowSparseStorage && rhs_stype == kRowSparseStorage) ||
-        (lhs_stype == kRowSparseStorage && rhs_stype == kDefaultStorage) ||
-        (lhs_stype == kDefaultStorage && rhs_stype == kRowSparseStorage)) {
-      // rsp, rsp -> rsp
-      // rsp, dns -> rsp
-      // dns, rsp -> rsp
-      dispatched = storage_type_assign(&out_stype, kRowSparseStorage,
-                                       dispatch_mode, dispatch_ex);
-    } else if (lhs_stype == kCSRStorage && rhs_stype == kCSRStorage) {
-      dispatched = storage_type_assign(&out_stype, kCSRStorage,
-                                       dispatch_mode, dispatch_ex);
-    } else if (lhs_stype == kCSRStorage || rhs_stype == kCSRStorage) {
-      dispatched = storage_type_assign(&out_stype, kCSRStorage,
-                                       dispatch_mode, 
DispatchMode::kFComputeFallback);
-    }
-  }
-  if (!dispatched) {
-    dispatch_fallback(out_attrs, dispatch_mode);
-  }
-  if (*dispatch_mode == DispatchMode::kFComputeFallback) {
-    LogStorageFallback(attrs, dev_mask, in_attrs, out_attrs);
-  }
-  return true;
-}
-
 }  // namespace op
 }  // namespace mxnet
diff --git a/src/operator/tensor/elemwise_binary_op.h 
b/src/operator/tensor/elemwise_binary_op.h
index 6a1cc02..b8b5bd1 100644
--- a/src/operator/tensor/elemwise_binary_op.h
+++ b/src/operator/tensor/elemwise_binary_op.h
@@ -273,11 +273,55 @@ class ElemwiseBinaryOp : public OpBase {
    * \param out_attrs Output storage attributes
    * \return true if handled
    */
+  template<bool lhs_dense_ok = true, bool rhs_dense_ok = true>
   static bool AllowLRDenseInputWithSparseOutputStorageType(const 
nnvm::NodeAttrs& attrs,
                                                            int dev_mask,
                                                            DispatchMode* 
dispatch_mode,
                                                            std::vector<int> 
*in_attrs,
-                                                           std::vector<int> 
*out_attrs);
+                                                           std::vector<int> 
*out_attrs) {
+    CHECK_EQ(in_attrs->size(), 2U) << " in operator " << attrs.name;
+    CHECK_EQ(out_attrs->size(), 1U) << " in operator " << attrs.name;
+    const auto& lhs_stype = in_attrs->at(0);
+    const auto& rhs_stype = in_attrs->at(1);
+    auto& out_stype = out_attrs->at(0);
+    bool dispatched = false;
+    const bool invalid_ctx = dev_mask != mshadow::cpu::kDevMask;
+    const auto dispatch_ex = invalid_ctx ? DispatchMode::kFComputeFallback :
+                             DispatchMode::kFComputeEx;
+    if (!dispatched && lhs_stype == kDefaultStorage && rhs_stype == 
kDefaultStorage) {
+      // dns, dns -> dns
+      dispatched = storage_type_assign(&out_stype, kDefaultStorage,
+                                       dispatch_mode, DispatchMode::kFCompute);
+    }
+    if (!dispatched) {
+      if ((lhs_stype == kRowSparseStorage && rhs_stype == kRowSparseStorage) ||
+          (rhs_dense_ok && lhs_stype == kRowSparseStorage && rhs_stype == 
kDefaultStorage) ||
+          (lhs_dense_ok && lhs_stype == kDefaultStorage && rhs_stype == 
kRowSparseStorage)) {
+        // rsp, rsp -> rsp
+        // rsp, dns -> rsp
+        // dns, rsp -> rsp
+        dispatched = storage_type_assign(&out_stype, kRowSparseStorage,
+                                         dispatch_mode, dispatch_ex);
+      } else if (lhs_stype == kCSRStorage && rhs_stype == kCSRStorage) {
+        // csr, csr -> csr
+        dispatched = storage_type_assign(&out_stype, kCSRStorage,
+                                         dispatch_mode, dispatch_ex);
+      } else if ((lhs_stype == kCSRStorage && rhs_dense_ok) ||
+        (rhs_stype == kCSRStorage && lhs_dense_ok)) {
+        // csr, dns -> csr
+        // dns, csr -> csr
+        dispatched = storage_type_assign(&out_stype, kCSRStorage,
+                                         dispatch_mode, 
DispatchMode::kFComputeFallback);
+      }
+    }
+    if (!dispatched) {
+      dispatch_fallback(out_attrs, dispatch_mode);
+    }
+    if (*dispatch_mode == DispatchMode::kFComputeFallback) {
+      LogStorageFallback(attrs, dev_mask, in_attrs, out_attrs);
+    }
+    return true;
+  }
 
   /*!
    * \brief Backward pass computing input gradient using forward inputs
diff --git a/src/operator/tensor/elemwise_binary_op_basic.cc 
b/src/operator/tensor/elemwise_binary_op_basic.cc
index f812fe0..b3be9e4 100644
--- a/src/operator/tensor/elemwise_binary_op_basic.cc
+++ b/src/operator/tensor/elemwise_binary_op_basic.cc
@@ -98,13 +98,14 @@ The storage type of ``elemwise_mul`` output depends on 
storage types of inputs
 
    - elemwise_mul(default, default) = default
    - elemwise_mul(row_sparse, row_sparse) = row_sparse
-   - elemwise_mul(default, row_sparse) = row_sparse
-   - elemwise_mul(row_sparse, default) = row_sparse
+   - elemwise_mul(default, row_sparse) = default
+   - elemwise_mul(row_sparse, default) = default
    - otherwise, ``elemwise_mul`` generates output with default storage
 
 )code")
 .set_attr<FInferStorageType>("FInferStorageType",
-                             
ElemwiseBinaryOp::AllowLRDenseInputWithSparseOutputStorageType)
+                             
ElemwiseBinaryOp::AllowLRDenseInputWithSparseOutputStorageType<
+                               false, false>)  // 0 * nan or nan * 0 -> nan, 
so rsp * dns -> dns
 .set_attr<FCompute>("FCompute<cpu>", ElemwiseBinaryOp::Compute<cpu, 
mshadow::op::mul>)
 .set_attr<FComputeEx>("FComputeEx<cpu>",
                       ElemwiseBinaryOp::ComputeDnsLRValueEx<cpu, 
mshadow::op::mul, true, true>)
diff --git a/tests/python/unittest/test_sparse_operator.py 
b/tests/python/unittest/test_sparse_operator.py
index b281749..d440553 100644
--- a/tests/python/unittest/test_sparse_operator.py
+++ b/tests/python/unittest/test_sparse_operator.py
@@ -327,6 +327,11 @@ def test_elemwise_binary_ops():
             return rstype
         return lstype
 
+    def most_dense(lstype, rstype):
+      if lstype == rstype:
+        return lstype
+      return 'default'
+
     def check_elemwise_binary_ops(lhs_stype, rhs_stype, shape,
                                   lhs_grad_stype=None, rhs_grad_stype=None,
                                   lhs_density=.5, rhs_density=.5,
@@ -362,7 +367,7 @@ def test_elemwise_binary_ops():
                                 lambda outg, l, r: (outg * r, outg * l),
                                 least_sparse(lhs_stype, rhs_stype),
                                 least_sparse(lhs_stype, rhs_stype),
-                                
expected_result_storage_type=least_sparse(lhs_stype, rhs_stype),
+                                
expected_result_storage_type=most_dense(lhs_stype, rhs_stype),
                                 ograd_density=ograd_density,
                                 force_lr_overlap=force_lr_overlap,
                                 force_grad_overlap=force_grad_overlap,
@@ -449,8 +454,8 @@ def test_elemwise_binary_ops():
 
                                 shape = rand_shape_2d()
 
-                                print("  force_lr_overlap={}, 
force_grad_overlap={}, shape={}"
-                                    .format(force_lr_overlap, 
force_grad_overlap, shape))
+                                print("  force_lr_overlap={}, 
force_grad_overlap={}, shape={}".
+                                      format(force_lr_overlap, 
force_grad_overlap, shape))
 
                                 # Left and right always overlap when one is 
default storage
                                 # (assuming the row_sparse one has some 
entries in it)

-- 
To stop receiving notification emails like this one, please contact
['"comm...@mxnet.apache.org" <comm...@mxnet.apache.org>'].

Reply via email to