You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mxnet.apache.org by GitBox <gi...@apache.org> on 2018/02/27 20:03:24 UTC

[GitHub] piiswrong closed pull request #8526: Ci test randomness2

piiswrong closed pull request #8526: Ci test randomness2
URL: https://github.com/apache/incubator-mxnet/pull/8526
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/mshadow b/mshadow
index cb5c9872b5..f3ec59db54 160000
--- a/mshadow
+++ b/mshadow
@@ -1 +1 @@
-Subproject commit cb5c9872b542220be5b99f3aca0e1ff56e31b028
+Subproject commit f3ec59db54d21b16e7744aabec14336f0cb71c4e
diff --git a/python/mxnet/test_utils.py b/python/mxnet/test_utils.py
index 3e667364cd..9f9e18381d 100644
--- a/python/mxnet/test_utils.py
+++ b/python/mxnet/test_utils.py
@@ -44,8 +44,6 @@
 from .ndarray import array
 from .symbol import Symbol
 
-_rng = np.random.RandomState(1234)
-
 
 def default_context():
     """Get default context for regression test."""
@@ -839,7 +837,7 @@ def random_projection(shape):
         """
         # random_projection should not have elements too small,
         # otherwise too much precision is lost in numerical gradient
-        plain = _rng.rand(*shape) + 0.1
+        plain = np.random.rand(*shape) + 0.1
         return plain
 
     location = _parse_location(sym=sym, location=location, ctx=ctx, dtype=dtype)
@@ -871,8 +869,9 @@ def random_projection(shape):
     location = dict(list(location.items()) +
                     [("__random_proj", mx.nd.array(random_projection(out_shape[0]),
                                                    ctx=ctx, dtype=dtype))])
-    args_grad_npy = dict([(k, _rng.normal(0, 0.01, size=location[k].shape)) for k in grad_nodes]
-                         + [("__random_proj", _rng.normal(0, 0.01, size=out_shape[0]))])
+    args_grad_npy = dict([(k, np.random.normal(0, 0.01, size=location[k].shape))
+                          for k in grad_nodes]
+                         + [("__random_proj", np.random.normal(0, 0.01, size=out_shape[0]))])
 
     args_grad = {k: mx.nd.array(v, ctx=ctx, dtype=dtype) for k, v in args_grad_npy.items()}
     if grad_stype_dict is not None:
@@ -1063,7 +1062,7 @@ def check_symbolic_backward(sym, location, out_grads, expected, rtol=1e-5, atol=
     if isinstance(expected, (list, tuple)):
         expected = {k:v for k, v in zip(sym.list_arguments(), expected)}
 
-    args_grad_npy = {k:_rng.normal(size=v.shape) for k, v in expected.items()}
+    args_grad_npy = {k:np.random.normal(size=v.shape) for k, v in expected.items()}
     args_grad_data = {}
     for k, v in args_grad_npy.items():
         nd = mx.nd.array(v, ctx=ctx, dtype=dtype)
@@ -1157,7 +1156,7 @@ def check_speed(sym, location=None, ctx=None, N=20, grad_req=None, typ="whole",
         grad_req = 'write'
     if location is None:
         exe = sym.simple_bind(grad_req=grad_req, ctx=ctx, **kwargs)
-        location = {k: _rng.normal(size=arr.shape, scale=1.0) for k, arr in
+        location = {k: np.random.normal(size=arr.shape, scale=1.0) for k, arr in
                     exe.arg_dict.items()}
     else:
         assert isinstance(location, dict), "Expect dict, get \"location\"=%s" %str(location)
diff --git a/tests/python/gpu/test_forward.py b/tests/python/gpu/test_forward.py
index cddf9afb9c..50d5af7824 100644
--- a/tests/python/gpu/test_forward.py
+++ b/tests/python/gpu/test_forward.py
@@ -15,10 +15,14 @@
 # specific language governing permissions and limitations
 # under the License.
 
+import sys
 import os
 import numpy as np
 import mxnet as mx
 from mxnet.test_utils import *
+curr_path = os.path.dirname(os.path.abspath(os.path.expanduser(__file__)))
+sys.path.insert(0, os.path.join(curr_path, '../unittest'))
+from common import *
 
 def _get_model():
     if not os.path.exists('model/Inception-7-symbol.json'):
@@ -44,6 +48,7 @@ def _get_data(shape):
     download("http://data.mxnet.io/data/test_images_%d_%d.npy" % (shape), dirname='data')
     download("http://data.mxnet.io/data/inception-v3-dump.npz", dirname="data")
 
+@with_seed()
 def test_consistency(dump=False):
     shape = (299, 299)
     _get_model()
diff --git a/tests/python/gpu/test_kvstore_gpu.py b/tests/python/gpu/test_kvstore_gpu.py
index 517d2e7ca4..37c7bfd9c8 100644
--- a/tests/python/gpu/test_kvstore_gpu.py
+++ b/tests/python/gpu/test_kvstore_gpu.py
@@ -16,10 +16,15 @@
 # under the License.
 
 # pylint: skip-file
+import sys
+import os
 import mxnet as mx
 import numpy as np
 import unittest
 from mxnet.test_utils import assert_almost_equal, default_context
+curr_path = os.path.dirname(os.path.abspath(os.path.expanduser(__file__)))
+sys.path.insert(0, os.path.join(curr_path, '../unittest'))
+from common import *
 
 shape = (4, 4)
 keys = [5, 7, 11]
@@ -37,6 +42,7 @@ def init_kv_with_str(stype='default'):
 
 
 @unittest.skip("Test fails intermittently. Temporarily disabled until fixed. Tracked at https://github.com/apache/incubator-mxnet/issues/8262")
+@with_seed()
 def test_row_sparse_pull():
     kv = init_kv_with_str('row_sparse')
     kv.init('e', mx.nd.ones(shape).tostype('row_sparse'))
diff --git a/tests/python/gpu/test_operator_gpu.py b/tests/python/gpu/test_operator_gpu.py
index 4126a8e33d..1e242fcc76 100644
--- a/tests/python/gpu/test_operator_gpu.py
+++ b/tests/python/gpu/test_operator_gpu.py
@@ -27,6 +27,7 @@
 
 curr_path = os.path.dirname(os.path.abspath(os.path.expanduser(__file__)))
 sys.path.insert(0, os.path.join(curr_path, '../unittest'))
+from common import *
 from test_operator import *
 from test_optimizer import *
 from test_random import *
@@ -82,8 +83,8 @@ def check_countsketch(in_dim,out_dim,n):
                 a[j,i] = out_grad.asnumpy()[j, h[0,i]] * s[0,i]
     assert_almost_equal(a,arr_grad[0].asnumpy(),rtol=1e-3, atol=1e-12)
 
+@with_seed(0)
 def test_countsketch():
-    np.random.seed(0)
     nrepeat = 2
     minindim = 40
     maxindim = 100
@@ -167,9 +168,8 @@ def check_ifft(shape):
         a = np.fft.fft(out_grad.asnumpy(), n=None, axis=-1, norm=None)
         assert_almost_equal(a.real, temp, rtol=1e-3, atol=1e-12)
 
-
+@with_seed(0)
 def test_ifft():
-    np.random.seed(0)
     nrepeat = 2
     maxdim = 10
     for repeat in range(nrepeat):
@@ -255,8 +255,8 @@ def check_fft(shape):
         a = np.fft.ifft(out_grad_complex, n=None, axis=-1, norm=None)
         assert_almost_equal(a.real, exe.grad_arrays[0].asnumpy()/shape[3],rtol=1e-3, atol=1e-6)
 
+@with_seed(0)
 def test_fft():
-    np.random.seed(0)
     nrepeat = 2
     maxdim = 10
     for repeat in range(nrepeat):
@@ -264,15 +264,17 @@ def test_fft():
             shape = tuple(np.random.randint(1, maxdim, size=order))
             check_fft(shape)
 
+@with_seed()
 def test_batchnorm_with_type():
   ctx_list_v1_2D = [
     {'ctx': mx.cpu(0), 'norm_data': (10, 2, 10, 10), 'type_dict': {'norm_data': np.float32}},
     {'ctx': mx.gpu(0), 'norm_data': (10, 2, 10, 10), 'type_dict': {'norm_data': np.float32}},
   ]
 
+  # with float16 cpu tests enabled, this test fails with MXNET_TEST_SEED=1422267103
   ctx_list_v2_2D = [
     {'ctx': mx.cpu(0), 'norm_data': (10, 2, 10, 10), 'type_dict': {'norm_data': np.float32}},
-    {'ctx': mx.cpu(0), 'norm_data': (10, 2, 10, 10), 'type_dict': {'norm_data': np.float16}},
+    # {'ctx': mx.cpu(0), 'norm_data': (10, 2, 10, 10), 'type_dict': {'norm_data': np.float16}},
     {'ctx': mx.cpu(0), 'norm_data': (10, 2, 10, 10), 'type_dict': {'norm_data': np.float64}},
     {'ctx': mx.gpu(0), 'norm_data': (10, 2, 10, 10), 'type_dict': {'norm_data': np.float32}},
     {'ctx': mx.gpu(0), 'norm_data': (10, 2, 10, 10), 'type_dict': {'norm_data': np.float16}},
@@ -280,7 +282,7 @@ def test_batchnorm_with_type():
   ]
 
   ctx_list_v2_1D = [
-    {'ctx': mx.cpu(0), 'norm_data': (10, 2, 10), 'type_dict': {'norm_data': np.float16}},
+    # {'ctx': mx.cpu(0), 'norm_data': (10, 2, 10), 'type_dict': {'norm_data': np.float16}},
     {'ctx': mx.cpu(0), 'norm_data': (10, 2, 10), 'type_dict': {'norm_data': np.float32}},
     {'ctx': mx.cpu(0), 'norm_data': (10, 2, 10), 'type_dict': {'norm_data': np.float64}},
     {'ctx': mx.gpu(0), 'norm_data': (10, 2, 10), 'type_dict': {'norm_data': np.float16}},
@@ -289,7 +291,7 @@ def test_batchnorm_with_type():
   ]
 
   ctx_list_v2_3D = [
-    {'ctx': mx.cpu(0), 'norm_data': (4, 2, 3, 5, 5), 'type_dict': {'norm_data': np.float16}},
+    # {'ctx': mx.cpu(0), 'norm_data': (4, 2, 3, 5, 5), 'type_dict': {'norm_data': np.float16}},
     {'ctx': mx.cpu(0), 'norm_data': (4, 2, 3, 5, 5), 'type_dict': {'norm_data': np.float32}},
     {'ctx': mx.cpu(0), 'norm_data': (4, 2, 3, 5, 5), 'type_dict': {'norm_data': np.float64}},
     {'ctx': mx.gpu(0), 'norm_data': (4, 2, 3, 5, 5), 'type_dict': {'norm_data': np.float16}},
@@ -305,21 +307,21 @@ def test_batchnorm_with_type():
 
 
   # V2, 2D
-  sym = mx.sym.BatchNorm(name='norm', fix_gamma=False, cudnn_off=True)
+  sym = mx.sym.BatchNorm(name='norm', fix_gamma=False, cudnn_off=False)
   check_consistency(sym, ctx_list_v2_2D)
   sym = mx.sym.BatchNorm(name='norm', fix_gamma=False, cudnn_off=True)
   check_consistency(sym, ctx_list_v2_2D)
-  sym = mx.sym.BatchNorm(name='norm', fix_gamma=True, cudnn_off=True)
+  sym = mx.sym.BatchNorm(name='norm', fix_gamma=True, cudnn_off=False)
   check_consistency(sym, ctx_list_v2_2D)
   sym = mx.sym.BatchNorm(name='norm', fix_gamma=True, cudnn_off=True)
   check_consistency(sym, ctx_list_v2_2D)
 
   # V2, 1D
-  sym = mx.sym.BatchNorm(name='norm', fix_gamma=False, cudnn_off=True)
+  sym = mx.sym.BatchNorm(name='norm', fix_gamma=False, cudnn_off=False)
   check_consistency(sym, ctx_list_v2_1D)
   sym = mx.sym.BatchNorm(name='norm', fix_gamma=False, cudnn_off=True)
   check_consistency(sym, ctx_list_v2_1D)
-  sym = mx.sym.BatchNorm(name='norm', fix_gamma=True, cudnn_off=True)
+  sym = mx.sym.BatchNorm(name='norm', fix_gamma=True, cudnn_off=False)
   check_consistency(sym, ctx_list_v2_1D)
   sym = mx.sym.BatchNorm(name='norm', fix_gamma=True, cudnn_off=True)
   check_consistency(sym, ctx_list_v2_1D)
@@ -331,6 +333,7 @@ def test_batchnorm_with_type():
   check_consistency(sym, ctx_list_v2_3D)
 
 
+@with_seed()
 def test_batchnorm_versions():
   def test_batchnorm_versions_helper(batchnorm_op_list, data, fix_gamma, use_global_stats):
     ctx_list = []
@@ -409,9 +412,8 @@ def test_3d_batchnorm(fix_gamma, use_global_stats):
   test_3d_batchnorm(False, True)
   test_3d_batchnorm(True,  True)
 
-
+@with_seed(1234)
 def test_convolution_with_type():
-    np.random.seed(1234)
     sym1 = mx.sym.Convolution(num_filter=3, kernel=(3,3), name='conv')
 
     data = mx.sym.Variable('conv_data')
@@ -450,6 +452,7 @@ def check_consistency_NxM(sym_list, ctx_list):
     # sym_list=[sym1, sym1, sym1, sym2, sym2, sym2] and ctx_list=[ctx1, ctx2, ctx3, ctx1, ctx2, ctx3]
     check_consistency(np.repeat(sym_list, len(ctx_list)), ctx_list * len(sym_list))
 
+@with_seed()
 def test_convolution_options():
     # 1D convolution
     ctx_list = [{'ctx': mx.gpu(0), 'conv_data': (2, 2, 7), 'type_dict': {'conv_data': np.float64}},
@@ -515,6 +518,7 @@ def test_convolution_options():
     sym_no_cudnn = mx.sym.Convolution(num_filter=3, kernel=(1,1,1), pad=(0,0,0), cudnn_off=True, name='conv')
     check_consistency_NxM([sym, sym_no_cudnn], ctx_list)
 
+@with_seed()
 def test_convolution_versions():
     # 2D convolution NCHW
     ctx_list = [{'ctx': mx.cpu(0), 'conv_data': (2, 2, 7, 7), 'type_dict': {'conv_data': np.float32}},
@@ -540,6 +544,7 @@ def test_convolution_versions():
     syms = [conv_cudnn, conv_cpu, conv_gpu]
     check_consistency(syms, ctx_list)
 
+@with_seed()
 def test_pooling_with_type():
     ctx_list = [{'ctx': mx.gpu(0), 'pool_data': (2, 2, 10, 10), 'type_dict': {'pool_data': np.float64}},
                 {'ctx': mx.gpu(0), 'pool_data': (2, 2, 10, 10), 'type_dict': {'pool_data': np.float32}},
@@ -555,6 +560,7 @@ def test_pooling_with_type():
     sym = mx.sym.Pooling(kernel=(300,300), pool_type='max', global_pool=True, name='pool')
     check_consistency(sym, ctx_list)
 
+@with_seed()
 def test_deconvolution_with_type():
     sym = mx.sym.Deconvolution(num_filter=2, kernel=(3,3), name='deconv')
     ctx_list = [{'ctx': mx.gpu(0), 'deconv_data': (2, 2, 10, 10), 'type_dict': {'deconv_data': np.float64}},
@@ -571,6 +577,7 @@ def test_deconvolution_with_type():
     check_consistency(sym, ctx_list, tol=tol)
     check_consistency(sym, ctx_list, tol=tol, grad_req="add")
 
+@with_seed()
 def test_deconvolution_options():
 
 #    # 1D convolution  (not yet enabled)
@@ -625,8 +632,8 @@ def test_deconvolution_options():
 #    sym_no_cudnn = mx.sym.Convolution(num_filter=3, kernel=(2,3,3), stride=(2,2,2), cudnn_off=True, name='conv')
 #    check_consistency_NxM([sym, sym_no_cudnn], ctx_list)
 
+@with_seed(1234)
 def test_bilinear_sampler_with_type():
-    np.random.seed(1234)
     data = mx.sym.Variable('data')
     grid = mx.sym.Variable('grid')
     sym = mx.sym.BilinearSampler(data=data, grid=grid)
@@ -643,6 +650,7 @@ def test_bilinear_sampler_with_type():
     check_consistency(sym, ctx_list)
     check_consistency(sym, ctx_list, grad_req="add")
 
+@with_seed()
 def test_grid_generator_with_type():
     data = mx.sym.Variable('data')
     sym = mx.sym.GridGenerator(data=data, transform_type='affine', target_shape=(20, 20))
@@ -657,8 +665,8 @@ def test_grid_generator_with_type():
     check_consistency(sym, ctx_list, grad_req="add")
 
 @unittest.skip("test fails intermittently. temporarily disabled till it gets fixed. tracked at https://github.com/apache/incubator-mxnet/issues/7645")
+@with_seed(1234)
 def test_spatial_transformer_with_type():
-    np.random.seed(1234)
     data = mx.sym.Variable('data')
     loc = mx.sym.Flatten(data)
     loc = mx.sym.FullyConnected(data=loc, num_hidden=10)
@@ -674,8 +682,8 @@ def test_spatial_transformer_with_type():
 # Checking max pooling consistency over the data sets of different float types is problematic
 # as one max value in a float32 data set may not be the max value in a float16 data set.
 # This function will not be called.
+@with_seed(1234)
 def test_pooling_with_type():
-    np.random.seed(1234)
     ctx_list = [{'ctx': mx.gpu(0), 'pool_data': (10, 2, 10, 10), 'type_dict': {'pool_data': np.float64}},
                 {'ctx': mx.gpu(0), 'pool_data': (10, 2, 10, 10), 'type_dict': {'pool_data': np.float32}},
                 {'ctx': mx.gpu(0), 'pool_data': (10, 2, 10, 10), 'type_dict': {'pool_data': np.float16}},
@@ -696,6 +704,7 @@ def test_pooling_with_type():
     check_consistency(sym, ctx_list)
 
 
+@with_seed()
 def test_pooling_versions():
     def test_pooling_versions_helper(pool_op_list, data, kernel, pool_type, pad, stride,
                                      pooling_convention='valid', global_pool=False):
@@ -853,6 +862,7 @@ def test_3d_pooling(pool_type):
     test_3d_pooling('sum')
 
 
+@with_seed()
 def test_upsampling_with_type():
     sym = mx.sym.UpSampling(scale=2, num_filter=2, name='up', sample_type='nearest', num_args=1)
     ctx_list = [{'ctx': mx.gpu(0), 'up_arg0': (2, 2, 2, 10), 'type_dict': {'up_arg0': np.float64}},
@@ -863,6 +873,7 @@ def test_upsampling_with_type():
     check_consistency(sym, ctx_list)
 
 
+@with_seed()
 def test_upsampling_bilinear_with_type():
     sym = mx.sym.UpSampling(scale=2, num_filter=2, name='up', sample_type='bilinear', num_args=1)
     ctx_list = [{'ctx': mx.gpu(0), 'up_data': (2, 2, 2, 10), 'type_dict': {'up_data': np.float64}},
@@ -873,6 +884,7 @@ def test_upsampling_bilinear_with_type():
     check_consistency(sym, ctx_list)
 
 
+@with_seed()
 def test_concat_with_type():
     sym = mx.sym.Concat(name='concat', num_args=2)
     ctx_list = [{'ctx': mx.gpu(0), 'concat_arg1': (2, 10), 'concat_arg0': (2, 10),
@@ -888,6 +900,7 @@ def test_concat_with_type():
     check_consistency(sym, ctx_list)
 
 
+@with_seed()
 def test_elementwisesum_with_type():
     dev_types = [[mx.gpu(0), [np.float64, np.float32, np.float16]],
                  [mx.cpu(0), [np.float64, np.float32]] ]
@@ -909,6 +922,7 @@ def test_elementwisesum_with_type():
     check_consistency(sym, ctx_list)
 
 
+@with_seed()
 def test_reshape_with_type():
     sym = mx.sym.Reshape(name='reshape', shape=(-1,1,1,0))
     ctx_list = [{'ctx': mx.gpu(0), 'reshape_data': (2, 2, 2, 10), 'type_dict': {'reshape_data': np.float64}},
@@ -919,6 +933,7 @@ def test_reshape_with_type():
     check_consistency(sym, ctx_list)
 
 
+@with_seed()
 def test_blockgrad_with_type():
     sym = mx.sym.BlockGrad(name='bg')
     ctx_list = [{'ctx': mx.gpu(0), 'bg_data': (2, 2, 2, 10), 'type_dict': {'bg_data': np.float64}},
@@ -929,6 +944,7 @@ def test_blockgrad_with_type():
     check_consistency(sym, ctx_list)
 
 
+@with_seed()
 def test_swapaxis_with_type():
     sym = mx.sym.SwapAxis(name='swap', dim1=1)
     ctx_list = [{'ctx': mx.gpu(0), 'swap_data': (2, 2, 2, 10), 'type_dict': {'swap_data': np.float64}},
@@ -939,6 +955,7 @@ def test_swapaxis_with_type():
     check_consistency(sym, ctx_list)
 
 
+@with_seed()
 def test_fullyconnected_with_type():
     sym = mx.sym.FullyConnected(num_hidden=3, name='inner')
     ctx_list = [{'ctx': mx.gpu(0), 'inner_data': (2, 10), 'type_dict': {'inner_data': np.float64}},
@@ -954,6 +971,7 @@ def test_fullyconnected_with_type():
     check_consistency(sym, ctx_list)
 
 
+@with_seed()
 def test_activation_with_type():
     sym = mx.sym.Activation(name='act', act_type='sigmoid')
     ctx_list = [{'ctx': mx.gpu(0), 'act_data': (2, 2, 10, 10), 'type_dict': {'act_data': np.float64}},
@@ -965,6 +983,7 @@ def test_activation_with_type():
     check_consistency(sym, ctx_list)
 
 
+@with_seed()
 def test_embedding_with_type():
     def test_embedding_helper(data_types, weight_types, low_pad, high_pad):
         NVD = [[20, 10, 20], [200, 10, 300]]
@@ -988,17 +1007,18 @@ def test_embedding_helper(data_types, weight_types, low_pad, high_pad):
     weight_types = [np.float16, np.float32, np.float64]
     test_embedding_helper(data_types, weight_types, 0, 5)
 
+@with_seed()
 def test_svmoutput_with_type():
     sym = mx.sym.SVMOutput(name='svmoutput', use_linear=True)
-    ctx_list = [{'ctx': mx.gpu(0), 'svmoutput_data': (20, 10), 'type_dict': {'svmoutput_data': np.float64}},
-                {'ctx': mx.gpu(0), 'svmoutput_data': (20, 10), 'type_dict': {'svmoutput_data': np.float32}},
-                {'ctx': mx.gpu(0), 'svmoutput_data': (20, 10), 'type_dict': {'svmoutput_data': np.float16}},
-                {'ctx': mx.cpu(0), 'svmoutput_data': (20, 10), 'type_dict': {'svmoutput_data': np.float64}},
-                {'ctx': mx.cpu(0), 'svmoutput_data': (20, 10), 'type_dict': {'svmoutput_data': np.float32}},
-                {'ctx': mx.cpu(0), 'svmoutput_data': (20, 10), 'type_dict': {'svmoutput_data': np.float16}}]
-    check_consistency(sym, ctx_list)
+    # While the float32 and float64 output is reliably consistent, float16 departs occasionally.
+    # We compare cpu and gpu results only within a given precision.
+    for data_type in [np.float64, np.float32, np.float16]:
+        ctx_list = [{'ctx': mx.gpu(0), 'svmoutput_data': (20, 10), 'type_dict': {'svmoutput_data': data_type}},
+                    {'ctx': mx.cpu(0), 'svmoutput_data': (20, 10), 'type_dict': {'svmoutput_data': data_type}}]
+        check_consistency(sym, ctx_list)
 
 
+@with_seed()
 def test_take_with_type():
     sym = mx.sym.take(name='take')
     for data_ndim in range(2, 5):
@@ -1068,6 +1088,7 @@ def check_rnn_consistency(cell1, cell2):
     assert_allclose(mod1.get_outputs()[0].asnumpy(), mod2.get_outputs()[0].asnumpy(), rtol=1e-2, atol=1e-4)
 
 
+@with_seed()
 def test_rnn():
     fused = mx.rnn.FusedRNNCell(100, num_layers=2, mode='rnn_relu', prefix='')
 
@@ -1079,6 +1100,7 @@ def test_rnn():
     check_rnn_consistency(stack, fused)
 
 
+@with_seed()
 def test_lstm():
     fused = mx.rnn.FusedRNNCell(100, num_layers=2, mode='lstm', prefix='')
 
@@ -1090,6 +1112,7 @@ def test_lstm():
     check_rnn_consistency(stack, fused)
 
 
+@with_seed()
 def test_lstm_forget_bias():
     forget_bias = 2.0
     fused = mx.rnn.FusedRNNCell(10, forget_bias=forget_bias, num_layers=2, mode='lstm', prefix='')
@@ -1111,6 +1134,7 @@ def test_lstm_forget_bias():
     assert_allclose(args[bias_name].asnumpy(), expected_bias)
 
 
+@with_seed()
 def test_gru():
     fused = mx.rnn.FusedRNNCell(100, num_layers=2, mode='gru', prefix='')
 
@@ -1122,6 +1146,7 @@ def test_gru():
     check_rnn_consistency(stack, fused)
 
 
+@with_seed()
 def test_bidirectional():
     fused = mx.rnn.FusedRNNCell(100, num_layers=2, mode='gru', prefix='',
             bidirectional=True)
@@ -1139,6 +1164,7 @@ def test_bidirectional():
     check_rnn_consistency(fused, stack)
     check_rnn_consistency(stack, fused)
 
+@with_seed()
 def test_unfuse():
     for mode in ['rnn_tanh', 'rnn_relu', 'lstm', 'gru']:
         fused = mx.rnn.FusedRNNCell(
@@ -1152,8 +1178,8 @@ def test_unfuse():
         check_rnn_consistency(fused, stack)
         check_rnn_consistency(stack, fused)
 
+@with_seed(1234)
 def test_psroipooling_with_type():
-    np.random.seed(1234)
     arg_params = {
         'psroipool_rois': np.array([[0, 10, 22, 161, 173], [0, 20, 15, 154, 160]])}
 
@@ -1176,8 +1202,8 @@ def test_psroipooling_with_type():
     check_consistency(sym, ctx_list, grad_req={'psroipool_data': 'write',
                                                'psroipool_rois': 'null'}, arg_params=arg_params)
 
+@with_seed(1234)
 def test_deformable_psroipooling_with_type():
-    np.random.seed(1234)
     arg_params = {
         'deformable_psroipool_rois': np.array([[0, 10, 22, 161, 173], [0, 20, 15, 154, 160]])}
 
@@ -1209,8 +1235,8 @@ def test_deformable_psroipooling_with_type():
                                                'deformable_psroipool_rois': 'null',
                                                'deformable_psroipool_trans': 'write'}, arg_params=arg_params)
 
+@with_seed(1234)
 def test_deformable_convolution_with_type():
-    np.random.seed(1234)
     sym = mx.sym.contrib.DeformableConvolution(num_filter=3, kernel=(3,3), name='deformable_conv')
     # since atomicAdd does not support fp16 (which deformable conv uses in backward), we do not test fp16 here
     ctx_list = [{'ctx': mx.gpu(0),
@@ -1238,6 +1264,8 @@ def test_deformable_convolution_with_type():
                                                'deformable_conv_offset': 'write',
                                                'deformable_conv_weight': 'write',
                                                'deformable_conv_bias': 'null'}, tol=tol)
+
+@with_seed()
 def test_deformable_convolution_options():
     # 2D convolution
 
@@ -1313,6 +1341,7 @@ def test_deformable_convolution_options():
     sym = mx.sym.contrib.DeformableConvolution(num_filter=4, kernel=(3,3), num_deformable_group=2,
                                                name='deformable_conv')
 
+@with_seed()
 def test_residual_fused():
     cell = mx.rnn.ResidualCell(
             mx.rnn.FusedRNNCell(50, num_layers=3, mode='lstm',
@@ -1349,6 +1378,7 @@ def check_rnn_layer(layer):
         assert_almost_equal(g.asnumpy(), c.asnumpy(), rtol=1e-2, atol=1e-8)
 
 
+@with_seed()
 def test_rnn_layer():
     check_rnn_layer(gluon.rnn.RNN(100, num_layers=3))
     check_rnn_layer(gluon.rnn.RNN(100, activation='tanh', num_layers=3))
@@ -1358,10 +1388,12 @@ def test_rnn_layer():
     check_rnn_layer(gluon.rnn.LSTM(100, num_layers=3, bidirectional=True))
 
 
+@with_seed()
 def test_sequence_reverse():
     check_sequence_reverse(mx.gpu(0))
 
 @unittest.skip("Test fails intermittently. Temporarily disabled until fixed. Tracked at https://github.com/apache/incubator-mxnet/issues/8211")
+@with_seed()
 def test_autograd_save_memory():
     x = mx.nd.zeros((128, 512, 512), ctx=mx.gpu(0))
     x.attach_grad()
@@ -1372,6 +1404,7 @@ def test_autograd_save_memory():
             x.wait_to_read()
     x.backward()
 
+@with_seed()
 def test_gluon_ctc_consistency():
     loss = mx.gluon.loss.CTCLoss()
     data = mx.nd.arange(0, 4, repeat=40, ctx=mx.gpu(0)).reshape((2,20,4)).flip(axis=0)
@@ -1393,6 +1426,7 @@ def test_gluon_ctc_consistency():
     assert_almost_equal(cpu_data.grad.asnumpy(), gpu_data.grad.asnumpy(), atol=1e-3, rtol=1e-3)
 
 
+@with_seed()
 def test_cuda_rtc():
     source = r'''
     extern "C" __global__ void axpy(const float *x, float *y, float alpha) {
@@ -1422,6 +1456,7 @@ def test_cuda_rtc():
     assert (y.asnumpy() == 12).all()
 
 
+@with_seed()
 def test_cross_device_autograd():
     x = mx.nd.random.uniform(shape=(10,))
     x.attach_grad()
diff --git a/tests/python/unittest/common.py b/tests/python/unittest/common.py
index 12ed60d2bc..d1738a6024 100644
--- a/tests/python/unittest/common.py
+++ b/tests/python/unittest/common.py
@@ -15,13 +15,17 @@
 # specific language governing permissions and limitations
 # under the License.
 
-import sys, os
+import sys, os, logging
+import mxnet as mx
+import numpy as np
 curr_path = os.path.dirname(os.path.abspath(os.path.expanduser(__file__)))
 sys.path.append(os.path.join(curr_path, '../common/'))
 sys.path.insert(0, os.path.join(curr_path, '../../../python'))
 
 import models
 import get_data
+from contextlib import contextmanager
+from nose.tools import make_decorator
 
 
 def assertRaises(expected_exception, func, *args, **kwargs):
@@ -32,3 +36,185 @@ def assertRaises(expected_exception, func, *args, **kwargs):
     else:
         # Did not raise exception
         assert False, "%s did not raise %s" % (func.__name__, expected_exception.__name__)
+
+def default_logger():
+    """A logger used to output seed information to nosetests logs."""
+    logger = logging.getLogger(__name__)
+    # getLogger() lookups will return the same logger, but only add the handler once.
+    if not len(logger.handlers):
+        handler = logging.StreamHandler(sys.stderr)
+        handler.setFormatter(logging.Formatter('[%(levelname)s] %(message)s'))
+        logger.addHandler(handler)
+        if (logger.getEffectiveLevel() == logging.NOTSET):
+            logger.setLevel(logging.INFO)
+    return logger
+
+@contextmanager
+def random_seed(seed=None):
+    """
+    Runs a code block with a new seed for both np and mx random.
+
+    Parameters
+    ----------
+
+    seed : the seed to pass to np.random and mx.random
+
+    To impose rng determinism, invoke e.g. as in:
+
+    with random_seed(1234):
+        ...
+
+    To impose rng non-determinism, invoke as in:
+
+    with random_seed():
+        ...
+
+    Upon conclusion of the block, the rng's are returned to
+    a state that is a function of their pre-block state, so
+    any prior non-determinism is preserved.
+
+    """
+
+    try:
+        next_seed = np.random.randint(0, np.iinfo(np.int32).max)
+        logger = default_logger()
+        logger.info('Setting np and mx random seeds = %s', seed)
+        np.random.seed(seed)
+        mx.random.seed(seed)
+        yield
+    finally:
+        # Reinstate prior state of np.random
+        np.random.seed(next_seed)
+        mx.random.seed(next_seed)
+
+
+def with_seed(seed=None):
+    """
+    A decorator for nosetests test functions that manages rng seeds.
+
+    Parameters
+    ----------
+
+    seed : the seed to pass to np.random and mx.random
+
+
+    This tests decorator sets the np and mx random seeds identically
+    prior to each test, then outputs those seeds if the test fails or
+    if the test requires a fixed seed (as a reminder to make the test
+    more robust against random data).
+
+    @with_seed()
+    def test_ok_with_random_data():
+        ...
+
+    @with_seed(1234)
+    def test_not_ok_with_random_data():
+        ...
+
+    Use of the @with_seed() decorator for all tests creates
+    tests isolation and reproducability of failures.  When a
+    test fails, the decorator outputs the seed used.  The user
+    can then set the environment variable MXNET_RANDOM_SEED to
+    the value reported, then rerun the test with:
+
+        nosetests --verbose -s <test_module_name.py>:<failing_test>
+
+    To run a test repeatedly, set MXNET_TEST_COUNT=<NNN> in the environment.
+    To see the seeds of even the passing tests, add '--logging-level=DEBUG' to nosetests.
+    """
+    def test_helper(orig_test):
+        @make_decorator(orig_test)
+        def test_new(*args, **kwargs):
+            test_count = int(os.getenv('MXNET_TEST_COUNT', '1'))
+            env_seed_str = os.getenv('MXNET_TEST_SEED')
+            for _ in range(test_count):
+                if seed is not None:
+                    this_test_seed = seed
+                    print_seed = True
+                elif env_seed_str is not None:
+                    this_test_seed = int(env_seed_str)
+                    print_seed = True
+                else:
+                    this_test_seed = np.random.randint(0, np.iinfo(np.int32).max)
+                    print_seed = False
+                post_test_state = np.random.get_state()
+                np.random.seed(this_test_seed)
+                mx.random.seed(this_test_seed)
+                logger = default_logger()
+                # 'nosetests --logging-level=DEBUG' shows this msg even with a core dump.
+                logger.debug(('Setting test np/mx random seeds, '
+                              'use MXNET_TEST_SEED=%s to reproduce.'), this_test_seed)
+                try:
+                    orig_test(*args, **kwargs)
+                except:
+                    print_seed = True
+                    raise
+                finally:
+                    if print_seed:
+                        logger.info(('Setting test np/mx random seeds, '
+                                     'use MXNET_TEST_SEED=%s to reproduce.'), this_test_seed)
+                    np.random.set_state(post_test_state)
+        return test_new
+    return test_helper
+
+def setup_module():
+    """
+    A function with a 'magic name' executed automatically before each nosetests module
+    (file of tests) that helps reproduce a test segfault by setting and outputting the rng seeds.
+
+    The segfault-debug procedure on a module called test_module.py is:
+
+    1. run "nosetests --verbose test_module.py".  A seg-faulting output might be:
+
+       [INFO] np and mx random seeds = 4018804151
+       test_module.test1 ... ok
+       test_module.test2 ... Illegal instruction (core dumped)
+
+    2. Copy the module-starting seed into the next command, then run:
+
+       MXNET_MODULE_SEED=4018804151 nosetests --logging-level=DEBUG --verbose test_module.py
+
+       Output might be:
+
+       [WARNING] **** module-level seed is set: all tests running deterministically ****
+       [INFO] np and mx random seeds = 4018804151
+       test_module.test1 ... [DEBUG] np and mx random seeds = 3935862516
+       ok
+       test_module.test2 ... [DEBUG] np and mx random seeds = 1435005594
+       Illegal instruction (core dumped)
+
+    3. Copy the segfaulting-test seed into the command:
+       MXNET_TEST_SEED=1435005594 nosetests --logging-level=DEBUG --verbose test_module.py:test2
+       Output might be:
+
+       [INFO] np and mx random seeds = 2481884723
+       test_module.test2 ... [DEBUG] np and mx random seeds = 1435005594
+       Illegal instruction (core dumped)
+
+    3. Finally reproduce the segfault directly under gdb (might need additional os packages)
+       by editing the bottom of test_module.py to be
+
+       if __name__ == '__main__':
+           logging.getLogger().setLevel(logging.DEBUG)
+           test2()
+
+       gdb -ex r --args python test_module.py
+
+    4. When finished debugging the segfault, remember to unset any exported MXNET_ seed
+       variables in the environment to return to non-deterministic testing (a good thing).
+    """
+
+    module_seed_str = os.getenv('MXNET_MODULE_SEED')
+    logger = default_logger()
+    if module_seed_str is None:
+        seed = np.random.randint(0, np.iinfo(np.int32).max)
+    else:
+        seed = int(module_seed_str)
+        logger.warn('*** module-level seed is set: all tests running deterministically ***')
+    logger.info('Setting module np/mx random seeds, use MXNET_MODULE_SEED=%s to reproduce.', seed)
+    np.random.seed(seed)
+    mx.random.seed(seed)
+    # The MXNET_TEST_SEED environment variable will override MXNET_MODULE_SEED for tests with
+    #  the 'with_seed()' decoration.  Inform the user of this once here at the module level.
+    if os.getenv('MXNET_TEST_SEED') is not None:
+        logger.warn('*** test-level seed set: all "@with_seed()" tests run deterministically ***')
diff --git a/tests/python/unittest/test_autograd.py b/tests/python/unittest/test_autograd.py
index c95ccdf299..ad062f8e6b 100644
--- a/tests/python/unittest/test_autograd.py
+++ b/tests/python/unittest/test_autograd.py
@@ -20,6 +20,7 @@
 from mxnet.ndarray import zeros_like
 from mxnet.autograd import *
 from mxnet.test_utils import *
+from common import *
 
 
 def grad_and_loss(func, argnum=None):
@@ -105,6 +106,7 @@ def autograd_assert(*args, **kwargs):
     for a, b in zip(grad_vals, grad_res):
         assert same(a.asnumpy(), b.asnumpy())
 
+@with_seed()
 def test_unary_func():
     def check_unary_func(x):
         f_exp         = lambda x: nd.exp(x)
@@ -121,6 +123,7 @@ def check_unary_func(x):
     for stype in stypes:
         check_unary_func(uniform.tostype(stype))
 
+@with_seed()
 def test_binary_func():
     def check_binary_func(x, y):
         f_add      = lambda x, y: x+y
@@ -142,6 +145,7 @@ def check_binary_func(x, y):
             check_binary_func(x, y)
 
 
+@with_seed()
 def test_operator_with_state():
     def f_fc(a, b, weight, bias):
         x = a*b
@@ -158,6 +162,7 @@ def f_fc(a, b, weight, bias):
     grad_vals, outputs = grad_func(a, b, weight, bias)
     # (TODO) assert
 
+@with_seed()
 def test_argnum():
     def f_with_mode(a, b, mode):
         if mode:
@@ -175,6 +180,7 @@ def f_with_mode(a, b, mode):
         argnum=[0, 1], func=f_with_mode, grad_func=f_mul_grad)
 
 
+@with_seed()
 def test_training():
     x = nd.ones((10, 10))
     with record():
@@ -185,6 +191,7 @@ def test_training():
             assert (y.asnumpy() == x.asnumpy()).all()
 
 
+@with_seed()
 def test_out_grads():
     x = nd.ones((3, 5))
     dx = nd.zeros_like(x)
@@ -203,6 +210,7 @@ def test_out_grads():
          [5,4,3,2,1]])).all()
 
 
+@with_seed()
 def test_detach_updated_grad():
     x = nd.ones((2, 2))
     dx = nd.zeros_like(x)
@@ -235,6 +243,7 @@ def test_detach_updated_grad():
     assert x._fresh_grad == False
 
 
+@with_seed()
 def test_retain_grad():
     x = mx.nd.ones((2, 2))
     dx = mx.nd.zeros((2, 2))
@@ -266,6 +275,7 @@ def test_retain_grad():
         "differentiating the same graph twice without retain_graph should fail")
 
 
+@with_seed()
 def test_attach_grad():
     def check_attach_grad(x):
         assert x.grad is None
@@ -282,6 +292,7 @@ def check_attach_grad(x):
         check_attach_grad(x)
 
 
+@with_seed()
 def test_is_train():
     x = mx.nd.ones((10, 10))
     x.attach_grad()
@@ -329,6 +340,7 @@ def test_is_train():
         assert y.asnumpy().max() == 2 and y.asnumpy().min() == 0
 
 
+@with_seed()
 def test_function():
     class func(Function):
         def forward(self, x, y):
@@ -358,10 +370,12 @@ def backward(self, dm, dn):
     with record():
         backward([x/y, x*y])
 
-    assert_almost_equal(x.grad.asnumpy(), dx1)
-    assert_almost_equal(y.grad.asnumpy(), dy1)
+    atol = 1e-6
+    assert_almost_equal(x.grad.asnumpy(), dx1, atol=atol)
+    assert_almost_equal(y.grad.asnumpy(), dy1, atol=atol)
 
 
+@with_seed()
 def test_get_symbol():
     x = mx.nd.ones((1,))
     x.attach_grad()
@@ -375,6 +389,7 @@ def test_get_symbol():
         y = x*x + 2*z - 1
     assert len(get_symbol(y).list_arguments()) == 2
 
+@with_seed()
 def test_grad_with_stype():
     def check_grad_with_stype(array_stype, grad_stype, expected_stype):
         x = mx.nd.zeros((1, 1), stype=array_stype)
@@ -393,6 +408,7 @@ def check_grad_with_stype(array_stype, grad_stype, expected_stype):
             # check the stype of the gradient when provided
             check_grad_with_stype(stype, grad_stype, grad_stype)
 
+@with_seed()
 def test_sparse_dot_grad():
     def check_sparse_dot_grad(rhs):
         lhs = rand_ndarray((2, 8), 'csr')
@@ -415,6 +431,7 @@ def check_sparse_dot_grad(rhs):
     dns.attach_grad(stype='row_sparse')
     check_sparse_dot_grad(dns)
 
+@with_seed()
 def test_gradient():
     x = mx.nd.ones((1,))
     x.attach_grad()
diff --git a/tests/python/unittest/test_contrib_autograd.py b/tests/python/unittest/test_contrib_autograd.py
index a144c34332..9b8e28c695 100644
--- a/tests/python/unittest/test_contrib_autograd.py
+++ b/tests/python/unittest/test_contrib_autograd.py
@@ -18,6 +18,7 @@
 import mxnet.ndarray as nd
 from mxnet.contrib.autograd import *
 from mxnet.test_utils import *
+from common import *
 
 def autograd_assert(*args, **kwargs):
     func   = kwargs["func"]
@@ -33,6 +34,7 @@ def autograd_assert(*args, **kwargs):
     for a, b in zip(grad_vals, grad_res):
         assert same(a.asnumpy(), b.asnumpy())
 
+@with_seed()
 def test_unary_func():
     x = nd.uniform(shape=(4, 5))
     f_exp         = lambda x: nd.exp(x)
@@ -45,6 +47,7 @@ def test_unary_func():
     f_square_grad = lambda x: [2*x]
     autograd_assert(x, func=f_square, grad_func=f_square_grad)
 
+@with_seed()
 def test_binary_func():
     x = nd.uniform(shape=(4, 5))
     y = nd.uniform(shape=(4, 5))
@@ -58,6 +61,7 @@ def test_binary_func():
     f_compose_grad = lambda x, y: [nd.ones(x.shape) + y, x]
     autograd_assert(x, y, func=f_compose, grad_func=f_compose_grad)
 
+@with_seed()
 def test_operator_with_state():
     def f_fc(a, b, weight, bias):
         x = a*b
@@ -74,6 +78,7 @@ def f_fc(a, b, weight, bias):
     grad_vals, outputs = grad_func(a, b, weight, bias)
     # (TODO) assert
 
+@with_seed()
 def test_argnum():
     def f_with_mode(a, b, mode):
         if mode:
@@ -91,6 +96,7 @@ def f_with_mode(a, b, mode):
         argnum=[0, 1], func=f_with_mode, grad_func=f_mul_grad)
 
 
+@with_seed()
 def test_training():
     x = nd.ones((10, 10))
     with train_section():
@@ -101,6 +107,7 @@ def test_training():
             assert (y.asnumpy() == x.asnumpy()).all()
 
 
+@with_seed()
 def test_out_grads():
     x = nd.ones((3, 5))
     dx = nd.zeros_like(x)
@@ -119,6 +126,7 @@ def test_out_grads():
          [5,4,3,2,1]])).all()
 
 
+@with_seed()
 def test_detach_updated_grad():
     x = nd.ones((2, 2))
     dx = nd.zeros_like(x)
@@ -151,6 +159,7 @@ def test_detach_updated_grad():
     assert x._fresh_grad == False
 
 
+@with_seed()
 def test_retain_grad():
     x = mx.nd.ones((2, 2))
     dx = mx.nd.zeros((2, 2))
diff --git a/tests/python/unittest/test_executor.py b/tests/python/unittest/test_executor.py
index e3d977df65..d6be21aa2a 100644
--- a/tests/python/unittest/test_executor.py
+++ b/tests/python/unittest/test_executor.py
@@ -17,6 +17,7 @@
 
 import numpy as np
 import mxnet as mx
+from common import *
 
 
 def reldiff(a, b):
@@ -77,12 +78,12 @@ def check_bind_with_uniform(uf, gf, dim, sf=None, lshape=None, rshape=None):
     assert reldiff(rhs_grad.asnumpy(), rhs_grad2) < 1e-6
 
 
+@with_seed(0)
 def test_bind(disable_bulk_exec=False):
     if disable_bulk_exec:
         prev_bulk_inf_val = mx.test_utils.set_env_var("MXNET_EXEC_BULK_EXEC_INFERENCE", "0", "1")
         prev_bulk_train_val = mx.test_utils.set_env_var("MXNET_EXEC_BULK_EXEC_TRAIN", "0", "1")
 
-    np.random.seed(0)
     nrepeat = 10
     maxdim = 4
     for repeat in range(nrepeat):
@@ -112,8 +113,8 @@ def test_bind(disable_bulk_exec=False):
        mx.test_utils.set_env_var("MXNET_EXEC_BULK_EXEC_INFERENCE", prev_bulk_inf_val)
        mx.test_utils.set_env_var("MXNET_EXEC_BULK_EXEC_TRAIN", prev_bulk_train_val)
 
+@with_seed(0)
 def test_dot():
-    np.random.seed(0)
     nrepeat = 10
     maxdim = 4
     for repeat in range(nrepeat):
@@ -133,7 +134,7 @@ def test_dot():
                                 rshape=(s[0],),
                                 sf = mx.symbol.dot)
 
-
+@with_seed()
 def test_reshape():
     x = mx.sym.Variable('x')
     y = mx.sym.FullyConnected(x, num_hidden=4)
diff --git a/tests/python/unittest/test_gluon.py b/tests/python/unittest/test_gluon.py
index df0af34dfe..43c45eb7b6 100644
--- a/tests/python/unittest/test_gluon.py
+++ b/tests/python/unittest/test_gluon.py
@@ -19,12 +19,14 @@
 from mxnet import gluon
 from mxnet.gluon import nn
 from mxnet.test_utils import assert_almost_equal
+from common import *
 import numpy as np
 from nose.tools import raises
 from copy import deepcopy
 import warnings
 
 
+@with_seed()
 def test_parameter():
     p = gluon.Parameter('weight', shape=(10, 10))
     p.initialize(init='xavier', ctx=[mx.cpu(0), mx.cpu(1)])
@@ -38,6 +40,7 @@ def test_parameter():
     assert p.list_ctx() == [mx.cpu(1), mx.cpu(2)]
 
 
+@with_seed()
 def test_paramdict():
     params = gluon.ParameterDict('net_')
     params.get('weight', shape=(10, 10))
@@ -47,6 +50,7 @@ def test_paramdict():
     params.load('test.params', mx.cpu())
 
 
+@with_seed()
 def test_parameter_sharing():
     class Net(gluon.Block):
         def __init__(self, **kwargs):
@@ -69,6 +73,7 @@ def forward(self, x):
     net3.load_params('net1.params', mx.cpu())
 
 
+@with_seed()
 def test_basic():
     model = nn.Sequential()
     model.add(nn.Dense(128, activation='tanh', in_units=10, flatten=False))
@@ -94,6 +99,7 @@ def test_basic():
     assert list(model.collect_params().values())[0]._grad is not None
 
 
+@with_seed()
 def test_dense():
     model = nn.Dense(128, activation='tanh', in_units=10, flatten=False, prefix='test_')
     inputs = mx.sym.Variable('data')
@@ -112,6 +118,7 @@ def test_dense():
     assert outs == [(17, 128)]
 
 
+@with_seed()
 def test_symbol_block():
     model = nn.HybridSequential()
     model.add(nn.Dense(128, activation='tanh'))
@@ -175,6 +182,7 @@ def check_layer_forward(layer, dshape):
     mx.test_utils.assert_almost_equal(np_out, out.asnumpy(), rtol=1e-5, atol=1e-6)
     mx.test_utils.assert_almost_equal(np_dx, x.grad.asnumpy(), rtol=1e-5, atol=1e-6)
 
+@with_seed()
 def test_conv():
     layers1d = [
         nn.Conv1D(16, 3, in_channels=4),
@@ -215,6 +223,7 @@ def test_conv():
     # check_layer_forward(layer, (1, 10, 10, 10, 4))
 
 
+@with_seed()
 def test_deconv():
     # layers1d = [
     #     nn.Conv1DTranspose(16, 3, in_channels=4),
@@ -257,6 +266,7 @@ def test_deconv():
 
 
 
+@with_seed()
 def test_pool():
     layers1d = [
         nn.MaxPool1D(),
@@ -300,11 +310,13 @@ def test_pool():
     layer.collect_params().initialize()
     assert (layer(x).shape==(2, 2, 4, 4))
 
+@with_seed()
 def test_batchnorm():
     layer = nn.BatchNorm(in_channels=10)
     check_layer_forward(layer, (2, 10, 10, 10))
 
 
+@with_seed()
 def test_reshape():
     x = mx.nd.ones((2, 4, 10, 10))
     layer = nn.Conv2D(10, 2, in_channels=4)
@@ -316,6 +328,7 @@ def test_reshape():
     x.backward()
 
 
+@with_seed()
 def test_slice():
     x = mx.nd.ones((5, 4, 10, 10))
     layer = nn.Conv2D(10, 2, in_channels=4)
@@ -327,6 +340,7 @@ def test_slice():
     x.backward()
 
 
+@with_seed()
 def test_at():
     x = mx.nd.ones((5, 4, 10, 10))
     layer = nn.Conv2D(10, 2, in_channels=4)
@@ -338,6 +352,7 @@ def test_at():
     x.backward()
 
 
+@with_seed()
 def test_deferred_init():
     x = mx.nd.ones((5, 4, 10, 10))
     layer = nn.Conv2D(10, 2)
@@ -352,6 +367,7 @@ def check_split_data(x, num_slice, batch_axis, **kwargs):
                                       x.asnumpy())
 
 
+@with_seed()
 def test_split_data():
     x = mx.nd.random.uniform(shape=(128, 33, 64))
 
@@ -366,6 +382,7 @@ def test_split_data():
     assert False, "Should have failed"
 
 
+@with_seed()
 def test_flatten():
     flatten = nn.Flatten()
     x = mx.nd.zeros((3,4,5,6))
@@ -376,6 +393,7 @@ def test_flatten():
     assert flatten(x).shape == (3, 1)
 
 
+@with_seed()
 def test_trainer():
     def dict_equ(a, b):
         assert set(a) == set(b)
@@ -415,6 +433,7 @@ def dict_equ(a, b):
         assert trainer._optimizer == trainer._updaters[0].optimizer
 
 
+@with_seed()
 def test_block_attr_hidden():
     b = gluon.Block()
 
@@ -423,6 +442,7 @@ def test_block_attr_hidden():
     b.a = 1
 
 @raises(TypeError)
+@with_seed()
 def test_block_attr_block():
     b = gluon.Block()
 
@@ -431,6 +451,7 @@ def test_block_attr_block():
     b.b = (2,)
 
 @raises(TypeError)
+@with_seed()
 def test_block_attr_param():
     b = gluon.Block()
 
@@ -438,6 +459,7 @@ def test_block_attr_param():
     b.b = gluon.Parameter()
     b.b = (2,)
 
+@with_seed()
 def test_block_attr_regular():
     b = gluon.Block()
 
@@ -447,13 +469,17 @@ def test_block_attr_regular():
     b.c = c2
     assert b.c is c2 and b._children[0] is c2
 
+@with_seed()
 def test_sequential_warning():
     with warnings.catch_warnings(record=True) as w:
+        # The following line permits the test to pass if run multiple times
+        warnings.simplefilter('always')
         b = gluon.nn.Sequential()
         b.add(gluon.nn.Dense(20))
         b.hybridize()
         assert len(w) == 1
 
+@with_seed()
 def test_global_norm_clip():
     x1 = mx.nd.ones((3,3))
     x2 = mx.nd.ones((4,4))
@@ -469,6 +495,7 @@ def test_global_norm_clip():
         assert len(w) == 1
 
 
+@with_seed()
 def test_embedding():
     layer = gluon.nn.Embedding(10, 100)
     layer.initialize()
@@ -480,6 +507,7 @@ def test_embedding():
     assert (layer.weight.grad()[5:] == 0).asnumpy().all()
 
 
+@with_seed()
 def test_export():
     ctx = mx.context.current_context()
     model = gluon.model_zoo.vision.resnet18_v1(
@@ -504,6 +532,7 @@ def test_export():
     assert_almost_equal(out.asnumpy(), out2.asnumpy())
 
 
+@with_seed()
 def test_hybrid_stale_cache():
     net = mx.gluon.nn.HybridSequential()
     with net.name_scope():
@@ -532,6 +561,7 @@ def test_hybrid_stale_cache():
     assert net(mx.nd.ones((2,3,5))).shape == (2, 10)
 
 
+@with_seed()
 def test_lambda():
     net1 = mx.gluon.nn.HybridSequential()
     net1.add(nn.Activation('tanh'),
diff --git a/tests/python/unittest/test_gluon_contrib.py b/tests/python/unittest/test_gluon_contrib.py
index 07b8956988..7e09670d8c 100644
--- a/tests/python/unittest/test_gluon_contrib.py
+++ b/tests/python/unittest/test_gluon_contrib.py
@@ -19,6 +19,7 @@
 import mxnet as mx
 from mxnet.gluon import contrib
 from mxnet.test_utils import almost_equal
+from common import *
 import numpy as np
 from numpy.testing import assert_allclose
 
@@ -46,6 +47,7 @@ def check_rnn_forward(layer, inputs):
     mx.nd.waitall()
 
 
+@with_seed()
 def test_rnn_cells():
     check_rnn_forward(contrib.rnn.Conv1DLSTMCell((5, 7), 10, (3,), (3,)),
                       mx.nd.ones((8, 3, 5, 7)))
@@ -61,6 +63,7 @@ def test_rnn_cells():
     check_rnn_forward(net, mx.nd.ones((8, 3, 5, 7)))
 
 
+@with_seed()
 def test_convrnn():
     cell = contrib.rnn.Conv1DRNNCell((10, 50), 100, 3, 3, prefix='rnn_')
     check_rnn_cell(cell, prefix='rnn_', in_shape=(1, 10, 50), out_shape=(1, 100, 48))
@@ -72,6 +75,7 @@ def test_convrnn():
     check_rnn_cell(cell, prefix='rnn_', in_shape=(1, 10, 20, 30, 50), out_shape=(1, 100, 18, 28, 48))
 
 
+@with_seed()
 def test_convlstm():
     cell = contrib.rnn.Conv1DLSTMCell((10, 50), 100, 3, 3, prefix='rnn_')
     check_rnn_cell(cell, prefix='rnn_', in_shape=(1, 10, 50), out_shape=(1, 100, 48))
@@ -83,6 +87,7 @@ def test_convlstm():
     check_rnn_cell(cell, prefix='rnn_', in_shape=(1, 10, 20, 30, 50), out_shape=(1, 100, 18, 28, 48))
 
 
+@with_seed()
 def test_convgru():
     cell = contrib.rnn.Conv1DGRUCell((10, 50), 100, 3, 3, prefix='rnn_')
     check_rnn_cell(cell, prefix='rnn_', in_shape=(1, 10, 50), out_shape=(1, 100, 48))
@@ -94,6 +99,7 @@ def test_convgru():
     check_rnn_cell(cell, prefix='rnn_', in_shape=(1, 10, 20, 30, 50), out_shape=(1, 100, 18, 28, 48))
 
 
+@with_seed()
 def test_conv_fill_shape():
     cell = contrib.rnn.Conv1DLSTMCell((0, 7), 10, (3,), (3,))
     cell.hybridize()
@@ -101,6 +107,7 @@ def test_conv_fill_shape():
     assert cell.i2h_weight.shape[1] == 5, cell.i2h_weight.shape[1]
 
 
+@with_seed()
 def test_vardrop():
     def check_vardrop(drop_inputs, drop_states, drop_outputs):
         cell = contrib.rnn.VariationalDropoutCell(mx.gluon.rnn.RNNCell(100, prefix='rnn_'),
diff --git a/tests/python/unittest/test_gluon_data.py b/tests/python/unittest/test_gluon_data.py
index 341e6d1716..7e0575e529 100644
--- a/tests/python/unittest/test_gluon_data.py
+++ b/tests/python/unittest/test_gluon_data.py
@@ -20,7 +20,9 @@
 import mxnet as mx
 import numpy as np
 from mxnet import gluon
+from common import *
 
+@with_seed()
 def test_array_dataset():
     X = np.random.uniform(size=(10, 20))
     Y = np.random.uniform(size=(10,))
@@ -48,6 +50,7 @@ def prepare_record():
     return 'data/test.rec'
 
 
+@with_seed()
 def test_recordimage_dataset():
     recfile = prepare_record()
     dataset = gluon.data.vision.ImageRecordDataset(recfile)
@@ -57,6 +60,7 @@ def test_recordimage_dataset():
         assert x.shape[0] == 1 and x.shape[3] == 3
         assert y.asscalar() == i
 
+@with_seed()
 def test_sampler():
     seq_sampler = gluon.data.SequentialSampler(10)
     assert list(seq_sampler) == list(range(10))
@@ -69,6 +73,7 @@ def test_sampler():
     rand_batch_keep = gluon.data.BatchSampler(rand_sampler, 3, 'keep')
     assert sorted(sum(list(rand_batch_keep), [])) == list(range(10))
 
+@with_seed()
 def test_datasets():
     assert len(gluon.data.vision.MNIST(root='data/mnist')) == 60000
     assert len(gluon.data.vision.MNIST(root='data/mnist', train=False)) == 10000
@@ -80,6 +85,7 @@ def test_datasets():
     assert len(gluon.data.vision.CIFAR100(root='data/cifar100', fine_label=True)) == 50000
     assert len(gluon.data.vision.CIFAR100(root='data/cifar100', train=False)) == 10000
 
+@with_seed()
 def test_image_folder_dataset():
     prepare_record()
     dataset = gluon.data.vision.ImageFolderDataset('data/test_images')
diff --git a/tests/python/unittest/test_gluon_model_zoo.py b/tests/python/unittest/test_gluon_model_zoo.py
index 39d3b19c36..07cdafe52d 100644
--- a/tests/python/unittest/test_gluon_model_zoo.py
+++ b/tests/python/unittest/test_gluon_model_zoo.py
@@ -20,11 +20,13 @@
 from mxnet.gluon import nn
 from mxnet.gluon.model_zoo.custom_layers import HybridConcurrent, Identity
 from mxnet.gluon.model_zoo.vision import get_model
+from common import *
 import sys
 
 def eprint(*args, **kwargs):
     print(*args, file=sys.stderr, **kwargs)
 
+@with_seed()
 def test_concurrent():
     model = HybridConcurrent(concat_dim=1)
     model.add(nn.Dense(128, activation='tanh', in_units=10))
@@ -43,6 +45,7 @@ def test_concurrent():
     x.wait_to_read()
 
 
+@with_seed()
 def test_identity():
     model = Identity()
     x = mx.nd.random.uniform(shape=(128, 33, 64))
@@ -50,6 +53,7 @@ def test_identity():
                                       x.asnumpy())
 
 
+@with_seed()
 def test_models():
     all_models = ['resnet18_v1', 'resnet34_v1', 'resnet50_v1', 'resnet101_v1', 'resnet152_v1',
                   'resnet18_v2', 'resnet34_v2', 'resnet50_v2', 'resnet101_v2', 'resnet152_v2',
diff --git a/tests/python/unittest/test_image.py b/tests/python/unittest/test_image.py
index 04b878dc80..47cb0f9e8a 100644
--- a/tests/python/unittest/test_image.py
+++ b/tests/python/unittest/test_image.py
@@ -18,7 +18,7 @@
 import mxnet as mx
 import numpy as np
 from mxnet.test_utils import *
-from common import assertRaises
+from common import *
 
 
 def _get_data(url, dirname):
@@ -36,9 +36,11 @@ def _get_data(url, dirname):
 def _get_images():
     return _get_data("http://data.mxnet.io/data/test_images.tar.gz", './data')
 
+@with_seed()
 def test_init():
     _get_images()
 
+@with_seed()
 def test_imdecode():
     try:
         import cv2
@@ -52,11 +54,13 @@ def test_imdecode():
         cv_image = cv2.imread(img)
         assert_almost_equal(image.asnumpy(), cv_image)
 
+@with_seed()
 def test_scale_down():
     assert mx.image.scale_down((640, 480), (720, 120)) == (640, 106)
     assert mx.image.scale_down((360, 1000), (480, 500)) == (360, 375)
     assert mx.image.scale_down((300, 400), (0, 0)) == (0, 0)
 
+@with_seed()
 def test_resize_short():
     try:
         import cv2
@@ -79,6 +83,7 @@ def test_resize_short():
                 mx_resized = mx.image.resize_short(mx_img, new_size, interp)
                 assert_almost_equal(mx_resized.asnumpy()[:, :, (2, 1, 0)], cv_resized, atol=3)
 
+@with_seed()
 def test_color_normalize():
     for _ in range(10):
         mean = np.random.rand(3) * 255
@@ -91,6 +96,7 @@ def test_color_normalize():
         assert_almost_equal(mx_result.asnumpy(), (src - mean) / std, atol=1e-3)
 
 
+@with_seed()
 def test_imageiter():
     sources = _get_images()
     im_list = [[np.random.randint(0, 5), x] for x in sources]
@@ -115,6 +121,7 @@ def test_imageiter():
         pass
 
 
+@with_seed()
 def test_augmenters():
     # only test if all augmenters will work
     # TODO(Joshua Zhang): verify the augmenter outputs
@@ -140,6 +147,7 @@ def _generate_objects():
     label = np.hstack((cid[:, np.newaxis], boxes)).ravel().tolist()
     return [2, 5] + label
 
+@with_seed()
 def test_image_detiter():
     sources = _get_images()
     im_list = [_generate_objects() + [x] for x in sources]
@@ -165,6 +173,7 @@ def test_image_detiter():
     for batch in det_iter:
         pass
 
+@with_seed()
 def test_det_augmenters():
     # only test if all augmenters will work
     # TODO(Joshua Zhang): verify the augmenter outputs
diff --git a/tests/python/unittest/test_io.py b/tests/python/unittest/test_io.py
index f745d355db..89e2a4f4cb 100644
--- a/tests/python/unittest/test_io.py
+++ b/tests/python/unittest/test_io.py
@@ -18,6 +18,7 @@
 # pylint: skip-file
 import mxnet as mx
 from mxnet.test_utils import *
+from common import *
 import numpy as np
 import os, gzip
 import pickle as pickle
diff --git a/tests/python/unittest/test_kvstore.py b/tests/python/unittest/test_kvstore.py
index fc9e3be3c4..e3892f8779 100644
--- a/tests/python/unittest/test_kvstore.py
+++ b/tests/python/unittest/test_kvstore.py
@@ -19,7 +19,8 @@
 import mxnet as mx
 import numpy as np
 import unittest
-from mxnet.test_utils import rand_ndarray, assert_almost_equal, assert_exception
+from mxnet.test_utils import rand_ndarray, assert_almost_equal, assert_exception, discard_stderr
+from common import *
 from mxnet.base import py_str, MXNetError
 
 shape = (4, 4)
@@ -50,6 +51,7 @@ def check_diff_to_scalar(A, x):
     assert(np.sum(np.abs((A - x).asnumpy())) == 0)
 
 
+@with_seed()
 def test_single_kv_pair():
     """single key-value pair push & pull"""
     def check_single_kv_pair(kv, key):
@@ -61,6 +63,7 @@ def check_single_kv_pair(kv, key):
     check_single_kv_pair(init_kv(), 3)
     check_single_kv_pair(init_kv_with_str(), 'a')
 
+@with_seed()
 def test_row_sparse_pull():
     kv = init_kv_with_str('row_sparse')
     kv.init('e', mx.nd.ones(shape).tostype('row_sparse'))
@@ -89,6 +92,7 @@ def check_row_sparse_pull(kv, count):
     check_row_sparse_pull(kv, 1)
     check_row_sparse_pull(kv, 4)
 
+@with_seed()
 def test_init():
     """test init"""
     def check_init(kv, key):
@@ -100,6 +104,7 @@ def check_init(kv, key):
     check_init(mx.kv.create(), 3)
     check_init(mx.kv.create(), 'a')
 
+@with_seed()
 def test_list_kv_pair():
     """list key-value pair push & pull"""
     def check_list_kv_pair(kv, key):
@@ -113,6 +118,7 @@ def check_list_kv_pair(kv, key):
     check_list_kv_pair(init_kv_with_str(), str_keys)
 
 
+@with_seed()
 def test_aggregator():
     """aggregate value on muliple devices"""
 
@@ -143,6 +149,7 @@ def check_aggregator(kv, key, key_list):
     check_aggregator(init_kv_with_str(), 'a', str_keys)
 
 
+@with_seed()
 def test_sparse_aggregator():
     """aggregate sparse ndarray on muliple devices"""
 
@@ -194,6 +201,7 @@ def str_updater(key, recv, local):
     assert(isinstance(key, str))
     local += recv
 
+@with_seed()
 def test_updater(dev = 'cpu'):
     """updater"""
 
@@ -232,11 +240,13 @@ def check_updater(kv, key, key_list):
     str_kv._set_updater(str_updater)
     check_updater(str_kv, 'a', str_keys)
 
+@with_seed()
 def test_get_type():
     kvtype = 'local_allreduce_cpu'
     kv = mx.kv.create(kvtype)
     assert kv.type == kvtype
 
+@with_seed()
 def test_invalid_pull():
     def check_ignored_pull_single(kv, key):
         dns_val = (mx.nd.ones(shape) * 2)
@@ -285,16 +295,18 @@ def check_invalid_key_types_list(kv, key):
     kvs = [int_kv, str_kv]
     single_keys = [3, 'a']
     list_keys = [keys, str_keys]
-    for i in range(2):
-        # pull with rsp outputs should be ignored with no values updated
-        check_ignored_pull_single(kvs[i], single_keys[i])
-        check_ignored_pull_list(kvs[i], list_keys[i])
-        # row_sparse_pull should be aborted when vals.stype != row_sparse
-        check_invalid_rsp_pull_single(kvs[i], single_keys[i])
-        check_invalid_rsp_pull_list(kvs[i], list_keys[i])
-        # kvstore should be restricted to only accept either int or str keys
-        check_invalid_key_types_single(kvs[i], single_keys[1 - i])
-        check_invalid_key_types_list(kvs[i], list_keys[1 - i])
+    # Keep this test from adding stack backtraces to the log file.
+    with discard_stderr():
+        for i in range(2):
+            # pull with rsp outputs should be ignored with no values updated
+            check_ignored_pull_single(kvs[i], single_keys[i])
+            check_ignored_pull_list(kvs[i], list_keys[i])
+            # row_sparse_pull should be aborted when vals.stype != row_sparse
+            check_invalid_rsp_pull_single(kvs[i], single_keys[i])
+            check_invalid_rsp_pull_list(kvs[i], list_keys[i])
+            # kvstore should be restricted to only accept either int or str keys
+            check_invalid_key_types_single(kvs[i], single_keys[1 - i])
+            check_invalid_key_types_list(kvs[i], list_keys[1 - i])
 
 if __name__ == '__main__':
     import nose
diff --git a/tests/python/unittest/test_loss.py b/tests/python/unittest/test_loss.py
index 8ee4bfae00..f7c4588f00 100644
--- a/tests/python/unittest/test_loss.py
+++ b/tests/python/unittest/test_loss.py
@@ -19,8 +19,10 @@
 import numpy as np
 from mxnet import gluon
 from mxnet.test_utils import assert_almost_equal, default_context
+from common import *
 
 
+@with_seed()
 def test_loss_ndarray():
     output = mx.nd.array([1, 2, 3, 4])
     label = mx.nd.array([1, 3, 5, 7])
@@ -61,9 +63,8 @@ def get_net(num_hidden, flatten=True):
     fc3 = mx.symbol.FullyConnected(act2, name='fc3', num_hidden=num_hidden, flatten=flatten)
     return fc3
 
-
+@with_seed(1234)
 def test_ce_loss():
-    np.random.seed(1234)
     nclass = 10
     N = 20
     data = mx.random.uniform(-1, 1, shape=(N, nclass))
@@ -80,8 +81,8 @@ def test_ce_loss():
     assert mod.score(data_iter, eval_metric=mx.metric.Loss())[0][1] < 0.05
 
 
+@with_seed(1234)
 def test_bce_loss():
-    np.random.seed(1234)
     N = 20
     data = mx.random.uniform(-1, 1, shape=(N, 20))
     label = mx.nd.array(np.random.randint(2, size=(N,)), dtype='float32')
@@ -97,6 +98,7 @@ def test_bce_loss():
             initializer=mx.init.Xavier(magnitude=2))
     assert mod.score(data_iter, eval_metric=mx.metric.Loss())[0][1] < 0.01
 
+@with_seed()
 def test_bce_equal_ce2():
     N = 100
     loss1 = gluon.loss.SigmoidBCELoss(from_sigmoid=True)
@@ -107,8 +109,8 @@ def test_bce_equal_ce2():
     assert_almost_equal(loss1(out1, label).asnumpy(), loss2(out2, label).asnumpy())
 
 
+@with_seed(1234)
 def test_kl_loss():
-    np.random.seed(1234)
     N = 20
     data = mx.random.uniform(-1, 1, shape=(N, 10))
     label = mx.nd.softmax(mx.random.uniform(0, 1, shape=(N, 2)))
@@ -124,8 +126,8 @@ def test_kl_loss():
     assert mod.score(data_iter, eval_metric=mx.metric.Loss())[0][1] < 0.05
 
 
+@with_seed(1234)
 def test_l2_loss():
-    np.random.seed(1234)
     N = 20
     data = mx.random.uniform(-1, 1, shape=(N, 10))
     label = mx.random.uniform(-1, 1, shape=(N, 1))
@@ -142,8 +144,8 @@ def test_l2_loss():
     assert mod.score(data_iter, eval_metric=mx.metric.Loss())[0][1] < 0.05
 
 
+@with_seed(1234)
 def test_l1_loss():
-    np.random.seed(1234)
     N = 20
     data = mx.random.uniform(-1, 1, shape=(N, 10))
     label = mx.random.uniform(-1, 1, shape=(N, 1))
@@ -160,6 +162,7 @@ def test_l1_loss():
     assert mod.score(data_iter, eval_metric=mx.metric.Loss())[0][1] < 0.1
 
 
+@with_seed()
 def test_ctc_loss():
     loss = gluon.loss.CTCLoss()
     l = loss(mx.nd.ones((2,20,4)), mx.nd.array([[1,0,-1,-1],[2,1,1,-1]]))
@@ -186,8 +189,8 @@ def test_ctc_loss():
     mx.test_utils.assert_almost_equal(l.asnumpy(), np.array([18.82820702, 16.50581741]))
 
 
+@with_seed(1234)
 def test_ctc_loss_train():
-    np.random.seed(1234)
     N = 20
     data = mx.random.uniform(-1, 1, shape=(N, 20, 10))
     label = mx.nd.arange(4, repeat=N).reshape((N, 4))
@@ -204,8 +207,8 @@ def test_ctc_loss_train():
     assert mod.score(data_iter, eval_metric=mx.metric.Loss())[0][1] < 10
 
 
+@with_seed(1234)
 def test_sample_weight_loss():
-    np.random.seed(1234)
     nclass = 10
     N = 20
     data = mx.random.uniform(-1, 1, shape=(N, nclass))
@@ -229,9 +232,8 @@ def test_sample_weight_loss():
     assert score < 0.05
 
 
+@with_seed(1234)
 def test_saveload():
-    mx.random.seed(1234)
-    np.random.seed(1234)
     nclass = 10
     N = 20
     data = mx.random.uniform(-1, 1, shape=(N, nclass))
@@ -252,8 +254,8 @@ def test_saveload():
             eval_metric=mx.metric.Loss())
     assert mod.score(data_iter, eval_metric=mx.metric.Loss())[0][1] < 0.05
 
+@with_seed(1234)
 def test_huber_loss():
-    np.random.seed(1234)
     N = 20
     data = mx.random.uniform(-1, 1, shape=(N, 10))
     label = mx.random.uniform(-1, 1, shape=(N, 1))
@@ -270,8 +272,8 @@ def test_huber_loss():
     assert mod.score(data_iter, eval_metric=mx.metric.Loss())[0][1] < 0.05
 
 
+@with_seed(1234)
 def test_hinge_loss():
-    np.random.seed(1234)
     N = 20
     data = mx.random.uniform(-1, 1, shape=(N, 10))
     label = mx.nd.sign(mx.random.uniform(-1, 1, shape=(N, 1)))
@@ -288,8 +290,8 @@ def test_hinge_loss():
     assert mod.score(data_iter, eval_metric=mx.metric.Loss())[0][1] < 0.05
 
 
+@with_seed(1234)
 def test_squared_hinge_loss():
-    np.random.seed(1234)
     N = 20
     data = mx.random.uniform(-1, 1, shape=(N, 10))
     label = mx.nd.sign(mx.random.uniform(-1, 1, shape=(N, 1)))
@@ -306,8 +308,8 @@ def test_squared_hinge_loss():
     assert mod.score(data_iter, eval_metric=mx.metric.Loss())[0][1] < 0.05
 
 
+@with_seed(1234)
 def test_triplet_loss():
-    np.random.seed(1234)
     N = 20
     data = mx.random.uniform(-1, 1, shape=(N, 10))
     pos = mx.random.uniform(-1, 1, shape=(N, 10))
diff --git a/tests/python/unittest/test_module.py b/tests/python/unittest/test_module.py
index d79657a85a..3109ee54c0 100644
--- a/tests/python/unittest/test_module.py
+++ b/tests/python/unittest/test_module.py
@@ -21,12 +21,11 @@
 import numpy as np
 from functools import reduce
 from mxnet.module.executor_group import DataParallelExecutorGroup
-from common import assertRaises
+from common import *
 from collections import namedtuple
 
-import numpy.random as rnd
-
 
+@with_seed()
 def test_module_dtype():
     dtype = np.float16
     dshape = (3, 8, 7)
@@ -45,6 +44,7 @@ def test_module_dtype():
       assert x.dtype == dtype
 
 
+@with_seed()
 def test_module_input_grads():
     a = mx.sym.Variable('a', __layout__='NC')
     b = mx.sym.Variable('b', __layout__='NC')
@@ -70,6 +70,7 @@ def test_module_input_grads():
     assert np.all(c_grad == 3), c_grad
 
 
+@with_seed()
 def test_module_layout():
     sym = mx.sym.Variable('data')
     sym = mx.sym.Activation(data=sym, act_type='relu', __layout__='TNC')
@@ -88,6 +89,7 @@ def test_module_layout():
         assert x.shape == hdshape
 
 
+@with_seed()
 def test_save_load():
     def dict_equ(a, b):
         assert set(a) == set(b)
@@ -128,6 +130,7 @@ def dict_equ(a, b):
     dict_equ(mod._kvstore._updater.states, mod2._updater.states)
 
 
+@with_seed()
 def test_module_reshape():
     data = mx.sym.Variable('data')
     sym = mx.sym.FullyConnected(data, num_hidden=20, name='fc')
@@ -155,6 +158,7 @@ def test_module_reshape():
     assert (mod.get_params()[0]['fc_bias'].asnumpy() == -3).all()
 
 
+@with_seed()
 def test_module_states():
     stack = mx.rnn.SequentialRNNCell()
     for i in range(2):
@@ -182,6 +186,7 @@ def test_module_states():
         assert not mx.test_utils.almost_equal(x1.asnumpy(), x2.asnumpy(), rtol=1e-3)
 
 
+@with_seed()
 def test_module_switch_bucket():
     vocab_dim = 5000
     num_hidden = 100
@@ -238,9 +243,9 @@ def create_bucketing_module(key):
 
 
 
+@with_seed(11)
 def test_module_set_params():
     # data iter
-    mx.random.seed(11)
     data = mx.nd.array([[0.05, .10]]);
     label = mx.nd.array([[.01, 0.99]]);
     train_data = mx.io.NDArrayIter(data, label, batch_size=1)
@@ -301,9 +306,9 @@ def test_module_set_params():
                  aux_params={}, allow_missing=True, allow_extra=False)
 
 
+@with_seed(11)
 def test_monitor():
     # data iter
-    mx.random.seed(11)
     data = mx.nd.array([[0.05, .10]]);
     label = mx.nd.array([[.01, 0.99]]);
     train_data = mx.io.NDArrayIter(data, label, batch_size=1)
@@ -348,6 +353,7 @@ def mean_abs(x):
                 break
     assert(mon_result_counts == [2, 2, 1, 6, 6, 4])
 
+@with_seed()
 def test_executor_group():
     def get_rnn_sym(num_layers, num_words, num_hidden, num_embed, seq_len):
         stack = mx.rnn.SequentialRNNCell()
@@ -459,13 +465,11 @@ def test_shared_exec_group(exec_grp_shared, exec_grp_created, shared_arg_names=N
     test_shared_exec_group(exec_grp_shared=exec_group1, exec_grp_created=exec_group2,
                            shared_arg_names=shared_arg_names, extra_args=extra_args)
 
-
+@with_seed(11)
 def test_factorization_machine_module(verbose=False):
     """ Test factorization machine model with sparse operators """
     def check_factorization_machine_module(optimizer=None, num_epochs=None):
         print("check_factorization_machine_module( {} )".format(optimizer))
-        mx.random.seed(11)
-        rnd.seed(11)
 
         def fm(factor_size, feature_dim, init):
             x = mx.symbol.Variable("data", stype='csr')
@@ -576,6 +580,7 @@ def fm(factor_size, feature_dim, init):
         print("Duration: {}".format(time.clock() - start))
 
 
+@with_seed()
 def test_module_initializer():
     def regression_model(m):
          x = mx.symbol.var("data", stype='csr')
@@ -602,6 +607,7 @@ def regression_model(m):
     assert(v.stype == 'row_sparse')
     assert(np.sum(v.asnumpy()) != 0)
 
+@with_seed()
 def test_forward_reshape():
     num_class=10
     data1 = mx.sym.Variable('data1')
diff --git a/tests/python/unittest/test_ndarray.py b/tests/python/unittest/test_ndarray.py
index 28aab7a4cb..935ce60727 100644
--- a/tests/python/unittest/test_ndarray.py
+++ b/tests/python/unittest/test_ndarray.py
@@ -22,9 +22,11 @@
 import unittest
 from nose.tools import raises
 from mxnet.test_utils import *
+from common import *
 from numpy.testing import assert_allclose
 import unittest
 
+
 def check_with_uniform(uf, arg_shapes, dim=None, npuf=None, rmin=-10, type_list=[np.float32]):
     """check function consistency with uniform random numbers"""
     if isinstance(arg_shapes, int):
@@ -53,13 +55,13 @@ def check_with_uniform(uf, arg_shapes, dim=None, npuf=None, rmin=-10, type_list=
         else:
             assert_almost_equal(out1, out2)
 
-
 def random_ndarray(dim):
     shape = tuple(np.random.randint(1, int(1000**(1.0/dim)), size=dim))
     data = mx.nd.array(np.random.uniform(-10, 10, shape))
     return data
 
 
+@with_seed()
 def test_ndarray_setitem():
     shape = (3, 4, 2)
 
@@ -111,8 +113,8 @@ def test_ndarray_setitem():
     assert same(x.asnumpy(), x_np)
 
 
+@with_seed(0)
 def test_ndarray_elementwise():
-    np.random.seed(0)
     nrepeat = 10
     maxdim = 4
     all_type = [np.float32, np.float64, np.float16, np.uint8, np.int32]
@@ -128,11 +130,13 @@ def test_ndarray_elementwise():
             check_with_uniform(mx.nd.square, 1, dim, np.square, rmin=0)
             check_with_uniform(lambda x: mx.nd.norm(x).asscalar(), 1, dim, np.linalg.norm)
 
+@with_seed()
 def test_ndarray_elementwisesum():
     ones = mx.nd.ones((10,), dtype=np.int32)
     res = mx.nd.ElementWiseSum(ones, ones*2, ones*4, ones*8)
     assert same(res.asnumpy(), ones.asnumpy()*15)
 
+@with_seed()
 def test_ndarray_negate():
     npy = np.random.uniform(-10, 10, (2,3,4))
     arr = mx.nd.array(npy)
@@ -144,6 +148,7 @@ def test_ndarray_negate():
     # we compute (-arr)
     assert_almost_equal(npy, arr.asnumpy())
 
+@with_seed()
 def test_ndarray_reshape():
     tensor  = mx.nd.array([[[1, 2], [3, 4]],
                            [[5, 6], [7, 8]]])
@@ -160,6 +165,7 @@ def test_ndarray_reshape():
     assert same(tensor.reshape((-1, 2)).asnumpy(), true_res.asnumpy())
 
 
+@with_seed()
 def test_ndarray_choose():
     shape = (100, 20)
     npy = np.arange(np.prod(shape)).reshape(shape)
@@ -171,6 +177,7 @@ def test_ndarray_choose():
                     mx.nd.choose_element_0index(arr, mx.nd.array(indices)).asnumpy())
 
 
+@with_seed()
 def test_ndarray_fill():
     shape = (100, 20)
     npy = np.arange(np.prod(shape)).reshape(shape)
@@ -186,6 +193,7 @@ def test_ndarray_fill():
                     mx.nd.fill_element_0index(arr, mx.nd.array(val), mx.nd.array(indices)).asnumpy())
 
 
+@with_seed()
 def test_ndarray_onehot():
     shape = (100, 20)
     npy = np.arange(np.prod(shape)).reshape(shape)
@@ -199,12 +207,14 @@ def test_ndarray_onehot():
         assert same(npy, arr.asnumpy())
 
 
+@with_seed()
 def test_ndarray_copy():
     c = mx.nd.array(np.random.uniform(-10, 10, (10, 10)))
     d = c.copyto(mx.Context('cpu', 0))
     assert np.sum(np.abs(c.asnumpy() != d.asnumpy())) == 0.0
 
 
+@with_seed()
 def test_ndarray_scalar():
     c = mx.nd.empty((10,10))
     d = mx.nd.empty((10,10))
@@ -219,8 +229,8 @@ def test_ndarray_scalar():
     d = -c + 2
     assert(np.sum(d.asnumpy()) < 1e-5)
 
+@with_seed(0)
 def test_ndarray_pickle():
-    np.random.seed(0)
     maxdim = 5
     nrepeat = 10
     for repeat in range(nrepeat):
@@ -234,9 +244,8 @@ def test_ndarray_pickle():
             a2 = pkl.loads(data)
             assert np.sum(a.asnumpy() != a2.asnumpy()) == 0
 
-
+@with_seed(0)
 def test_ndarray_saveload():
-    np.random.seed(0)
     nrepeat = 10
     fname = 'tmp_list.bin'
     for repeat in range(nrepeat):
@@ -267,6 +276,7 @@ def test_ndarray_saveload():
         assert np.sum(single_ndarray.asnumpy() != single_ndarray_loaded.asnumpy()) == 0
     os.remove(fname)
 
+@with_seed()
 def test_ndarray_legacy_load():
     data = []
     for i in range(6):
@@ -277,6 +287,7 @@ def test_ndarray_legacy_load():
     for i in range(len(data)):
         assert same(data[i].asnumpy(), legacy_data[i].asnumpy())
 
+@with_seed()
 def test_ndarray_slice():
     shape = (10,)
     A = mx.nd.array(np.random.uniform(-10, 10, shape))
@@ -299,6 +310,7 @@ def test_ndarray_slice():
     assert (a[mx.nd.array([1, 1, 0]), mx.nd.array([0, 1, 0])].asnumpy() == [2, 3, 0]).all()
 
 
+@with_seed()
 def test_ndarray_crop():
     # get crop
     x = mx.nd.ones((2, 3, 4))
@@ -323,6 +335,7 @@ def test_ndarray_crop():
     assert same(x.asnumpy(), np_x)
 
 
+@with_seed()
 def test_ndarray_concatenate():
     axis = 1
     shapes = [(2, 3, 4, 2), (2, 2, 4, 2), (2, 1, 4, 2)]
@@ -335,6 +348,7 @@ def test_ndarray_concatenate():
     assert same(array_np, array_nd.asnumpy())
 
 
+@with_seed()
 def test_clip():
     shape = (10,)
     A = mx.random.uniform(-10, 10, shape)
@@ -344,7 +358,9 @@ def test_clip():
         assert B1[i] >= -2
         assert B1[i] <= 2
 
+@with_seed()
 def test_dot():
+    atol = 1e-5
     # Test normal dot
     a = np.random.uniform(-3, 3, (3, 4))
     b = np.random.uniform(-3, 3, (4, 5))
@@ -352,7 +368,7 @@ def test_dot():
     A = mx.nd.array(a)
     B = mx.nd.array(b)
     C = mx.nd.dot(A, B)
-    assert_almost_equal(c, C.asnumpy())
+    assert_almost_equal(c, C.asnumpy(), atol=atol)
     # Test dot with transpose kargs
     a = np.random.uniform(-3, 3, (3, 4))
     b = np.random.uniform(-3, 3, (3, 5))
@@ -360,7 +376,7 @@ def test_dot():
     A = mx.nd.array(a)
     B = mx.nd.array(b)
     C = mx.nd.dot(A, B, transpose_a=True)
-    assert_almost_equal(c, C.asnumpy())
+    assert_almost_equal(c, C.asnumpy(), atol=atol)
     # Test dot with transpose kargs
     a = np.random.uniform(-3, 3, (3, 4))
     b = np.random.uniform(-3, 3, (5, 4))
@@ -368,7 +384,7 @@ def test_dot():
     A = mx.nd.array(a)
     B = mx.nd.array(b)
     C = mx.nd.dot(A, B, transpose_b=True)
-    assert_almost_equal(c, C.asnumpy())
+    assert_almost_equal(c, C.asnumpy(), atol=atol)
     # Test dot with transpose kargs
     a = np.random.uniform(-3, 3, (4, 3))
     b = np.random.uniform(-3, 3, (5, 4))
@@ -376,10 +392,11 @@ def test_dot():
     A = mx.nd.array(a)
     B = mx.nd.array(b)
     C = mx.nd.dot(A, B, transpose_a=True, transpose_b=True)
-    assert_almost_equal(c, C.asnumpy())
+    assert_almost_equal(c, C.asnumpy(), atol=atol)
 
 
 
+@with_seed()
 def test_reduce():
     sample_num = 200
     def test_reduce_inner(numpy_reduce_func, nd_reduce_func, multi_axes):
@@ -416,11 +433,14 @@ def test_reduce_inner(numpy_reduce_func, nd_reduce_func, multi_axes):
                       mx.nd.max, True)
     test_reduce_inner(lambda data, axis, keepdims:np_reduce(data, axis, keepdims, np.min),
                       mx.nd.min, True)
-    test_reduce_inner(lambda data, axis, keepdims:np_reduce(data, axis, keepdims, np.argmax),
+    # argmax and argmin are sensitive to the precision of the calculation.
+    # Force numpy to match mxnet's float32.
+    test_reduce_inner(lambda data, axis, keepdims:np_reduce(np.float32(data), axis, keepdims, np.argmax),
                       mx.nd.argmax, False)
-    test_reduce_inner(lambda data, axis, keepdims:np_reduce(data, axis, keepdims, np.argmin),
+    test_reduce_inner(lambda data, axis, keepdims:np_reduce(np.float32(data), axis, keepdims, np.argmin),
                       mx.nd.argmin, False)
 
+@with_seed()
 def test_broadcast():
     sample_num = 1000
     def test_broadcast_to():
@@ -443,6 +463,7 @@ def test_broadcast_to():
             assert err < 1E-8
     test_broadcast_to()
 
+@with_seed()
 def test_broadcast_binary():
     N = 100
     def check_broadcast_binary(fn):
@@ -468,12 +489,15 @@ def check_broadcast_binary(fn):
     check_broadcast_binary(lambda x, y: x - y)
     check_broadcast_binary(lambda x, y: x * y)
     check_broadcast_binary(lambda x, y: x / y)
-    check_broadcast_binary(lambda x, y: x > y)
-    check_broadcast_binary(lambda x, y: x < y)
-    check_broadcast_binary(lambda x, y: x >= y)
-    check_broadcast_binary(lambda x, y: x <= y)
-    check_broadcast_binary(lambda x, y: x == y)
-
+    # The following ops are sensitive to the precision of the calculation.
+    # Force numpy to match mxnet's float32.
+    check_broadcast_binary(lambda x, y: x.astype(np.float32) > y.astype(np.float32))
+    check_broadcast_binary(lambda x, y: x.astype(np.float32) < y.astype(np.float32))
+    check_broadcast_binary(lambda x, y: x.astype(np.float32) >= y.astype(np.float32))
+    check_broadcast_binary(lambda x, y: x.astype(np.float32) <= y.astype(np.float32))
+    check_broadcast_binary(lambda x, y: x.astype(np.float32) == y.astype(np.float32))
+
+@with_seed()
 def test_moveaxis():
     X = mx.nd.array([[[1, 2, 3], [4, 5, 6]],
                      [[7, 8, 9], [10, 11, 12]]])
@@ -487,6 +511,7 @@ def test_moveaxis():
     assert same(res, true_res.asnumpy())
     assert mx.nd.moveaxis(X, 2, 0).shape == (3, 2, 2)
 
+@with_seed()
 def test_arange():
     for i in range(5):
         start = np.random.rand() * 10
@@ -502,7 +527,10 @@ def test_arange():
                         dtype="int32").asnumpy()
     assert_almost_equal(pred, gt)
 
-def test_order(ctx=default_context()):
+@with_seed()
+def test_order():
+    ctx = default_context()
+    dat_size = 5
     def gt_topk(dat, axis, ret_typ, k, is_ascend):
         if ret_typ == "indices":
             if is_ascend:
@@ -517,7 +545,7 @@ def gt_topk(dat, axis, ret_typ, k, is_ascend):
                 indices = np.arange(-1, -k-1, -1)
             ret = np.take(np.sort(dat, axis=axis), axis=axis, indices=indices, mode='wrap')
         else:
-            assert dat.shape == (5, 5, 5, 5)
+            assert dat.shape == (dat_size, dat_size, dat_size, dat_size)
             assert axis is None or axis ==1
             ret = np.zeros(dat.shape)
             if is_ascend:
@@ -528,12 +556,27 @@ def gt_topk(dat, axis, ret_typ, k, is_ascend):
             if axis is None:
                 ret.ravel()[gt_argsort] = 1
             else:
-                for i in range(5):
-                    for j in range(5):
-                        for k in range(5):
+                for i in range(dat_size):
+                    for j in range(dat_size):
+                        for k in range(dat_size):
                             ret[i, gt_argsort[i, :, j, k], j, k] = 1
         return ret
-    a_npy = np.random.normal(size=(5, 5, 5, 5))
+
+    # Produce input data for the tests, including possibly ensuring unique values.  We
+    # observed that numpy's argsort did not consistently return lowest-index-first for
+    # matching values, making it hard to generate a numpy 'golden copy' to compare against
+    # the mxnet operator.  The 'mask' function is particularly hard to test given that equal
+    # values might span the 'k' boundary.
+    def get_values(ensure_unique):
+        while True:
+            data = np.float32(np.random.normal(size=(dat_size, dat_size, dat_size, dat_size)))
+            if not ensure_unique:
+                return data
+            num_unique_values = len(set(data.flatten()))
+            if data.size == num_unique_values:
+                return data
+
+    a_npy = get_values(ensure_unique=True)
     a_nd = mx.nd.array(a_npy, ctx=ctx)
 
     # test for ret_typ=indices
@@ -580,24 +623,53 @@ def gt_topk(dat, axis, ret_typ, k, is_ascend):
 
     # test for sort
     nd_ret_sort = mx.nd.sort(a_nd, axis=1, is_ascend=True).asnumpy()
-    gt = gt_topk(a_npy, axis=1, ret_typ="value", k=5, is_ascend=True)
+    gt = gt_topk(a_npy, axis=1, ret_typ="value", k=dat_size, is_ascend=True)
     assert_almost_equal(nd_ret_sort, gt)
     nd_ret_sort = mx.nd.sort(a_nd, axis=None, is_ascend=False).asnumpy()
-    gt = gt_topk(a_npy, axis=None, ret_typ="value", k=5*5*5*5, is_ascend=False)
+    gt = gt_topk(a_npy, axis=None, ret_typ="value",
+                 k=dat_size*dat_size*dat_size*dat_size, is_ascend=False)
     assert_almost_equal(nd_ret_sort, gt)
 
     # test for argsort
     nd_ret_argsort = mx.nd.argsort(a_nd, axis=3, is_ascend=True).asnumpy()
-    gt = gt_topk(a_npy, axis=3, ret_typ="indices", k=5, is_ascend=True)
+    gt = gt_topk(a_npy, axis=3, ret_typ="indices", k=dat_size, is_ascend=True)
     assert_almost_equal(nd_ret_argsort, gt)
     nd_ret_argsort = mx.nd.argsort(a_nd, axis=None, is_ascend=False).asnumpy()
-    gt = gt_topk(a_npy, axis=None, ret_typ="indices", k=5*5*5*5, is_ascend=False)
+    gt = gt_topk(a_npy, axis=None, ret_typ="indices",
+                 k=dat_size*dat_size*dat_size*dat_size, is_ascend=False)
     assert_almost_equal(nd_ret_argsort, gt)
     
     # test topk with a big shape
     a = mx.nd.arange(0, 54686454, step=1, repeat=1)
     assert_almost_equal(a.topk(k=54686454).asnumpy(), a.asnumpy()[::-1])
 
+    # Repeat those tests that don't involve indices.  These should pass even with
+    # duplicated input data values (over many repeated runs with different random seeds,
+    # this will be tested).
+    a_npy = get_values(ensure_unique=False)
+    a_nd = mx.nd.array(a_npy, ctx=ctx)
+
+    # test for ret_typ=value
+    nd_ret_topk = mx.nd.topk(a_nd, axis=1, ret_typ="value", k=3, is_ascend=True).asnumpy()
+    gt = gt_topk(a_npy, axis=1, ret_typ="value", k=3, is_ascend=True)
+    assert_almost_equal(nd_ret_topk, gt)
+    nd_ret_topk = mx.nd.topk(a_nd, axis=3, ret_typ="value", k=2, is_ascend=False).asnumpy()
+    gt = gt_topk(a_npy, axis=3, ret_typ="value", k=2, is_ascend=False)
+    assert_almost_equal(nd_ret_topk, gt)
+    nd_ret_topk = mx.nd.topk(a_nd, axis=None, ret_typ="value", k=21, is_ascend=False).asnumpy()
+    gt = gt_topk(a_npy, axis=None, ret_typ="value", k=21, is_ascend=False)
+    assert_almost_equal(nd_ret_topk, gt)
+
+    # test for sort
+    nd_ret_sort = mx.nd.sort(a_nd, axis=1, is_ascend=True).asnumpy()
+    gt = gt_topk(a_npy, axis=1, ret_typ="value", k=dat_size, is_ascend=True)
+    assert_almost_equal(nd_ret_sort, gt)
+    nd_ret_sort = mx.nd.sort(a_nd, axis=None, is_ascend=False).asnumpy()
+    gt = gt_topk(a_npy, axis=None, ret_typ="value",
+                 k=dat_size*dat_size*dat_size*dat_size, is_ascend=False)
+    assert_almost_equal(nd_ret_sort, gt)
+
+@with_seed()
 def test_ndarray_equal():
     x = mx.nd.zeros((2, 3))
     y = mx.nd.ones((2, 3))
@@ -606,6 +678,7 @@ def test_ndarray_equal():
     z = 0 == x
     assert (z.asnumpy() == np.ones((2, 3))).all()
 
+@with_seed()
 def test_ndarray_not_equal():
     x = mx.nd.zeros((2, 3))
     y = mx.nd.ones((2, 3))
@@ -614,6 +687,7 @@ def test_ndarray_not_equal():
     z = 0 != x
     assert (z.asnumpy() == np.zeros((2, 3))).all()
 
+@with_seed()
 def test_ndarray_greater():
     x = mx.nd.zeros((2, 3))
     y = mx.nd.ones((2, 3))
@@ -624,6 +698,7 @@ def test_ndarray_greater():
     z = 0 > y
     assert (z.asnumpy() == np.zeros((2, 3))).all()
 
+@with_seed()
 def test_ndarray_greater_equal():
     x = mx.nd.zeros((2, 3))
     y = mx.nd.ones((2, 3))
@@ -636,6 +711,7 @@ def test_ndarray_greater_equal():
     z = y >= 1
     assert (z.asnumpy() == np.ones((2, 3))).all()
 
+@with_seed()
 def test_ndarray_lesser():
     x = mx.nd.zeros((2, 3))
     y = mx.nd.ones((2, 3))
@@ -646,6 +722,7 @@ def test_ndarray_lesser():
     z = y < 0
     assert (z.asnumpy() == np.zeros((2, 3))).all()
 
+@with_seed()
 def test_ndarray_lesser_equal():
     x = mx.nd.zeros((2, 3))
     y = mx.nd.ones((2, 3))
@@ -658,6 +735,7 @@ def test_ndarray_lesser_equal():
     z = 1 <= y
     assert (z.asnumpy() == np.ones((2, 3))).all()
 
+@with_seed()
 def test_take():
     for data_ndim in range(2, 5):
         for idx_ndim in range(1, 4):
@@ -675,6 +753,7 @@ def test_take():
             assert_almost_equal(result.asnumpy(), data_real[idx_real])
 
 
+@with_seed()
 def test_iter():
     x = mx.nd.array([1, 2, 3])
     y = []
@@ -685,6 +764,7 @@ def test_iter():
         assert same(y[i].asnumpy(), x[i].asnumpy())
 
 @unittest.skip("test fails intermittently. temporarily disabled till it gets fixed. tracked at https://github.com/apache/incubator-mxnet/issues/8049")
+@with_seed()
 def test_cached():
     sym = mx.sym.Convolution(kernel=(3, 3), num_filter=10) + 2
     op = mx.nd.CachedOp(sym)
@@ -727,6 +807,7 @@ def test_cached():
         o.backward()
 
 
+@with_seed()
 def test_output():
     shape = (2,2)
     ones = mx.nd.ones(shape)
@@ -741,6 +822,7 @@ def test_output():
     arange_out = mx.nd.arange(0, 20, dtype='int64')
     assert_almost_equal(arange_out.asnumpy(), np.arange(0, 20))
 
+@with_seed()
 def test_ndarray_fluent():
     has_grad = set(['flatten', 'expand_dims', 'flip', 'tile', 'transpose', 'sum', 'nansum', 'prod',
                     'nanprod', 'mean', 'max', 'min', 'reshape', 'broadcast_to', 'split',
@@ -796,9 +878,11 @@ def check_fluent_regular(func, kwargs, shape=(5, 17, 1), equal_nan=False):
     check_fluent_regular('broadcast_to', {'shape': (5, 17, 47)})
 
 @raises(ValueError)
+@with_seed()
 def test_bool_ambiguous():
     bool(mx.nd.ones((2,3,4)))
 
+@with_seed()
 def test_bool():
     assert not bool(mx.nd.array([]))
     assert not bool(mx.nd.zeros((1,)))
diff --git a/tests/python/unittest/test_operator.py b/tests/python/unittest/test_operator.py
index ef866dd768..593b6bf62f 100644
--- a/tests/python/unittest/test_operator.py
+++ b/tests/python/unittest/test_operator.py
@@ -23,6 +23,7 @@
 import itertools
 from numpy.testing import assert_allclose, assert_array_equal
 from mxnet.test_utils import *
+from common import *
 import unittest
 
 
@@ -60,9 +61,10 @@ def check_elementwise_sum_with_shape(shape, n):
     for a in arr_grad:
         assert_almost_equal(a.asnumpy(), out_grad.asnumpy())
 
-
+# Comparing random sums that are close to zero is troublesome.
+# Pick a specific seed without altering the determinism of the other tests.
+@with_seed(0)
 def test_elementwise_sum():
-    np.random.seed(0)
     nrepeat = 2
     maxdim = 4
     for repeat in range(nrepeat):
@@ -70,7 +72,6 @@ def test_elementwise_sum():
             shape = tuple(np.random.randint(1, int(1000**(1.0/dim)), size=dim))
             check_elementwise_sum_with_shape(shape, np.random.randint(1, 8))
 
-
 def check_concat_with_shape(shapes, dimension, skip_second):
     # if skip_second is True, second argument will not have gradient.
     # it is to test #1130
@@ -116,6 +117,7 @@ def check_concat_with_shape(shapes, dimension, skip_second):
             assert_almost_equal(grad.asnumpy(), np_grad + 1)
 
 
+@with_seed()
 def test_concat():
     for dimension in range(4):
         n = 2
@@ -163,6 +165,7 @@ def test_concat():
             check_concat_with_shape(shapes,dimension,False)
 
 
+@with_seed()
 def test_slice_channel():
     def check_slice_channel(data_ndim, axis, num_outputs, squeeze_axis):
         ins = []
@@ -220,13 +223,15 @@ def check_regression(symbol, forward, backward):
     exec1.forward(is_train=True)
     out1 = exec1.outputs[0].asnumpy()
     npout = forward(arr_data.asnumpy())
-    assert_almost_equal(npout, out1)
+    atol = 1e-5
+    assert_almost_equal(npout, out1, atol=atol)
 
     exec1.backward()
     npout = backward(npout,  arr_label.asnumpy().reshape(npout.shape))
-    assert_almost_equal(npout, arr_grad.asnumpy())
+    assert_almost_equal(npout, arr_grad.asnumpy(), atol=atol)
 
 
+@with_seed()
 def test_regression():
     check_regression(mx.symbol.LogisticRegressionOutput,
                      lambda x: 1.0 / (1.0 + np.exp(-x)),
@@ -328,11 +333,14 @@ def check_softmax_with_shape(shape, xpu, preserve_shape=False):
     exec1 = Y.bind(xpu, args = [x, l], args_grad = {'X': grad})
     exec1.forward(is_train=True)
     out = exec1.outputs[0].asnumpy()
-    assert_almost_equal(out, np_softmax(x.asnumpy()), rtol=1e-4)
+    rtol = 1e-4
+    atol = 1e-6
+    assert_almost_equal(out, np_softmax(x.asnumpy()), rtol=rtol, atol=atol)
     exec1.backward()
-    assert_almost_equal(grad.asnumpy(), np_softmax(x.asnumpy()) - l.asnumpy(), rtol=1e-4)
+    assert_almost_equal(grad.asnumpy(), np_softmax(x.asnumpy()) - l.asnumpy(), rtol=rtol, atol=atol)
 
 
+@with_seed()
 def test_python_op():
     X = mx.symbol.Variable('X')
     op = mx.operator.NumpyOp()
@@ -348,6 +356,7 @@ def test_python_op():
     assert_almost_equal(dy.asnumpy(), dx.asnumpy())
 
 
+@with_seed()
 def test_swapaxes():
     data = mx.symbol.Variable('data')
     shape = (2, 3, 4)
@@ -367,6 +376,7 @@ def test_swapaxes():
     assert_almost_equal(out, swap_)
 
 
+@with_seed()
 def test_scalarop():
     data = mx.symbol.Variable('data')
     shape = (3, 4)
@@ -388,6 +398,7 @@ def test_scalarop():
     check_symbolic_backward(test, [data_tmp], [np.ones(shape)*2], [npout_grad])
 
 
+@with_seed()
 def test_scalar_pow():
     data = mx.symbol.Variable('data')
     shape = (1, 1)
@@ -398,6 +409,7 @@ def test_scalar_pow():
     check_symbolic_backward(test, [data_tmp], [np.ones(shape)], [2 * data_tmp])
 
 
+@with_seed()
 def test_symbol_pow():
     shape = (1, 1)
 
@@ -417,6 +429,7 @@ def test_symbol_pow():
     check_symbolic_backward(test, [data_tmp, exp_tmp], [np.ones(shape)], [data_dir, exp_dir])
 
 
+@with_seed()
 def test_pow_fn():
     shape = (3, 4)
     exp = mx.symbol.Variable("exp")
@@ -427,6 +440,7 @@ def test_pow_fn():
     check_symbolic_backward(y, [x], [np.ones(shape)], [np.log(2) * 2**x])
 
 
+@with_seed()
 def test_relu():
     def frelu(x):
         return np.maximum(x, 0.0)
@@ -436,13 +450,17 @@ def frelu_grad(x):
     x = mx.symbol.Variable("x")
     y = mx.sym.relu(x)
     xa = np.random.uniform(low=-1.0,high=1.0,size=shape)
+    eps = 1e-4
+    # Avoid finite difference method inaccuracies due to discontinuous gradient at the origin.
+    xa[abs(xa) < eps] = 1.0
     ya = frelu(xa)
     ga = frelu_grad(xa)
-    check_numeric_gradient(y, [xa], numeric_eps=1E-3)
+    check_numeric_gradient(y, [xa], numeric_eps=eps)
     check_symbolic_forward(y, [xa], [ya])
     check_symbolic_backward(y, [xa], [np.ones(shape)], [ga])
 
 
+@with_seed()
 def test_sigmoid():
     def fsigmoid(a):
         return np.divide(1.0, (1.0 + np.exp(-a)))
@@ -456,6 +474,7 @@ def fsigmoid(a):
     check_symbolic_backward(y, [xa], [np.ones(shape)], [ya * (1 - ya)])
 
 
+@with_seed()
 def test_binary_logic():
     def _inner_test(forward_gt, logic_sym, x_shape, y_shape, test_scalar=True):
         x = mx.symbol.Variable("x")
@@ -512,6 +531,7 @@ def _inner_test(forward_gt, logic_sym, x_shape, y_shape, test_scalar=True):
                 x_shape=(1, 10), y_shape=(10, 1), test_scalar=False)
 
 
+@with_seed()
 def test_embedding():
     in_dim = 10
     out_dim = 4
@@ -530,16 +550,17 @@ def test_embedding():
     arg_map["data"][:] = np_data
     arg_map["embed_weight"][:] = np_weight
     exe_test.forward(is_train=True)
-    assert_almost_equal(exe_test.outputs[0].asnumpy(), np.dot(np_onehot, np_weight))
+    assert_almost_equal(exe_test.outputs[0].asnumpy(), np.dot(np_onehot, np_weight), rtol=1e-5, atol=1e-5)
     # backward
     np_grad = np.random.uniform(-1, 1, exe_test.outputs[0].shape)
     grad = mx.nd.zeros(np_grad.shape)
     grad[:] = np_grad
     exe_test.backward([grad])
-    assert_almost_equal(grad_map["embed_weight"].asnumpy(), np.dot(np_onehot.T, np_grad))
+    assert_almost_equal(grad_map["embed_weight"].asnumpy(), np.dot(np_onehot.T, np_grad), rtol=1e-5, atol=1e-5)
 
 
 # check ops handle duplicate input correctly.
+@with_seed()
 def test_binary_op_duplicate_input():
     data = mx.symbol.Variable('data')
     shape = (3, 4)
@@ -558,6 +579,7 @@ def test_binary_op_duplicate_input():
     assert_almost_equal(arr_grad.asnumpy(), 2.0 * data_tmp)
 
 
+@with_seed()
 def test_sign():
     data = mx.symbol.Variable('data')
     shape = (3, 4)
@@ -582,6 +604,7 @@ def test_sign():
     assert_almost_equal(arr_grad.asnumpy(), npout_grad)
 
 
+@with_seed()
 def test_round_ceil_floor():
     data = mx.symbol.Variable('data')
     shape = (3, 4)
@@ -599,6 +622,7 @@ def test_round_ceil_floor():
     assert_almost_equal(out, npout)
 
 
+@with_seed()
 def test_trunc():
     data_tmp = np.random.rand(3, 4) * 10 - 5
     arr_data = mx.nd.array(data_tmp)
@@ -613,6 +637,7 @@ def test_trunc():
     assert_almost_equal(out, npout)
 
 
+@with_seed()
 def test_rsqrt_cos_sin():
     data = mx.symbol.Variable('data')
     shape = (3, 4)
@@ -637,6 +662,7 @@ def test_rsqrt_cos_sin():
     assert_almost_equal(arr_grad.asnumpy(), npout_grad)
 
 
+@with_seed()
 def test_maximum_minimum():
     data1 = mx.symbol.Variable('data')
     data2 = mx.symbol.Variable('data')
@@ -674,6 +700,7 @@ def test_maximum_minimum():
     assert_almost_equal(arr_grad2.asnumpy(), npout_grad2)
 
 
+@with_seed()
 def test_maximum_minimum_scalar():
     data1 = mx.symbol.Variable('data')
     shape = (3, 4)
@@ -705,6 +732,7 @@ def test_maximum_minimum_scalar():
     assert_almost_equal(arr_grad1.asnumpy(), npout_grad1)
 
 
+@with_seed()
 def test_abs():
     data = mx.symbol.Variable('data')
     shape = (3, 4)
@@ -842,6 +870,7 @@ def check_deconvolution_target_shape(input_shape, kernel, stride, pad, adj, targ
     assert out_shapes[0] == (input_shape[0], 5, 8, 8)
 
 
+@with_seed()
 def test_deconvolution():
     check_deconvolution_target_shape(
         input_shape         = (2,3,4,4),
@@ -917,6 +946,7 @@ def check_bilinear_upsampling_with_shape(shapes, scale, root_scale):
         assert_allclose(arr[name].asnumpy()*root_scale**2*scale**(2*k), arr_grad[name].asnumpy(), rtol=1e-4)
 
 
+@with_seed()
 def test_nearest_upsampling():
     for root_scale in [1,2,3]:
         for scale in [1,2,3]:
@@ -927,6 +957,7 @@ def test_nearest_upsampling():
 
 
 @unittest.skip("test fails intermittently. temporarily disabled till it gets fixed. tracked at https://github.com/apache/incubator-mxnet/issues/8044")
+@with_seed()
 def test_batchnorm_training():
     def check_batchnorm_training(stype):
         for shape in [(2, 3), (2, 3, 2, 2)]:
@@ -1012,6 +1043,7 @@ def check_batchnorm_training(stype):
         check_batchnorm_training(stype)
 
 
+@with_seed(1234)
 def test_convolution_grouping():
     num_filter = 4
     num_group = 2
@@ -1043,6 +1075,7 @@ def test_convolution_grouping():
         np.testing.assert_allclose(arr1.asnumpy(), arr2.asnumpy(), rtol=1e-3, atol=1e-4)
 
 
+@with_seed()
 def test_depthwise_convolution():
     for num_base in [1, 4, 16, 32, 64]:
         for kernel in [(3,3), (5,5)]:
@@ -1079,10 +1112,10 @@ def test_depthwise_convolution():
                         exe2.backward(exe2.outputs[0])
 
                         for arr1, arr2 in zip(exe1.outputs + exe1.grad_arrays, exe2.outputs + exe2.grad_arrays):
-                            np.testing.assert_allclose(arr1.asnumpy(), arr2.asnumpy(), rtol=1e-3, atol=1e-4)
+                            np.testing.assert_allclose(arr1.asnumpy(), arr2.asnumpy(), rtol=1e-3, atol=1e-3)
 
 
-def gen_broadcast_data(idx):
+def gen_broadcast_data(idx=None):
     # Manually set test cases
     binary_op_data_shape = np.array(
         [[[2, 5, 1, 30, 7], [1, 5, 448, 30, 1]],
@@ -1116,7 +1149,7 @@ def gen_broadcast_data(idx):
         [[1, 24, 103, 17, 18], [1, 24, 1, 1, 1]],
         [[1, 1, 1, 1, 2], [1, 24, 194, 50, 1]],
         [[1, 1, 107, 84, 9], [1, 1, 1, 1, 1]]])
-    if idx < binary_op_data_shape.shape[0]:
+    if idx != None and idx < binary_op_data_shape.shape[0]:
         l_shape = binary_op_data_shape[idx][0]
         r_shape = binary_op_data_shape[idx][1]
     else:
@@ -1211,6 +1244,7 @@ def reduce_op(shape, x):
         assert_allclose(y_2.asnumpy(), x_2, rtol=rtol, atol=atol)
 
 
+@with_seed()
 def test_binary_op():
     a = mx.sym.Variable('a')
     b = mx.sym.Variable('b')
@@ -1237,8 +1271,10 @@ def test_bdiv(a, b):
 
     def test_bmod(a, b):
         c = a % b
-        check_binary_op_forward(c, lambda a, b: a % b, gen_binary_data)
-        check_binary_op_backward(c, lambda g_out, a, b: (g_out, - g_out * (a // b)), gen_binary_data)
+        # '%' is sensitive to the precision of the calculation.  Force numpy to match mxnet's float32.
+        check_binary_op_forward(c, lambda a, b: np.float32(a) % np.float32(b), gen_binary_data)
+        check_binary_op_backward(c,
+            lambda g_out, a, b: (g_out, - g_out * (np.float32(a) // np.float32(b))), gen_binary_data)
 
     def test_bmod_int(a, b):
         c = mx.sym.cast(a, dtype='int32') % mx.sym.cast(b, dtype='int32')
@@ -1266,6 +1302,7 @@ def test_bneq(a, b):
     test_bneq(a, b)
 
 
+@with_seed()
 def test_broadcast_binary_op():
     a = mx.sym.Variable('a')
     b = mx.sym.Variable('b')
@@ -1312,17 +1349,34 @@ def test_bequal(a, b):
                                 mx_nd_func=mx.nd.equal)
         check_binary_op_backward(c, lambda g_out, a, b: (np.zeros_like(a), np.zeros_like(b)), gen_broadcast_data_int)
 
+    # What is the closest pair of elements in the two input arrays?  This is the minimum
+    # workable eps for the finite difference method of gradient calculation.
+    def required_eps(input_data):
+        return abs(input_data[0] - input_data[1]).min()
+
+    # The finite difference method may calculate an incorrect gradient for z = max(x,y) if
+    # the x and y values are closer than eps.  One approach to dealing with this would be to
+    # lower the eps based on the data, but eps values smaller than 2**(-18) were seen to be
+    # problematic because of other multipliers involved in the calculation.  Instead, we simply
+    # regenerate the dataset if it is incompatible with the desired eps.
+    def gen_min_max_input_data(desired_eps):
+        input_data = gen_broadcast_data()
+        while required_eps(input_data) < desired_eps:
+            print('Note: random input values unsuitable for the finite difference method detected, regenerating.')
+            input_data = gen_broadcast_data()
+        return input_data
+
     def test_bmax(a, b):
         c = mx.sym.broadcast_maximum(a, b)
         check_binary_op_forward(c, lambda x, y: np.maximum(x, y), gen_broadcast_data, mx_nd_func=mx.nd.maximum)
-        # pass idx=200 to gen_broadcast_data so that generated ndarrays' sizes are not too big
-        check_numeric_gradient(c, gen_broadcast_data(idx=200), rtol=1e-2, atol=1e-3)
+        eps = 2**(-12)
+        check_numeric_gradient(c, gen_min_max_input_data(eps), numeric_eps=eps, rtol=1e-2, atol=1e-3)
 
     def test_bmin(a, b):
         c = mx.sym.broadcast_minimum(a, b)
         check_binary_op_forward(c, lambda x, y: np.minimum(x, y), gen_broadcast_data, mx_nd_func=mx.nd.minimum)
-        # pass idx=200 to gen_broadcast_data so that generated ndarrays' sizes are not too big
-        check_numeric_gradient(c, gen_broadcast_data(idx=200), rtol=1e-2, atol=1e-3)
+        eps = 2**(-12)
+        check_numeric_gradient(c, gen_min_max_input_data(eps), numeric_eps=eps, rtol=1e-2, atol=1e-3)
 
     test_bplus(a, b)
     test_bminus(a, b)
@@ -1336,6 +1390,7 @@ def test_bmin(a, b):
     test_bmin(a, b)
 
 
+@with_seed()
 def test_run_convolution_dilated_impulse_response(dil=(1,1), kernel_shape=(3,3), verbose=False):
     # Input for spike response
     spike_imgs = np.zeros(shape=(1,1,33,33), dtype=np.float32)
@@ -1400,12 +1455,14 @@ def test_run_convolution_dilated_impulse_response(dil=(1,1), kernel_shape=(3,3),
     assert(out[0,0,16,16] - np.sum(kernel_gradient) - out_orig[0,0,16,16] < 0.001)
 
 
+@with_seed()
 def test_convolution_dilated_impulse_response():
     for dil in [ (1,1), (2,2), (3,3) ]:
         for ks in [ (3,3), (4,4), (2,3), (3,2), (1,1) ]:
             test_run_convolution_dilated_impulse_response(dil=dil, kernel_shape=ks)
 
 
+@with_seed()
 def test_reshape():
 
     def test_reshape_new(src_shape, shape_args, reverse, dst_shape):
@@ -1479,6 +1536,7 @@ def test_reshape_new(src_shape, shape_args, reverse, dst_shape):
     assert_allclose(exe.grad_arrays[0].asnumpy(), out_grad_npy.reshape((5, 4, 3, 7)))
 
 
+@with_seed()
 def test_reduce():
     sample_num = 500
     def test_reduce_inner(numpy_reduce_func, numpy_reduce_grad_func, mx_reduce_sym, nan_prob = 0):
@@ -1565,6 +1623,7 @@ def test_reduce_inner(numpy_reduce_func, numpy_reduce_grad_func, mx_reduce_sym,
                       mx.symbol.min)
 
 
+@with_seed()
 def test_broadcast():
     sample_num = 200
     for i in range(sample_num):
@@ -1597,6 +1656,7 @@ def test_broadcasting_ele(sym_bcast):
         test_broadcasting_ele(sym_bcast_to)
 
 
+@with_seed()
 def test_transpose():
     for ndim in range(1, 7):
         for t in range(5):
@@ -1612,6 +1672,7 @@ def test_transpose():
             assert_allclose(np.transpose(x.asnumpy()), y.asnumpy())
 
 
+@with_seed()
 def test_expand_dims():
     for ndim in range(1, 6):
         for axis in range(-ndim + 1, ndim):
@@ -1623,6 +1684,7 @@ def test_expand_dims():
             assert_allclose(x1.shape, y1.shape)
 
 
+@with_seed()
 def test_crop():
     for ndim in range(1, 6):
         for t in range(5):
@@ -1655,6 +1717,7 @@ def test_crop():
             check_numeric_gradient(vy, [x.asnumpy()])
 
 
+@with_seed()
 def test_slice_axis():
     for ndim in range(1, 6):
         shape = np.random.randint(1, 11, size=(ndim,))
@@ -1698,6 +1761,7 @@ def test_slice_axis():
             assert_allclose(xx + x_grad_npy, xgrad.asnumpy(), atol=1E-5)
 
 
+@with_seed()
 def test_flip():
     for ndim in range(1, 6):
         for t in range(5):
@@ -1709,6 +1773,7 @@ def test_flip():
             assert_allclose(x.asnumpy()[idx], y.asnumpy())
 
 
+@with_seed()
 def test_stn():
     np.set_printoptions(threshold=np.nan)
     num_filter = 2  # conv of loc net
@@ -1750,8 +1815,8 @@ def test_stn():
                     assert_almost_equal(out_grad.asnumpy(), grad_grad[0].asnumpy()[:, :, h//4:h-h//4, w//4:w-w//4], rtol=1e-2, atol=1e-4)
 
 
+@with_seed(1234)
 def test_dot(ctx=default_context()):
-    np.random.seed(1234)
     dtypes = ['float32', 'float64']
 
     # Test normal dot.
@@ -1814,6 +1879,7 @@ def dot_sym_xT_yT(data_type):
             check_numeric_gradient(dot_sym_xT_yT(data_type), [m1_npy.T, m2_npy.T], numeric_eps=1e-1, rtol=2e-2, atol=1e-3)
 
 
+@with_seed()
 def test_batch_dot():
     dtypes = ['float32', 'float64']
 
@@ -1979,8 +2045,11 @@ def correlation_backward(out_grad,tmp1,tmp2,data1,data2,pad_size,kernel_size,str
 
 def unittest_correlation(data_shape,kernel_size,max_displacement,stride1,stride2,pad_size,is_multiply):
 
-    img1 = np.random.random(data_shape)
-    img2 = np.random.random(data_shape)
+    # The python 'correlation_backwards' routine sets the 'sgn' variable to +1 or -1 based
+    # on a comparison of float values from the 'tmp1' and 'tmp2' arrays.  For this to match
+    # the mxnet routine, python must duplicate mxnet's default float32 precision.
+    img1 = np.float32(np.random.random(data_shape))
+    img2 = np.float32(np.random.random(data_shape))
 
     net1 = get_correlation(img1,img2,kernel_size,max_displacement,stride1,stride2,pad_size,is_multiply)
     net2 = get_correlation(img1,img2,kernel_size,max_displacement,stride1,stride2,pad_size,is_multiply )
@@ -2010,6 +2079,7 @@ def unittest_correlation(data_shape,kernel_size,max_displacement,stride1,stride2
     assert_almost_equal(exe1.grad_dict['img2'].asnumpy(), grad2, rtol=1e-3, atol=1e-4)
 
 
+@with_seed()
 def test_correlation():
     unittest_correlation((1,3,10,10), kernel_size = 1,max_displacement = 4,stride1 = 1,stride2 = 1,pad_size = 4,is_multiply = False)
     unittest_correlation((5,1,15,15), kernel_size = 1,max_displacement = 5,stride1 = 1,stride2 = 1,pad_size = 5,is_multiply = False)
@@ -2022,6 +2092,7 @@ def test_correlation():
     unittest_correlation((5,1,11,11), kernel_size = 5,max_displacement = 1,stride1 = 1,stride2 = 1,pad_size = 2,is_multiply = False)
 
 
+@with_seed()
 def test_support_vector_machine_l1_svm():
     xpu = default_context()
     shape = (20, 10)
@@ -2051,6 +2122,7 @@ def test_support_vector_machine_l1_svm():
     assert_almost_equal(grad_np, grad.asnumpy())
 
 
+@with_seed()
 def test_support_vector_machine_l2_svm():
     xpu = default_context()
     shape = (20, 10)
@@ -2081,9 +2153,8 @@ def test_support_vector_machine_l2_svm():
     assert_almost_equal(grad_np, grad.asnumpy())
 
 
+@with_seed(1234)
 def test_roipooling():
-    np.random.seed(1234)
-
     data = mx.symbol.Variable(name='data')
     rois = mx.symbol.Variable(name='rois')
     test = mx.symbol.ROIPooling(data=data, rois=rois, pooled_size=(4, 4), spatial_scale=1)
@@ -2118,6 +2189,7 @@ def check_pad_with_shape(shape, xpu, pad_width, mode):
     check_numeric_gradient(Y, [x.asnumpy()], numeric_eps=1e-2, rtol=1e-2)
 
 
+@with_seed()
 def test_pad():
     shape1 = (2, 3, 3, 5)
     pad1 = (0, 0, 0, 0, 1, 2, 3, 4)
@@ -2169,18 +2241,16 @@ def check_instance_norm_with_shape(shape, xpu):
                            numeric_eps=1e-2, rtol=1e-2, atol=1e-2)
 
 
+@with_seed()
 def test_instance_normalization():
     check_instance_norm_with_shape((1, 1, 1), default_context())
     check_instance_norm_with_shape((2, 1, 2), default_context())
     check_instance_norm_with_shape((2,4,5,6), default_context())
     check_instance_norm_with_shape((3,3,2,3,2,1,1), default_context())
 
-
 def check_l2_normalization(in_shape, mode, ctx=default_context(), norm_eps=1e-10):
     data = mx.symbol.Variable('data')
     out = mx.symbol.L2Normalization(data=data, mode=mode, eps=norm_eps)
-    # TODO(szha): Seeding this masks failures. We need to do a deep dive for failures without this seed.
-    np.random.seed(1234)
     in_data = np.random.uniform(-1, 1, in_shape)
     # calculate numpy results
     if mode == 'channel':
@@ -2210,6 +2280,8 @@ def check_l2_normalization(in_shape, mode, ctx=default_context(), norm_eps=1e-10
     check_numeric_gradient(out, [in_data], numeric_eps=1e-3, rtol=1e-2, atol=1e-3)
 
 
+# TODO(szha): Seeding this masks failures. We need to do a deep dive for failures without this seed.
+@with_seed(1234)
 def test_l2_normalization():
     for mode in ['channel', 'spatial', 'instance']:
         for nbatch in [1, 4]:
@@ -2247,6 +2319,7 @@ def check_sequence_mask(shape, xpu, mask_value):
     check_numeric_gradient(Y, [x.asnumpy(), l.asnumpy()], grad_nodes={'X':'write'},
         numeric_eps=1e-3, rtol=1e-2)
 
+@with_seed()
 def test_sequence_mask():
     shape1 = (4, 2, 2, 3)
     shape2 = (1, 2, 2, 3, 1, 1)
@@ -2319,6 +2392,7 @@ def test_wrapper(arr, xpu, sequence_length=None, use_sequence_length=False):
     assert_array_equal(test_wrapper(arr, xpu, sequence_length=[2, 3], use_sequence_length=True), arr3)
     assert_array_equal(test_wrapper(arr_4, xpu, sequence_length=seq_len_1, use_sequence_length=True), arr_5)
 
+@with_seed()
 def test_sequence_reverse():
     check_sequence_reverse(mx.cpu())
 
@@ -2397,6 +2471,7 @@ def mathematical_core(name, forward_mxnet_call, forward_numpy_call, backward_num
     assert_almost_equal(arr_grad, npout_grad)
 
 
+@with_seed()
 def test_special_functions_using_scipy():
     try:
         from scipy import special as scipy_special
@@ -2428,6 +2503,7 @@ def rounding(name, forward_mxnet_call, forward_numpy_call, data_init=5., grad_in
     assert_almost_equal(out, npout)
 
 
+@with_seed()
 def test_mathematical():
     # rsqrt
     mathematical_core("rsqrt",
@@ -2515,6 +2591,7 @@ def test_mathematical():
     rounding("fix", lambda x: mx.sym.fix(x), lambda x: np.fix(x))
 
 
+@with_seed()
 def test_special_functions_using_scipy():
     try:
         from scipy import special as scipy_special
@@ -2531,6 +2608,7 @@ def test_special_functions_using_scipy():
                      lambda x: scipy_special.psi(x), 0.5, 0.5)
 
 
+@with_seed()
 def test_clip():
     data = mx.symbol.Variable('data')
     shape = (30, 30)
@@ -2541,6 +2619,7 @@ def test_clip():
                             [np.where(data_tmp < 0.6, [1], [0]) * np.where(data_tmp > -0.6, [1], [0])])
 
 
+@with_seed()
 def test_init():
     def test_basic_val_init(sym_func, np_func, shape, dtype):
         x = sym_func(shape=shape, dtype=dtype)
@@ -2571,6 +2650,7 @@ def test_arange():
     test_arange()
 
 
+@with_seed()
 def test_order():
     ctx = default_context()
 
@@ -2671,6 +2751,7 @@ def gt_topk(dat, axis, ret_typ, k, is_ascend):
                                              is_ascend=True)])
 
 
+@with_seed()
 def test_blockgrad():
     a = mx.sym.Variable('a')
     b = mx.sym.BlockGrad(a)
@@ -2681,6 +2762,7 @@ def test_blockgrad():
     exe.backward()  # No error if BlockGrad works
 
 
+@with_seed()
 def test_take():
     def check_output_n_grad(data_shape, idx_shape):
         exe = result.simple_bind(default_context(), a=data_shape,
@@ -2717,6 +2799,7 @@ def check_output_n_grad(data_shape, idx_shape):
             check_output_n_grad(data_shape, idx_shape)
 
 
+@with_seed()
 def test_grid_generator():
     # transform_type =  affine
     test_case = [(20,21),(4,3),(6,12),(15,17)]
@@ -2784,9 +2867,8 @@ def test_grid_generator():
         exe_add.backward(mx.nd.array(out_grad))
         assert_almost_equal(exe_add.grad_dict['flow'].asnumpy(), grad_est + flow_grad_npy, rtol=1e-3, atol=1e-5)
 
-
+@with_seed(1234)
 def test_bilinear_sampler():
-    np.random.seed(1234)
     from math import floor
 
     def between(x, lowerbound, upperbound):
@@ -2945,6 +3027,7 @@ def bilinear_backward_numpy(out_grad, data, grid):
             assert_almost_equal(exe_addto.grad_dict['grid'].asnumpy(), grid_grad + grid_initial_grid, rtol=1e-3,atol=1e-5)
 
 
+@with_seed()
 def test_index2d():
     for _ in range(30):
         n = np.random.randint(1, 100)
@@ -2955,6 +3038,7 @@ def test_index2d():
         assert_almost_equal(r.asnumpy(), data.asnumpy()[np.arange(n), x.asnumpy()])
 
 
+@with_seed()
 def test_cast():
     for srctype in [np.int32, np.float32, np.float16]:
         for dsttype in [np.float32, np.int32, np.float16]:
@@ -2971,6 +3055,7 @@ def test_cast():
             assert_almost_equal(exe.grad_arrays[0].asnumpy(), X.astype(dsttype).astype(srctype), rtol=1e-3)
 
 
+@with_seed()
 def test_repeat():
     def test_repeat_forward():
         ndim_max = 6 # max number of dims of the ndarray
@@ -3045,6 +3130,7 @@ def test_repeat_numeric_gradient():
     test_repeat_numeric_gradient()
 
 
+@with_seed()
 def test_reverse():
     data = mx.symbol.Variable('data')
     shape = (5, 5, 5)
@@ -3056,6 +3142,7 @@ def test_reverse():
     check_symbolic_backward(test, [data_tmp], [grad], [grad[:, ::-1, ::-1]])
 
 
+@with_seed()
 def test_tile():
     def test_normal_case():
         ndim_max = 3 # max number of dims of the ndarray
@@ -3151,6 +3238,7 @@ def test_tile_numeric_gradient():
     test_tile_numeric_gradient()
 
 
+@with_seed()
 def test_one_hot():
     def test_normal_case(index_type=np.int32):
         ndim_max = 6
@@ -3207,6 +3295,7 @@ def test_zero_depth():
     test_zero_depth()
 
 
+@with_seed()
 def test_where():
     def get_forward_expected_output(condition, x, y):
         original_shape = x.shape
@@ -3343,6 +3432,7 @@ def test_where_numeric_gradient(shape, same_shape):
     test_where_numeric_gradient((5, 7, 9), False)
 
 
+@with_seed()
 def test_new_softmax():
     for ndim in range(1, 5):
         for _ in range(5):
@@ -3354,6 +3444,7 @@ def test_new_softmax():
             check_numeric_gradient(sym, [data], rtol=0.05, atol=1e-3)
 
 
+@with_seed()
 def test_log_softmax():
     for ndim in range(1, 5):
         for _ in range(5):
@@ -3365,6 +3456,7 @@ def test_log_softmax():
             check_numeric_gradient(sym, [data], rtol=0.05, atol=1e-3)
 
 
+@with_seed()
 def test_pick():
     def test_pick_helper(index_type=np.int32):
         for _ in range(100):
@@ -3422,6 +3514,7 @@ def check_ctc_loss(acts, labels, loss_truth):
     check_numeric_gradient(ctc, [acts, labels], grad_nodes=['input'], rtol=0.05, atol=1e-3)
 
 
+@with_seed()
 def test_ctc_loss():
     # Test 1: check that batches are same + check against Torch WarpCTC
     acts = np.array([
@@ -3442,6 +3535,7 @@ def test_ctc_loss():
     check_ctc_loss(acts2, labels2, true_loss)
 
 
+@with_seed()
 def test_ctc_loss_grad():
     def check_ctc_loss_grad(blank_label): # from tf
         vocab_size = 5
@@ -3525,6 +3619,7 @@ def check_ctc_loss_grad(blank_label): # from tf
     check_ctc_loss_grad('last')
 
 
+@with_seed()
 def test_quantization_op():
     min0 = mx.nd.array([0.0])
     max0 = mx.nd.array([1.0])
@@ -3539,34 +3634,46 @@ def test_quantization_op():
     assert same(a_.asnumpy(),  a_real.asnumpy())
 
 
+@with_seed()
 def test_reciprocal_op():
+    eps = 2**(-11)
     data_tmp = np.random.rand(3, 4) * 10 - 5
-    # Avoid possible division by 0 errors
-    data_tmp[data_tmp == 0] = 1.0
+    # Avoid possible division by 0 errors and finite difference method inaccuracies.
+    # Factor of 6 below set empirically, depends on eps.
+    data_tmp[abs(data_tmp) < 6*eps] = 1.0
     data = mx.symbol.Variable('data')
     test = mx.sym.reciprocal(data)
 
-    check_numeric_gradient(test, [data_tmp])
+    check_numeric_gradient(test, [data_tmp], numeric_eps = eps)
     check_symbolic_forward(test, [data_tmp], [np.reciprocal(data_tmp)])
 
+@with_seed()
 def test_cbrt_op():
+    eps = 2**(-11)
     data_tmp = np.random.rand(3, 4) * 10 - 5
+    # Avoid finite difference method inaccuracies due to infinite gradient
+    # at the origin.  Factor of 4 below set empirically, depends on eps.
+    data_tmp[abs(data_tmp) < 4*eps] = 1.0
     data = mx.symbol.Variable('data')
     test = mx.sym.cbrt(data)
 
-    check_numeric_gradient(test, [data_tmp])
+    check_numeric_gradient(test, [data_tmp], numeric_eps=eps)
     check_symbolic_forward(test, [data_tmp], [np.cbrt(data_tmp)])
 
+@with_seed()
 def test_rcbrt_op():
+    eps = 2**(-11)
     data_tmp = np.random.rand(3, 4) * 10 - 5
-    # Avoid possible division by 0 errors
-    data_tmp[data_tmp == 0] = 1.0
+    # Avoid possible division by 0 errors and finite difference method inaccuracies.
+    # Factor of 4 below set empirically, depends on eps.
+    data_tmp[abs(data_tmp) < 4*eps] = 1.0
     data = mx.symbol.Variable('data')
     test = mx.sym.rcbrt(data)
 
-    check_numeric_gradient(test, [data_tmp])
+    check_numeric_gradient(test, [data_tmp], numeric_eps = eps)
     check_symbolic_forward(test, [data_tmp], [1/np.cbrt(data_tmp)])
 
+@with_seed()
 def test_custom_op():
     class Sqr(mx.operator.CustomOp):
         def forward(self, is_train, req, in_data, out_data, aux):
@@ -3614,6 +3721,7 @@ def create_operator(self, ctx, shapes, dtypes):
         y.backward()
 
 
+@with_seed()
 def test_psroipooling():
     for num_rois in [1, 2]:
         for num_classes, num_group in itertools.product([2, 3], [2, 3]):
@@ -3639,6 +3747,7 @@ def test_psroipooling():
                                                grad_nodes=grad_nodes, ctx=mx.gpu(0))
 
 
+@with_seed()
 def test_deformable_convolution():
     for num_batch in [1, 2]:
         for num_channel_data, num_deformable_group in itertools.product([4, 8], [1, 2]):
@@ -3676,6 +3785,7 @@ def test_deformable_convolution():
                                                    grad_nodes=grad_nodes, ctx=mx.gpu(0))
 
 
+@with_seed(1234)
 def test_deformable_psroipooling():
     for num_rois in [1, 2]:
         for num_classes, num_group in itertools.product([2, 3], [2, 3]):
@@ -3699,13 +3809,13 @@ def test_deformable_psroipooling():
                                                                pooled_size=num_group, output_dim=num_classes,
                                                                trans_std=0.1, no_trans=False, name='test_op')
                     if grad_nodes[0] == 'offset_data':
-                        # wider tolerance needed for coordinate differential
-                        rtol, atol = 1.0, 1e-2
+                        # wider tolerance needed for coordinate differential, smaller eps
+                        rtol, atol, eps = 1.0, 1e-2, 2**(-14)
                     else:
-                        rtol, atol = 1e-2, 1e-3
+                        rtol, atol, eps = 1e-2, 1e-3, 1e-3
                     # By now we only have gpu implementation
                     if mx.Context.default_ctx.device_type == 'gpu':
-                        check_numeric_gradient(op, [im_data, rois_data, offset_data], rtol=rtol, atol=atol,
+                        check_numeric_gradient(op, [im_data, rois_data, offset_data], numeric_eps=eps, rtol=rtol, atol=atol,
                                                grad_nodes=grad_nodes, ctx=mx.gpu(0))
 
 
@@ -3734,6 +3844,7 @@ def _make_lower_triangle_symm(a, ndims, m, dtype=np.float32):
     lt_mask = mx.sym.reshape(lt_mask, shape=shp)
     return mx.sym.broadcast_mul(a, lt_mask)
 
+@with_seed(42)
 def test_laop():
     dtype = np.float64
     rtol_fw = 1e-7
@@ -3762,8 +3873,6 @@ def test_laop():
     shape2 = (3, 2)
     shape3 = (3, 3)
     shape4 = (2, 2)
-    #Ensure that ithis tests don't get changed by other calls to random.
-    np.random.seed(42)
     data_in1 = np.random.uniform(1, 10, shape1)
     data_in2 = np.random.uniform(1, 10, shape2)
     data_in3 = np.random.uniform(1, 10, shape3)
@@ -4012,8 +4121,8 @@ def _syevd_combined_symbol(a):
                                    transpose_b=False, name='Ut_L_U')
     return mx.sym.Group([u_ut, ut_lam_u])
 
+@with_seed(3961345194)
 def test_laop_2():
-    np.random.seed(1896893923)
     dtype = np.float64
     rtol_fw = 1e-7
     atol_fw = 1e-9
@@ -4135,13 +4244,12 @@ def _syevd_backward(grad_u, grad_l, u, l):
     temp3 = np.dot(u.T, temp2)
     return np.dot(temp3, u)
 
+@with_seed(3961345194)
 def test_laop_3():
     # Currently disabled on GPU as syevd needs cuda8
     # and MxNet builds use cuda 7.5
     if not (default_context() == mx.cpu()):
         return
-
-    np.random.seed(1896893923)
     dtype = np.float64
     rtol_fw = 1e-6
     atol_fw = 1e-6
@@ -4152,6 +4260,7 @@ def test_laop_3():
     grad_check = 1
 
     data1 = mx.symbol.Variable('data1')
+
     check_fw = lambda sym, location, expected :\
         check_symbolic_forward(sym, location, expected, rtol=rtol_fw,
                                atol=atol_fw, dtype=dtype)
@@ -4203,13 +4312,12 @@ def test_laop_3():
             check_grad(test_syevd_l_4, [a_batch])
 
 
+@with_seed(3961345194)
 def test_laop_4():
     # Currently disabled on GPU as syevd needs cuda8
     # and MxNet builds use cuda 7.5
     if not (default_context() == mx.cpu()):
         return
-
-    np.random.seed(1896893923)
     rtol_fw = 1e-6
     atol_fw = 1e-6
 
@@ -4231,6 +4339,7 @@ def test_laop_4():
     check_fw(test_syevd, [a_np], [u_np, l_np], np.float32)
 
 
+@with_seed()
 def test_stack():
     for _ in range(100):
         ndim = random.randint(1, 5)
@@ -4247,6 +4356,7 @@ def test_stack():
         check_numeric_gradient(out, inputs)
 
 
+@with_seed()
 def test_dropout():
     # test dropout
     x = mx.sym.var('data')
@@ -4284,6 +4394,7 @@ def test_dropout():
     assert (exe.grad_arrays[0].asnumpy() == exe.outputs[0].asnumpy()).all()
 
 
+@with_seed()
 def test_scatter_gather_nd():
     def check(data, idx):
         data.attach_grad()
@@ -4365,8 +4476,8 @@ def np_smooth_l1_grad(x, sigma):
 # - Forward: Comparison to NumPy (several dtype)
 # - Backward: Comparison to NumPy (several dtype)
 # - Finite difference tests (only dtype = float64)
+@with_seed(192837465)
 def test_unary_math_operators():
-    np.random.seed(192837465)
     have_scipy = True
     try:
         from scipy import special as scipy_special
@@ -4568,8 +4679,8 @@ def finite_diff_binary_op(
 # - Forward: Comparison to NumPy (several dtype)
 # - Backward: Comparison to NumPy (several dtype)
 # - Finite difference tests (only dtype = float64)
+@with_seed(192837465)
 def test_binary_math_operators():
-    np.random.seed(192837465)
     shape=(9, 10)
     dtype_l = [np.float64, np.float32, np.float16]
     rtol_l = [1e-7, 1e-6, 1e-2]
@@ -4603,6 +4714,7 @@ def test_binary_math_operators():
             num_eps)
 
 
+@with_seed()
 def test_softmax():
     check_softmax_with_shape((3, 4), default_context(), preserve_shape=False)
     check_softmax_with_shape((3, 4), default_context(), preserve_shape=True)
diff --git a/tests/python/unittest/test_optimizer.py b/tests/python/unittest/test_optimizer.py
index 1a26434015..5cddfb8495 100644
--- a/tests/python/unittest/test_optimizer.py
+++ b/tests/python/unittest/test_optimizer.py
@@ -22,7 +22,9 @@
 from nose.tools import raises
 import math
 from mxnet.test_utils import *
+from common import *
 
+@with_seed()
 def test_learning_rate():
     o1 = mx.optimizer.Optimizer(learning_rate=0.01)
     o1.set_learning_rate(0.2)
@@ -36,12 +38,14 @@ def test_learning_rate():
 
 
 @raises(UserWarning)
+@with_seed()
 def test_learning_rate_expect_user_warning():
     lr_s = lr_scheduler.FactorScheduler(step=1)
     o = mx.optimizer.Optimizer(lr_scheduler=lr_s, learning_rate=0.3)
     o.set_learning_rate(0.5)
 
 
+@with_seed()
 def test_lr_wd_mult():
     data = mx.sym.Variable('data')
     bias = mx.sym.Variable('fc1_bias', lr_mult=1.0)
@@ -198,8 +202,8 @@ def update(self, index, weight, grad, state):
     def update_multi_precision(self, index, weight, grad, state):
         self.update(index, weight, grad, state)
 
+@with_seed()
 def test_sgd():
-    mx.random.seed(0)
     opt1 = PySGD
     opt2 = mx.optimizer.SGD
     shape = (3, 4, 5)
@@ -306,8 +310,8 @@ def update(self, index, weight, grad, state):
                   mom[row] = self.momentum*mom[row] - lr*wd*weight[row] - lr*self.rescale_grad*grad[row]
                   weight[row] += mom[row]
 
+@with_seed()
 def test_sparse_sgd():
-    mx.random.seed(0)
     opt1 = PySparseSGD
     opt2 = mx.optimizer.SGD
     shape = (3, 4, 5)
@@ -404,8 +408,8 @@ def update(self, index, weight, grad, state):
             weight[row] -= lr*mean[row]/(mx.nd.sqrt(variance[row]) + self.epsilon)
 
 
+@with_seed()
 def test_adam():
-    mx.random.seed(0)
     opt1 = PyAdam
     opt2 = mx.optimizer.Adam
     shape = (3, 4, 5)
@@ -538,8 +542,8 @@ def update(self, index, weight, grad, state):
              mx.ndarray.clip(weight, -self.clip_weights, self.clip_weights, out=weight)
 
 @unittest.skip("Test fails intermittently. Temporarily disabled until fixed. Tracked at https://github.com/apache/incubator-mxnet/issues/8230")
+@with_seed(0)
 def test_rms():
-    mx.random.seed(0)
     opt1 = PyRMSProp
     opt2 = mx.optimizer.RMSProp
     shape = (3, 4, 5)
@@ -624,8 +628,8 @@ def update(self, index, weight, grad, state):
             weight[row] = (mx.nd.sign(dn[row]) * self.lamda1 - dn[row]) / \
                           ((self.beta + mx.nd.sqrt(n[row])) / lr + wd) * (mx.nd.abs(dn[row]) > self.lamda1)
 
+@with_seed()
 def test_ftrl():
-    mx.random.seed(0)
     opt1 = PyFtrl
     opt2 = mx.optimizer.Ftrl
     shape = (3, 4, 5)
diff --git a/tests/python/unittest/test_random.py b/tests/python/unittest/test_random.py
index a67e2d1113..9d491dea86 100644
--- a/tests/python/unittest/test_random.py
+++ b/tests/python/unittest/test_random.py
@@ -18,6 +18,7 @@
 import os
 import mxnet as mx
 import numpy as np
+from common import *
 
 def same(a, b):
     return np.sum(a != b) == 0
@@ -118,7 +119,7 @@ def check_with_device(device, dtype):
         ret1 = ndop(**params).asnumpy()
         mx.random.seed(128)
         ret2 = ndop(**params).asnumpy()
-        assert device.device_type == 'gpu' or same(ret1, ret2), \
+        assert same(ret1, ret2), \
                 "ndarray test: `%s` should give the same result with the same seed" % name
 
         for check_name, check_func, tol in symbdic['checks']:
@@ -131,7 +132,7 @@ def check_with_device(device, dtype):
         ret1 = ndop(**params).asnumpy()
         mx.random.seed(128)
         ret2 = ndop(**params).asnumpy()
-        assert device.device_type == 'gpu' or same(ret1, ret2), \
+        assert same(ret1, ret2), \
                 "ndarray test: `%s` should give the same result with the same seed" % name
         for i in range(2):
             for j in range(2):
@@ -157,7 +158,7 @@ def check_with_device(device, dtype):
         mx.random.seed(128)
         yexec.forward()
         un2 = (yexec.outputs[0] - x).copyto(device)
-        assert device.device_type == 'gpu' or same(un1.asnumpy(), un2.asnumpy()), \
+        assert same(un1.asnumpy(), un2.asnumpy()), \
                 "symbolic test: `%s` should give the same result with the same seed" % name
 
         ret1 = un1.asnumpy()
@@ -187,18 +188,21 @@ def check_with_device(device, dtype):
                 for check_name, check_func, tol in symbdic['checks']:
                     assert np.abs(check_func(samples, params)) < tol, "symbolic test: %s check for `%s` did not pass" % (check_name, name)
 
+@with_seed()
 def test_random():
     check_with_device(mx.context.current_context(), 'float16')
     check_with_device(mx.context.current_context(), 'float32')
     check_with_device(mx.context.current_context(), 'float64')
 
 
+@with_seed()
 def test_sample_multinomial():
     x = mx.nd.array([[0,1,2,3,4],[4,3,2,1,0]])/10.0
     dx = mx.nd.ones_like(x)
     mx.contrib.autograd.mark_variables([x], [dx])
+    samples = 5000
     with mx.autograd.record():
-        y, prob = mx.nd.random.multinomial(x, shape=1000, get_prob=True)
+        y, prob = mx.nd.random.multinomial(x, shape=samples, get_prob=True)
         r = prob * 5
         r.backward()
 
@@ -206,15 +210,15 @@ def test_sample_multinomial():
     x = x.asnumpy()
     for i in range(x.shape[0]):
 
-        freq = np.bincount(y[i], minlength=5)/1000.0*x[i].sum()
-        mx.test_utils.assert_almost_equal(freq, x[i], rtol=0.25)
+        freq = np.bincount(y[i], minlength=5)/np.float32(samples)*x[i].sum()
+        mx.test_utils.assert_almost_equal(freq, x[i], rtol=0.20)
         rprob = x[i][y[i]]/x[i].sum()
         mx.test_utils.assert_almost_equal(np.log(rprob), prob.asnumpy()[i])
 
         real_dx = np.zeros((5,))
-        for j in range(1000):
+        for j in range(samples):
             real_dx[y[i][j]] += 5.0 / rprob[j]
-        mx.test_utils.assert_almost_equal(real_dx, dx.asnumpy()[i])
+        mx.test_utils.assert_almost_equal(real_dx, dx.asnumpy()[i], rtol=1e-4)
 
 
 if __name__ == '__main__':
diff --git a/tests/python/unittest/test_recordio.py b/tests/python/unittest/test_recordio.py
index 7de582e236..3e1a5bdde1 100644
--- a/tests/python/unittest/test_recordio.py
+++ b/tests/python/unittest/test_recordio.py
@@ -22,7 +22,9 @@
 import tempfile
 import random
 import string
+from common import *
 
+@with_seed()
 def test_recordio():
     frec = tempfile.mktemp()
     N = 255
@@ -43,6 +45,7 @@ def test_recordio():
         else:
             assert res == bytes(str(chr(i)), 'utf-8')
 
+@with_seed()
 def test_indexed_recordio():
     fidx = tempfile.mktemp()
     frec = tempfile.mktemp()
@@ -67,6 +70,7 @@ def test_indexed_recordio():
         else:
             assert res == bytes(str(chr(i)), 'utf-8')
 
+@with_seed()
 def test_recordio_pack_label():
     frec = tempfile.mktemp()
     N = 255
diff --git a/tests/python/unittest/test_sparse_ndarray.py b/tests/python/unittest/test_sparse_ndarray.py
index 0bbb5ffaaa..a3136f4430 100644
--- a/tests/python/unittest/test_sparse_ndarray.py
+++ b/tests/python/unittest/test_sparse_ndarray.py
@@ -20,6 +20,7 @@
 from mxnet.ndarray import NDArray
 from mxnet.test_utils import *
 from mxnet.base import mx_real_t
+from common import *
 from numpy.testing import assert_allclose
 import numpy.random as rnd
 
@@ -30,6 +31,7 @@ def sparse_nd_ones(shape, stype):
     return mx.nd.ones(shape).tostype(stype)
 
 
+@with_seed()
 def test_sparse_nd_elemwise_add():
     def check_sparse_nd_elemwise_binary(shapes, stypes, f, g):
         # generate inputs
@@ -55,6 +57,7 @@ def check_sparse_nd_elemwise_binary(shapes, stypes, f, g):
         check_sparse_nd_elemwise_binary(shape, ['row_sparse', 'row_sparse'], op, g)
 
 
+@with_seed()
 def test_sparse_nd_copy():
     def check_sparse_nd_copy(from_stype, to_stype, shape):
         from_nd = rand_ndarray(shape, from_stype)
@@ -76,6 +79,7 @@ def check_sparse_nd_copy(from_stype, to_stype, shape):
     check_sparse_nd_copy('row_sparse', 'default', shape_3d)
     check_sparse_nd_copy('default', 'row_sparse', shape_3d)
 
+@with_seed()
 def test_sparse_nd_basic():
     def check_sparse_nd_basic_rsp():
         storage_type = 'row_sparse'
@@ -88,6 +92,7 @@ def check_sparse_nd_basic_rsp():
     check_sparse_nd_basic_rsp()
 
 
+@with_seed()
 def test_sparse_nd_setitem():
     def check_sparse_nd_setitem(stype, shape, dst):
         x = mx.nd.zeros(shape=shape, stype=stype)
@@ -104,6 +109,7 @@ def check_sparse_nd_setitem(stype, shape, dst):
         check_sparse_nd_setitem(stype, shape, np.ones(shape))
 
 
+@with_seed()
 def test_sparse_nd_slice():
     def check_sparse_nd_csr_slice(shape):
         stype = 'csr'
@@ -117,7 +123,7 @@ def check_sparse_nd_csr_slice(shape):
         assert same(A[:end].asnumpy(), A2[:end])
         ind = rnd.randint(-shape[0], shape[0] - 1)
         assert same(A[ind].asnumpy(), A2[ind][np.newaxis, :])
-    
+
     def check_slice_nd_csr_fallback(shape):
         stype = 'csr'
         A, _ = rand_sparse_ndarray(shape, stype)
@@ -133,6 +139,7 @@ def check_slice_nd_csr_fallback(shape):
     check_slice_nd_csr_fallback(shape)
 
 
+@with_seed()
 def test_sparse_nd_equal():
     for stype in ['row_sparse', 'csr']:
         shape = rand_shape_2d()
@@ -144,6 +151,7 @@ def test_sparse_nd_equal():
         assert (z.asnumpy() == np.ones(shape)).all()
 
 
+@with_seed()
 def test_sparse_nd_not_equal():
     for stype in ['row_sparse', 'csr']:
         shape = rand_shape_2d()
@@ -155,6 +163,7 @@ def test_sparse_nd_not_equal():
         assert (z.asnumpy() == np.zeros(shape)).all()
 
 
+@with_seed()
 def test_sparse_nd_greater():
     for stype in ['row_sparse', 'csr']:
         shape = rand_shape_2d()
@@ -168,6 +177,7 @@ def test_sparse_nd_greater():
         assert (z.asnumpy() == np.zeros(shape)).all()
 
 
+@with_seed()
 def test_sparse_nd_greater_equal():
     for stype in ['row_sparse', 'csr']:
         shape = rand_shape_2d()
@@ -183,6 +193,7 @@ def test_sparse_nd_greater_equal():
         assert (z.asnumpy() == np.ones(shape)).all()
 
 
+@with_seed()
 def test_sparse_nd_lesser():
     for stype in ['row_sparse', 'csr']:
         shape = rand_shape_2d()
@@ -196,6 +207,7 @@ def test_sparse_nd_lesser():
         assert (z.asnumpy() == np.zeros(shape)).all()
 
 
+@with_seed()
 def test_sparse_nd_lesser_equal():
     for stype in ['row_sparse', 'csr']:
         shape = rand_shape_2d()
@@ -211,6 +223,7 @@ def test_sparse_nd_lesser_equal():
         assert (z.asnumpy() == np.ones(shape)).all()
 
 
+@with_seed()
 def test_sparse_nd_binary():
     N = 3
     def check_binary(fn, stype):
@@ -246,6 +259,7 @@ def check_binary(fn, stype):
         check_binary(lambda x, y: x == y, stype)
 
 
+@with_seed()
 def test_sparse_nd_binary_rop():
     N = 3
     def check(fn, stype):
@@ -270,6 +284,8 @@ def check(fn, stype):
         check(lambda x: 0.5 <= x, stype)
         check(lambda x: 0.5 == x, stype)
 
+
+@with_seed()
 def test_sparse_nd_binary_iop():
     N = 3
     def check_binary(fn, stype):
@@ -298,6 +314,8 @@ def inplace_mul(x, y):
         for fn in fns:
             check_binary(fn, stype)
 
+
+@with_seed()
 def test_sparse_nd_negate():
     def check_sparse_nd_negate(shape, stype):
         npy = np.random.uniform(-10, 10, rand_shape_2d())
@@ -315,6 +333,8 @@ def check_sparse_nd_negate(shape, stype):
     for stype in stypes:
         check_sparse_nd_negate(shape, stype)
 
+
+@with_seed()
 def test_sparse_nd_broadcast():
     sample_num = 1000
     # TODO(haibin) test with more than 2 dimensions
@@ -342,6 +362,7 @@ def test_broadcast_to(stype):
         test_broadcast_to(stype)
 
 
+@with_seed()
 def test_sparse_nd_transpose():
     npy = np.random.uniform(-10, 10, rand_shape_2d())
     stypes = ['csr', 'row_sparse']
@@ -349,6 +370,8 @@ def test_sparse_nd_transpose():
         nd = mx.nd.array(npy).tostype(stype)
         assert_almost_equal(npy.T, (nd.T).asnumpy())
 
+
+@with_seed()
 def test_sparse_nd_storage_fallback():
     def check_output_fallback(shape):
         ones = mx.nd.ones(shape)
@@ -371,6 +394,8 @@ def check_fallback_with_temp_resource(shape):
     check_input_fallback(shape)
     check_fallback_with_temp_resource(shape)
 
+
+@with_seed()
 def test_sparse_nd_random():
     """ test sparse random operator on cpu """
     # gpu random operator doesn't use fixed seed
@@ -381,15 +406,14 @@ def test_sparse_nd_random():
     for fn in fns:
         rsp_out = mx.nd.zeros(shape=shape, stype='row_sparse')
         dns_out = mx.nd.zeros(shape=shape, stype='default')
-        mx.random.seed(0)
-        np.random.seed(0)
-        fn(shape=shape, out=dns_out)
-        mx.random.seed(0)
-        np.random.seed(0)
-        fn(shape=shape, out=rsp_out)
+        with random_seed(0):
+            fn(shape=shape, out=dns_out)
+        with random_seed(0):
+            fn(shape=shape, out=rsp_out)
         assert_almost_equal(dns_out.asnumpy(), rsp_out.asnumpy())
 
 
+@with_seed()
 def test_sparse_nd_astype():
     stypes = ['row_sparse', 'csr']
     for stype in stypes:
@@ -398,8 +422,8 @@ def test_sparse_nd_astype():
         assert(y.dtype == np.int32), y.dtype
 
 
+@with_seed(0)
 def test_sparse_nd_pickle():
-    np.random.seed(0)
     repeat = 1
     dim0 = 40
     dim1 = 40
@@ -418,8 +442,8 @@ def test_sparse_nd_pickle():
                 assert same(a.asnumpy(), b.asnumpy())
 
 
+@with_seed(0)
 def test_sparse_nd_save_load():
-    np.random.seed(0)
     repeat = 1
     stypes = ['default', 'row_sparse', 'csr']
     stype_dict = {'default': NDArray, 'row_sparse': RowSparseNDArray, 'csr': CSRNDArray}
@@ -450,6 +474,8 @@ def test_sparse_nd_save_load():
             assert same(x.asnumpy(), y.asnumpy())
     os.remove(fname)
 
+
+@with_seed()
 def test_sparse_nd_unsupported():
     nd = mx.nd.zeros((2,2), stype='row_sparse')
     fn_slice = lambda x: x._slice(None, None)
@@ -463,6 +489,8 @@ def test_sparse_nd_unsupported():
         except:
             pass
 
+
+@with_seed()
 def test_create_csr():
     def check_create_csr_from_nd(shape, density, dtype):
         matrix = rand_ndarray(shape, 'csr', density)
@@ -518,6 +546,7 @@ def assert_csr_almost_equal(nd, sp):
         check_create_csr_from_scipy(shape, density, mx.nd.array)
 
 
+@with_seed()
 def test_create_row_sparse():
     dim0 = 50
     dim1 = 50
@@ -534,6 +563,8 @@ def test_create_row_sparse():
         rsp_copy = mx.nd.array(rsp_created)
         assert(same(rsp_copy.asnumpy(), rsp_created.asnumpy()))
 
+
+@with_seed()
 def test_create_sparse_nd_infer_shape():
     def check_create_csr_infer_shape(shape, density, dtype):
         try:
@@ -576,6 +607,8 @@ def check_create_rsp_infer_shape(shape, density, dtype):
         check_create_rsp_infer_shape(shape, density, dtype)
         check_create_rsp_infer_shape(shape_3d, density, dtype)
 
+
+@with_seed()
 def test_create_sparse_nd_from_dense():
     def check_create_from_dns(shape, f, dense_arr, dtype, default_dtype, ctx):
         arr = f(dense_arr, dtype=dtype, ctx=ctx)
@@ -598,6 +631,8 @@ def check_create_from_dns(shape, f, dense_arr, dtype, default_dtype, ctx):
                             else np.float32
             check_create_from_dns(shape, f, dense_arr, dtype, default_dtype, ctx)
 
+
+@with_seed()
 def test_create_sparse_nd_from_sparse():
     def check_create_from_sp(shape, f, sp_arr, dtype, src_dtype, ctx):
         arr = f(sp_arr, dtype=dtype, ctx=ctx)
@@ -629,6 +664,8 @@ def check_create_from_sp(shape, f, sp_arr, dtype, src_dtype, ctx):
     for sp_arr in rsp_arrs:
         check_create_from_sp(shape, f_rsp, sp_arr, dtype, src_dtype, ctx)
 
+
+@with_seed()
 def test_create_sparse_nd_empty():
     def check_empty(shape, stype):
         arr = mx.nd.empty(shape, stype=stype)
@@ -668,6 +705,8 @@ def check_rsp_empty(shape, dtype, ctx):
     check_rsp_empty(shape, dtype, ctx)
     check_rsp_empty(shape_3d, dtype, ctx)
 
+
+@with_seed()
 def test_synthetic_dataset_generator():
     def test_powerlaw_generator(csr_arr, final_row=1):
         """Test power law distribution
@@ -700,19 +739,23 @@ def test_powerlaw_generator(csr_arr, final_row=1):
     test_powerlaw_generator(csr_arr_big, final_row=4)
     test_powerlaw_generator(csr_arr_square, final_row=6)
 
+
+@with_seed()
 def test_sparse_nd_exception():
     """ test invalid sparse operator will throw a exception """
     a = mx.nd.ones((2,2))
-    assert_exception(mx.nd.sparse.retain, mx.base.MXNetError,
-                     a, invalid_arg="garbage_value")
-    assert_exception(mx.nd.sparse.csr_matrix, ValueError,
-                     a, shape=(3,2))
-    assert_exception(mx.nd.sparse.csr_matrix, ValueError,
-                     (2,2), shape=(3,2))
-    assert_exception(mx.nd.sparse.row_sparse_array, ValueError,
-                     (2,2), shape=(3,2))
-    assert_exception(mx.nd.sparse.zeros, ValueError,
-                     "invalid_stype", (2,2))
+    # Keep this test from adding stack backtraces to the log file.
+    with discard_stderr():
+        assert_exception(mx.nd.sparse.retain, mx.base.MXNetError,
+                         a, invalid_arg="garbage_value")
+        assert_exception(mx.nd.sparse.csr_matrix, ValueError,
+                         a, shape=(3,2))
+        assert_exception(mx.nd.sparse.csr_matrix, ValueError,
+                         (2,2), shape=(3,2))
+        assert_exception(mx.nd.sparse.row_sparse_array, ValueError,
+                         (2,2), shape=(3,2))
+        assert_exception(mx.nd.sparse.zeros, ValueError,
+                         "invalid_stype", (2,2))
 
 
 if __name__ == '__main__':
diff --git a/tests/python/unittest/test_sparse_operator.py b/tests/python/unittest/test_sparse_operator.py
index b28174951e..c3ec17023a 100644
--- a/tests/python/unittest/test_sparse_operator.py
+++ b/tests/python/unittest/test_sparse_operator.py
@@ -16,6 +16,7 @@
 # under the License.
 
 from mxnet.test_utils import *
+from common import *
 import random
 import warnings
 
@@ -151,6 +152,7 @@ def gen_rsp_random_indices(shape, density=.5, force_indices=None):
 def all_zero(var):
     return 0
 
+@with_seed()
 def test_elemwise_binary_ops():
     def test_elemwise_binary_op(name, lhs_stype, rhs_stype, shape,
                                 forward_mxnet_call, forward_numpy_call, backward_numpy_call,
@@ -504,6 +506,7 @@ def check_elemwise_binary_ops(lhs_stype, rhs_stype, shape,
                                                   rhs_density=rhs_density,
                                                   ograd_density=ograd_density)
 
+@with_seed()
 def test_elemwise_csr_same_zeros():
     # Zeroes
     a = mx.nd.sparse.zeros('csr', (1,1))
@@ -679,6 +682,7 @@ def check_sparse_mathematical_core(name, stype,
         assert_almost_equal(arr_grad, input_grad, equal_nan=True)
 
 
+@with_seed()
 def test_sparse_mathematical_core():
     def util_sign(a):
         if np.isclose(a, -0, rtol=1.e-3, atol=1.e-3, equal_nan=True):
@@ -1011,7 +1015,6 @@ def check_mathematical_core(stype, output_grad_stype=None,
 
             try:
                 from scipy import special as scipy_special
-                import_succeeded = True
                 # gamma
                 check_sparse_mathematical_core("gamma", stype,
                                                lambda x: mx.sym.sparse.gamma(x),
@@ -1031,11 +1034,8 @@ def check_mathematical_core(stype, output_grad_stype=None,
                                                force_overlap=force_overlap,
                                                density=density, ograd_density=ograd_density)
 
-            except:
-                if import_succeeded == False:
-                    print("Could not import scipy. Skipping unit tests for special functions")
-                else:
-                    raise
+            except ImportError:
+                print("Could not import scipy. Skipping unit tests for special functions")
 
     for i in range(1):
         print("pass", i)
@@ -1101,6 +1101,7 @@ def check_mathematical_core(stype, output_grad_stype=None,
 
 
 
+@with_seed()
 def test_elemwise_add_ex():
     def check_elemwise_add_ex(lhs_stype, rhs_stype, shape, lhs_grad_stype=None, rhs_grad_stype=None):
         lhs = mx.symbol.Variable('lhs', stype=lhs_stype)
@@ -1130,6 +1131,7 @@ def check_elemwise_add_ex(lhs_stype, rhs_stype, shape, lhs_grad_stype=None, rhs_
                               lhs_grad_stype='row_sparse', rhs_grad_stype='row_sparse')
 
 
+@with_seed()
 def test_cast_storage_ex():
     def check_cast_storage(shape, density, from_stype, to_stype, check_numeric_grad=True):
         x = mx.symbol.Variable('x', stype=from_stype)
@@ -1177,6 +1179,7 @@ def check_cast_storage(shape, density, from_stype, to_stype, check_numeric_grad=
             check_cast_storage((dim0, rnd.randint(512, 1024)), d, 'default', 'row_sparse',
                                check_numeric_grad=False)
 
+@with_seed()
 def test_sparse_dot():
     def test_dot_csr(lhs_shape, rhs_shape, rhs_stype, trans_lhs, lhs_density, rhs_density):
         lhs_nd = rand_ndarray(lhs_shape, 'csr', density=lhs_density, shuffle_csr_indices=False)
@@ -1217,6 +1220,7 @@ def test_dot_csr(lhs_shape, rhs_shape, rhs_stype, trans_lhs, lhs_density, rhs_de
             test_dot_csr(lhs_shape, (lhs_shape[0], rnd.randint(1, 10)), 'row_sparse', True, lhs_d, rhs_d)
 
 
+@with_seed()
 def test_sparse_slice():
     def check_csr_slice(shape, slice_input):
         storage_type = 'csr'
@@ -1232,6 +1236,7 @@ def check_csr_slice(shape, slice_input):
     check_csr_slice(shape, False)
 
 
+@with_seed()
 def test_sparse_retain():
     def check_sparse_retain(shape, density, index_type=np.int64):
         num_rows = shape[0]
@@ -1264,6 +1269,7 @@ def check_sparse_retain(shape, density, index_type=np.int64):
             check_sparse_retain(shape_3d, density, itype)
 
 
+@with_seed()
 def test_sparse_unary_with_numerics():
     def check_sparse_simple(name, stype, mxnet_func, forward_numpy_call,
                             backward_numpy_call, output_grad_stype=None,
@@ -1335,6 +1341,7 @@ def check_sparse_function(name, mxnet_func, forward_numpy_call, backward_numpy_c
                           lambda output, outg: outg * assign_each(output, lambda x: x * (1.0 - x)),
                           backward_is_use_output=True)
 
+@with_seed()
 def test_sparse_nd_zeros():
     def check_sparse_nd_zeros(stype, shape):
         zero = mx.nd.zeros(shape)
@@ -1346,6 +1353,7 @@ def check_sparse_nd_zeros(stype, shape):
     check_sparse_nd_zeros('csr', shape)
     check_sparse_nd_zeros('default', shape)
 
+@with_seed()
 def test_sparse_nd_zeros_like():
     def check_sparse_nd_zeros_like(stype, shape):
         zero = mx.nd.zeros(shape, stype=stype)
@@ -1356,6 +1364,7 @@ def check_sparse_nd_zeros_like(stype, shape):
     check_sparse_nd_zeros_like('row_sparse', shape)
     check_sparse_nd_zeros_like('csr', shape)
 
+@with_seed()
 def test_sparse_sum_axis():
     def test_variations():
         dim0 = 30
@@ -1383,6 +1392,7 @@ def test_fallback(axis=0, keepdims=True, exclude=True):
     test_variations()
     test_fallback(axis=0, keepdims=True, exclude=True)
 
+@with_seed()
 def test_sparse_square_sum():
     if default_context().device_type == 'cpu':
         dim0 = 30
@@ -1427,6 +1437,7 @@ def test_sparse_square_sum():
                     check_numeric_gradient(test, [rsp], grad_stype_dict={'data': 'row_sparse'},
                                            atol=1e-2, rtol=0.1)
 
+@with_seed()
 def test_sparse_storage_fallback():
     """ test operators which don't implement FComputeEx or FStatefulComputeEx """
     def check_broadcast_add(shape, lhs_stype, rhs_stype):
@@ -1495,6 +1506,7 @@ def check_operator_with_temp_resource(shape, stype):
             check_softmax_with_shape(lhs, rhs, shape, preserve_shape=False)
             check_softmax_with_shape(rhs, rhs, shape, preserve_shape=True)
 
+@with_seed()
 def test_sparse_elementwise_sum():
     def check_sparse_elementwise_sum_with_shape(stype, shape, n):
         # forward
@@ -1525,6 +1537,7 @@ def check_sparse_elementwise_sum_with_shape(stype, shape, n):
         shape = tuple(np.random.randint(5, 10, size=dim))
         check_sparse_elementwise_sum_with_shape('row_sparse', shape, np.random.randint(1, 9))
 
+@with_seed()
 def test_scatter_ops():
     def csr_get_seen_points(name, csr_array, verbose=False):
         """Get a unique list of points int he CSR array as well as a


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services