From 447e20472d2881cf41dcc1d3ebb1aa29ac81e679 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Wed, 29 Jul 2020 00:30:03 +0000 Subject: [PATCH 1/8] initial --- src/operator/tensor/la_op.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/operator/tensor/la_op.h b/src/operator/tensor/la_op.h index e15390ecde5a..f47ac8797c05 100644 --- a/src/operator/tensor/la_op.h +++ b/src/operator/tensor/la_op.h @@ -177,6 +177,7 @@ inline bool LaMatrixMultMacOpShape(const nnvm::NodeAttrs& attrs, axis_param = nnvm::get(attrs.parsed).axis; } if ( (*in_attrs)[0].ndim() >= 2 && (*in_attrs)[0].ndim() == (*in_attrs)[1].ndim() ) { + // Forward shape inference. const int ndim((*in_attrs)[0].ndim()), axis(axis_param < 0 ? ndim + axis_param : axis_param); CHECK(axis >= 0 && axis < ndim-1) From 235d04d6305a0ae8332275e8674e46aef4764ec5 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Wed, 29 Jul 2020 01:08:14 +0000 Subject: [PATCH 2/8] test --- src/operator/tensor/la_op.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/operator/tensor/la_op.h b/src/operator/tensor/la_op.h index f47ac8797c05..2d30430aaf5d 100644 --- a/src/operator/tensor/la_op.h +++ b/src/operator/tensor/la_op.h @@ -37,6 +37,13 @@ namespace mxnet { namespace op { +// check if any dimension is too large +//void check_large_dim(index_t* dims, int size) { + //for (int i=0; i= 2^31) are not supported"; +//} + // Parameters for general matrix-matrix multiply-accumulate (mac) struct LaMatrixMacParam : public dmlc::Parameter { bool transpose_a, transpose_b; From a3844cb216fb2e53dbaf78132fd93fc004bc6b29 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Wed, 29 Jul 2020 04:12:56 +0000 Subject: [PATCH 3/8] gemm and gemm2 --- src/operator/tensor/la_op.h | 31 +++++++++++++++++++++++-------- tests/nightly/test_large_array.py | 21 ++++++++++++++++++++- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/src/operator/tensor/la_op.h b/src/operator/tensor/la_op.h index 2d30430aaf5d..bc37567df6c1 100644 --- a/src/operator/tensor/la_op.h +++ b/src/operator/tensor/la_op.h @@ -37,13 +37,6 @@ namespace mxnet { namespace op { -// check if any dimension is too large -//void check_large_dim(index_t* dims, int size) { - //for (int i=0; i= 2^31) are not supported"; -//} - // Parameters for general matrix-matrix multiply-accumulate (mac) struct LaMatrixMacParam : public dmlc::Parameter { bool transpose_a, transpose_b; @@ -164,6 +157,14 @@ struct LaTrianParam : public dmlc::Parameter { } }; +// check if any dim will overflow 32-bit int +inline void check_large_dim(std::vector dims) { + for (index_t dim : dims) { + CHECK_LE(dim, INT_MAX) + << "Large matrix dimensions (>= 2^31) are not supported"; + } +} + // Common function for shape inference for matrix mult and matrix mac. inline bool LaMatrixMultMacOpShape(const nnvm::NodeAttrs& attrs, mxnet::ShapeVector* in_attrs, @@ -184,11 +185,25 @@ inline bool LaMatrixMultMacOpShape(const nnvm::NodeAttrs& attrs, axis_param = nnvm::get(attrs.parsed).axis; } if ( (*in_attrs)[0].ndim() >= 2 && (*in_attrs)[0].ndim() == (*in_attrs)[1].ndim() ) { - // Forward shape inference. const int ndim((*in_attrs)[0].ndim()), axis(axis_param < 0 ? ndim + axis_param : axis_param); CHECK(axis >= 0 && axis < ndim-1) << "Invalid row axis (" << axis_param << ")"; + // check if any dim is too large + check_large_dim({(*in_attrs)[0][axis], + (*in_attrs)[0][ndim-1], + (*in_attrs)[1][axis], + (*in_attrs)[1][ndim-1]}); + /* + CHECK_LE((*in_attrs)[0][axis], INT_MAX) + << "Large matrix dimensions (>= 2^31) are not supported"; + CHECK_LE((*in_attrs)[0][ndim-1], INT_MAX) + << "Large matrix dimensions (>= 2^31) are not supported";; + CHECK_LE((*in_attrs)[1][axis], INT_MAX) + << "Large matrix dimensions (>= 2^31) are not supported";; + CHECK_LE((*in_attrs)[1][ndim-1], INT_MAX) + << "Large matrix dimensions (>= 2^31) are not supported";; + */ std::vector oshape(ndim); for ( int i = 0; i < ndim-1; ++i ) { if (i != axis) { diff --git a/tests/nightly/test_large_array.py b/tests/nightly/test_large_array.py index 306c827bab9f..f92c1f8783ea 100644 --- a/tests/nightly/test_large_array.py +++ b/tests/nightly/test_large_array.py @@ -27,7 +27,8 @@ from mxnet.test_utils import rand_ndarray, assert_almost_equal, rand_coord_2d, default_context, check_symbolic_forward, create_2d_tensor, get_identity_mat, get_identity_mat_batch from mxnet import gluon, nd -from common import with_seed, with_post_test_cleanup +from common import with_seed, with_post_test_cleanup, assertRaises +from mxnet.base import MXNetError from nose.tools import with_setup import unittest @@ -1350,6 +1351,24 @@ def run_trsm(inp): check_batch_trsm() +def test_linalg_large_dim(): + def check_gemm(): + A = mx.nd.ones(shape=(1, 2**32, 1)) + B = mx.nd.ones(shape=(1, 2**32, 1)) + C = mx.nd.ones(shape=(1, 1, 1)) + assertRaises(MXNetError, mx.nd.linalg.gemm, \ + A, B, C, transpose_b=True, alpha=1.0 , beta=1.0) + + def check_gemm2(): + A = mx.nd.ones(shape=(1, 1, 2**32)) + B = mx.nd.ones(shape=(1, 1, 2**32)) + assertRaises(MXNetError, mx.nd.linalg.gemm2, \ + A, B, transpose_b=True, alpha=1.0) + + check_gemm() + check_gemm2() + + def test_basic(): def check_elementwise(): a = nd.ones(shape=(LARGE_X, SMALL_Y)) From 36a74c9de61871de2bf37891ca5920bb1d347690 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Wed, 29 Jul 2020 05:19:30 +0000 Subject: [PATCH 4/8] type fix --- src/operator/tensor/la_op.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/operator/tensor/la_op.h b/src/operator/tensor/la_op.h index bc37567df6c1..fdf153fd9382 100644 --- a/src/operator/tensor/la_op.h +++ b/src/operator/tensor/la_op.h @@ -158,8 +158,8 @@ struct LaTrianParam : public dmlc::Parameter { }; // check if any dim will overflow 32-bit int -inline void check_large_dim(std::vector dims) { - for (index_t dim : dims) { +inline void check_large_dim(std::vector dims) { + for (dim_t dim : dims) { CHECK_LE(dim, INT_MAX) << "Large matrix dimensions (>= 2^31) are not supported"; } From 9d7a6e83d02cd0544b02fd6e7793ff20138ddfce Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Wed, 29 Jul 2020 23:42:11 +0000 Subject: [PATCH 5/8] syrk trmm trsm --- src/operator/tensor/la_op.h | 25 ++++++++---------- tests/nightly/test_large_array.py | 43 +++++++++++++++++++++++-------- 2 files changed, 43 insertions(+), 25 deletions(-) diff --git a/src/operator/tensor/la_op.h b/src/operator/tensor/la_op.h index fdf153fd9382..ed2551eb5c48 100644 --- a/src/operator/tensor/la_op.h +++ b/src/operator/tensor/la_op.h @@ -189,21 +189,11 @@ inline bool LaMatrixMultMacOpShape(const nnvm::NodeAttrs& attrs, const int ndim((*in_attrs)[0].ndim()), axis(axis_param < 0 ? ndim + axis_param : axis_param); CHECK(axis >= 0 && axis < ndim-1) << "Invalid row axis (" << axis_param << ")"; - // check if any dim is too large + // Check if input matrix dims are too large check_large_dim({(*in_attrs)[0][axis], - (*in_attrs)[0][ndim-1], - (*in_attrs)[1][axis], - (*in_attrs)[1][ndim-1]}); - /* - CHECK_LE((*in_attrs)[0][axis], INT_MAX) - << "Large matrix dimensions (>= 2^31) are not supported"; - CHECK_LE((*in_attrs)[0][ndim-1], INT_MAX) - << "Large matrix dimensions (>= 2^31) are not supported";; - CHECK_LE((*in_attrs)[1][axis], INT_MAX) - << "Large matrix dimensions (>= 2^31) are not supported";; - CHECK_LE((*in_attrs)[1][ndim-1], INT_MAX) - << "Large matrix dimensions (>= 2^31) are not supported";; - */ + (*in_attrs)[0][ndim-1], + (*in_attrs)[1][axis], + (*in_attrs)[1][ndim-1]}); std::vector oshape(ndim); for ( int i = 0; i < ndim-1; ++i ) { if (i != axis) { @@ -248,6 +238,10 @@ inline bool LaTriangMatrixMultOpShape(const nnvm::NodeAttrs& attrs, << "Shapes of inputs 0, 1 must be the same, except on last two dimensions"; oshape[i] = (*in_attrs)[0][i]; } + // Check if the input matrix dims are too large; it suffices to check the second + // input only because the first is square whose size is bounded by memory + check_large_dim({(*in_attrs)[1][ndim-1], + (*in_attrs)[1][ndim-2]}); if ( param.rightside ) { // We compute B * A where A is the first and B the second input. CHECK_EQ((*in_attrs)[0][ndim-2], (*in_attrs)[1][ndim-1]) @@ -364,6 +358,9 @@ inline bool LaSyrkShape(const nnvm::NodeAttrs& attrs, bool transpose = nnvm::get(attrs.parsed).transpose; const int ndim = in_attr.ndim(); if ( ndim >= 2 ) { + // Check if input matrix dims are too large + check_large_dim({in_attr[ndim-1], + in_attr[ndim-2]}); // Forward shape inference. std::vector oshape(ndim); for ( int i = 0; i < ndim-2; ++i ) { diff --git a/tests/nightly/test_large_array.py b/tests/nightly/test_large_array.py index f92c1f8783ea..32361ea9af95 100644 --- a/tests/nightly/test_large_array.py +++ b/tests/nightly/test_large_array.py @@ -42,7 +42,7 @@ LARGE_SIZE = LARGE_X * SMALL_Y LARGE_TENSOR_SHAPE = 2**32 RNN_LARGE_TENSOR = 2**28 - +INT32_MAX = 2**31-1 def test_nn(): def check_gluon_embedding(): @@ -1353,21 +1353,42 @@ def run_trsm(inp): def test_linalg_large_dim(): def check_gemm(): - A = mx.nd.ones(shape=(1, 2**32, 1)) - B = mx.nd.ones(shape=(1, 2**32, 1)) - C = mx.nd.ones(shape=(1, 1, 1)) - assertRaises(MXNetError, mx.nd.linalg.gemm, \ - A, B, C, transpose_b=True, alpha=1.0 , beta=1.0) + A = nd.ones(shape=(1, INT32_MAX + 1, 1)) + B = nd.ones(shape=(1, INT32_MAX + 1, 1)) + C = nd.ones(shape=(1, 1, 1)) + assertRaises(MXNetError, nd.linalg.gemm, \ + A, B, C, transpose_b=True) def check_gemm2(): - A = mx.nd.ones(shape=(1, 1, 2**32)) - B = mx.nd.ones(shape=(1, 1, 2**32)) - assertRaises(MXNetError, mx.nd.linalg.gemm2, \ - A, B, transpose_b=True, alpha=1.0) + A = nd.ones(shape=(1, 1, INT32_MAX + 1)) + B = nd.ones(shape=(1, 1, INT32_MAX + 1)) + assertRaises(MXNetError, nd.linalg.gemm2, \ + A, B, transpose_b=True) + + def check_trmm(): + A = nd.ones(shape=(1, 1, 1)) + B = nd.ones(shape=(1, INT32_MAX + 1, 1)) + assertRaises(MXNetError, nd.linalg.trmm, \ + A, B, rightside=True) + + def check_trsm(): + A = nd.ones(shape=(1, 1, 1)) + B = nd.ones(shape=(1, 1, INT32_MAX + 1)) + assertRaises(MXNetError, nd.linalg.trsm, \ + A, B, rightside=False) + def check_syrk(): + A = nd.ones(shape=(1, INT32_MAX + 1, 1)) + assertRaises(MXNetError, nd.linalg.syrk, A) + assertRaises(MXNetError, nd.linalg.syrk, A, transpose=True) + + # batch input check_gemm() check_gemm2() - + check_trmm() + check_trsm() + check_syrk() + def test_basic(): def check_elementwise(): From 465644f308f9e90160544072a46c45674f4c1af5 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Thu, 30 Jul 2020 00:02:39 +0000 Subject: [PATCH 6/8] gelqf --- src/operator/tensor/la_op.h | 3 +++ tests/nightly/test_large_array.py | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/src/operator/tensor/la_op.h b/src/operator/tensor/la_op.h index ed2551eb5c48..da122908ce29 100644 --- a/src/operator/tensor/la_op.h +++ b/src/operator/tensor/la_op.h @@ -391,6 +391,9 @@ inline bool LaLQFactShape(const nnvm::NodeAttrs& attrs, const int ndim(in_a.ndim()); CHECK_LE(in_a[ndim-2], in_a[ndim-1]) << "Input A shape wrong: Last dimension must be >= than second to last"; + // Check if the last dimension is too large; it suffices to check the last dim + // only since the second to last dim <= last dim + check_large_dim({in_a[ndim-1]}); // Q must have same shape as A SHAPE_ASSIGN_CHECK(*out_attrs, 0, in_a); std::vector oshape_l(ndim); diff --git a/tests/nightly/test_large_array.py b/tests/nightly/test_large_array.py index 32361ea9af95..8ce8f5f948c3 100644 --- a/tests/nightly/test_large_array.py +++ b/tests/nightly/test_large_array.py @@ -1382,12 +1382,17 @@ def check_syrk(): assertRaises(MXNetError, nd.linalg.syrk, A) assertRaises(MXNetError, nd.linalg.syrk, A, transpose=True) + def check_gelqf(): + A = nd.ones(shape=(1, 1, INT32_MAX + 1)) + assertRaises(MXNetError, nd.linalg.gelqf, A) + # batch input check_gemm() check_gemm2() check_trmm() check_trsm() check_syrk() + check_gelqf() def test_basic(): From 3996c531a30ab1ce166b8706199fc3b55c9d8d1e Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Thu, 30 Jul 2020 17:12:26 +0000 Subject: [PATCH 7/8] move tests from test_large_array.py to test_large_vector.py --- tests/nightly/test_large_array.py | 46 +-------------------------- tests/nightly/test_large_vector.py | 51 +++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 46 deletions(-) diff --git a/tests/nightly/test_large_array.py b/tests/nightly/test_large_array.py index 8ce8f5f948c3..5a0f2b58837c 100644 --- a/tests/nightly/test_large_array.py +++ b/tests/nightly/test_large_array.py @@ -42,7 +42,7 @@ LARGE_SIZE = LARGE_X * SMALL_Y LARGE_TENSOR_SHAPE = 2**32 RNN_LARGE_TENSOR = 2**28 -INT32_MAX = 2**31-1 + def test_nn(): def check_gluon_embedding(): @@ -1351,50 +1351,6 @@ def run_trsm(inp): check_batch_trsm() -def test_linalg_large_dim(): - def check_gemm(): - A = nd.ones(shape=(1, INT32_MAX + 1, 1)) - B = nd.ones(shape=(1, INT32_MAX + 1, 1)) - C = nd.ones(shape=(1, 1, 1)) - assertRaises(MXNetError, nd.linalg.gemm, \ - A, B, C, transpose_b=True) - - def check_gemm2(): - A = nd.ones(shape=(1, 1, INT32_MAX + 1)) - B = nd.ones(shape=(1, 1, INT32_MAX + 1)) - assertRaises(MXNetError, nd.linalg.gemm2, \ - A, B, transpose_b=True) - - def check_trmm(): - A = nd.ones(shape=(1, 1, 1)) - B = nd.ones(shape=(1, INT32_MAX + 1, 1)) - assertRaises(MXNetError, nd.linalg.trmm, \ - A, B, rightside=True) - - def check_trsm(): - A = nd.ones(shape=(1, 1, 1)) - B = nd.ones(shape=(1, 1, INT32_MAX + 1)) - assertRaises(MXNetError, nd.linalg.trsm, \ - A, B, rightside=False) - - def check_syrk(): - A = nd.ones(shape=(1, INT32_MAX + 1, 1)) - assertRaises(MXNetError, nd.linalg.syrk, A) - assertRaises(MXNetError, nd.linalg.syrk, A, transpose=True) - - def check_gelqf(): - A = nd.ones(shape=(1, 1, INT32_MAX + 1)) - assertRaises(MXNetError, nd.linalg.gelqf, A) - - # batch input - check_gemm() - check_gemm2() - check_trmm() - check_trsm() - check_syrk() - check_gelqf() - - def test_basic(): def check_elementwise(): a = nd.ones(shape=(LARGE_X, SMALL_Y)) diff --git a/tests/nightly/test_large_vector.py b/tests/nightly/test_large_vector.py index bbad75627769..d4365391cf4e 100644 --- a/tests/nightly/test_large_vector.py +++ b/tests/nightly/test_large_vector.py @@ -27,13 +27,15 @@ from mxnet.test_utils import rand_ndarray, assert_almost_equal, rand_coord_2d, create_vector from mxnet import gluon, nd -from tests.python.unittest.common import with_seed +from tests.python.unittest.common import with_seed, assertRaises +from mxnet.base import MXNetError from nose.tools import with_setup import unittest # dimension constants LARGE_X = 4300000000 MEDIUM_X = 1000000000 +INT32_MAX = 2**31-1 def test_nn(): @@ -1064,6 +1066,53 @@ def check_minimum(): check_minimum() +# openblas and cublas are known to not work well with large +# matrix dims under current configuration. checks are added +# to exit from such use cases +def test_linalg_large_dim(): + def check_gemm(): + A = nd.ones(shape=(1, INT32_MAX + 1, 1)) + B = nd.ones(shape=(1, INT32_MAX + 1, 1)) + C = nd.ones(shape=(1, 1, 1)) + assertRaises(MXNetError, nd.linalg.gemm, \ + A, B, C, transpose_b=True) + + def check_gemm2(): + A = nd.ones(shape=(1, 1, INT32_MAX + 1)) + B = nd.ones(shape=(1, 1, INT32_MAX + 1)) + assertRaises(MXNetError, nd.linalg.gemm2, \ + A, B, transpose_b=True) + + def check_trmm(): + A = nd.ones(shape=(1, 1, 1)) + B = nd.ones(shape=(1, INT32_MAX + 1, 1)) + assertRaises(MXNetError, nd.linalg.trmm, \ + A, B, rightside=True) + + def check_trsm(): + A = nd.ones(shape=(1, 1, 1)) + B = nd.ones(shape=(1, 1, INT32_MAX + 1)) + assertRaises(MXNetError, nd.linalg.trsm, \ + A, B, rightside=False) + + def check_syrk(): + A = nd.ones(shape=(1, INT32_MAX + 1, 1)) + assertRaises(MXNetError, nd.linalg.syrk, A) + assertRaises(MXNetError, nd.linalg.syrk, A, transpose=True) + + def check_gelqf(): + A = nd.ones(shape=(1, 1, INT32_MAX + 1)) + assertRaises(MXNetError, nd.linalg.gelqf, A) + + # batch input + check_gemm() + check_gemm2() + check_trmm() + check_trsm() + check_syrk() + check_gelqf() + + if __name__ == '__main__': import nose nose.runmodule() From ca8f4df60cd13101a7a619015229b34508030b12 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Thu, 30 Jul 2020 17:44:53 +0000 Subject: [PATCH 8/8] fix white space issue --- src/operator/tensor/la_op.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/operator/tensor/la_op.h b/src/operator/tensor/la_op.h index da122908ce29..3e608d8f9de9 100644 --- a/src/operator/tensor/la_op.h +++ b/src/operator/tensor/la_op.h @@ -238,10 +238,10 @@ inline bool LaTriangMatrixMultOpShape(const nnvm::NodeAttrs& attrs, << "Shapes of inputs 0, 1 must be the same, except on last two dimensions"; oshape[i] = (*in_attrs)[0][i]; } - // Check if the input matrix dims are too large; it suffices to check the second + // Check if the input matrix dims are too large; it suffices to check the second // input only because the first is square whose size is bounded by memory check_large_dim({(*in_attrs)[1][ndim-1], - (*in_attrs)[1][ndim-2]}); + (*in_attrs)[1][ndim-2]}); if ( param.rightside ) { // We compute B * A where A is the first and B the second input. CHECK_EQ((*in_attrs)[0][ndim-2], (*in_attrs)[1][ndim-1]) @@ -360,7 +360,7 @@ inline bool LaSyrkShape(const nnvm::NodeAttrs& attrs, if ( ndim >= 2 ) { // Check if input matrix dims are too large check_large_dim({in_attr[ndim-1], - in_attr[ndim-2]}); + in_attr[ndim-2]}); // Forward shape inference. std::vector oshape(ndim); for ( int i = 0; i < ndim-2; ++i ) {