From 90b64089722389b3ca0d76eabb0f4ab2dd56a059 Mon Sep 17 00:00:00 2001 From: Nikoli Dryden Date: Fri, 24 Mar 2017 07:24:05 -0700 Subject: [PATCH 1/4] Update Hadamard, Dot, ColumnTwoNorms, ColumnMaxNorms, and HilbertSchmidt to support block matrices, and add tests for Hadamard, Dot, ColumnTwoNorms, and ColumnMaxNorms. --- include/El/blas_like/level1/Dot.hpp | 4 +- include/El/blas_like/level1/Hadamard.hpp | 12 +-- include/El/blas_like/level1/decl.hpp | 18 ++--- src/blas_like/level1/ColumnNorms.cpp | 22 ++++-- src/blas_like/level1/HilbertSchmidt.cpp | 4 +- tests/blas_like/ColumnNorms.cpp | 97 ++++++++++++++++++++++++ tests/blas_like/Dot.cpp | 63 +++++++++++++++ tests/blas_like/Hadamard.cpp | 64 ++++++++++++++++ 8 files changed, 257 insertions(+), 27 deletions(-) create mode 100644 tests/blas_like/ColumnNorms.cpp create mode 100644 tests/blas_like/Dot.cpp create mode 100644 tests/blas_like/Hadamard.cpp diff --git a/include/El/blas_like/level1/Dot.hpp b/include/El/blas_like/level1/Dot.hpp index beda613785..ce1dc6fdde 100644 --- a/include/El/blas_like/level1/Dot.hpp +++ b/include/El/blas_like/level1/Dot.hpp @@ -19,7 +19,7 @@ T Dot( const Matrix& A, const Matrix& B ) } template -T Dot( const ElementalMatrix& A, const ElementalMatrix& B ) +T Dot( const AbstractDistMatrix& A, const AbstractDistMatrix& B ) { EL_DEBUG_CSE return HilbertSchmidt( A, B ); @@ -114,7 +114,7 @@ T Dotu( const DistMultiVec& A, const DistMultiVec& B ) EL_EXTERN template T Dot \ ( const Matrix& A, const Matrix& B ); \ EL_EXTERN template T Dot \ - ( const ElementalMatrix& A, const ElementalMatrix& B ); \ + ( const AbstractDistMatrix& A, const AbstractDistMatrix& B ); \ EL_EXTERN template T Dot \ ( const DistMultiVec& A, const DistMultiVec& B ); \ EL_EXTERN template T Dotu \ diff --git a/include/El/blas_like/level1/Hadamard.hpp b/include/El/blas_like/level1/Hadamard.hpp index e1a5b062d2..4d741b1298 100644 --- a/include/El/blas_like/level1/Hadamard.hpp +++ b/include/El/blas_like/level1/Hadamard.hpp @@ -42,9 +42,9 @@ void Hadamard( const Matrix& A, const Matrix& B, Matrix& C ) template void Hadamard -( const ElementalMatrix& A, - const ElementalMatrix& B, - ElementalMatrix& C ) +( const AbstractDistMatrix& A, + const AbstractDistMatrix& B, + AbstractDistMatrix& C ) { EL_DEBUG_CSE const DistData& ADistData = A.DistData(); @@ -87,9 +87,9 @@ void Hadamard EL_EXTERN template void Hadamard \ ( const Matrix& A, const Matrix& B, Matrix& C ); \ EL_EXTERN template void Hadamard \ - ( const ElementalMatrix& A, \ - const ElementalMatrix& B, \ - ElementalMatrix& C ); \ + ( const AbstractDistMatrix& A, \ + const AbstractDistMatrix& B, \ + AbstractDistMatrix& C ); \ EL_EXTERN template void Hadamard \ ( const DistMultiVec& A, \ const DistMultiVec& B, \ diff --git a/include/El/blas_like/level1/decl.hpp b/include/El/blas_like/level1/decl.hpp index 48cd5f269e..e129c0968b 100644 --- a/include/El/blas_like/level1/decl.hpp +++ b/include/El/blas_like/level1/decl.hpp @@ -196,9 +196,9 @@ void Recv( Matrix& A, mpi::Comm comm, int source ); template void ColumnTwoNorms ( const Matrix& X, Matrix>& norms ); -template +template void ColumnTwoNorms -( const DistMatrix& X, DistMatrix,V,STAR>& norms ); +( const DistMatrix& X, DistMatrix,V,STAR,W>& norms ); template void ColumnTwoNorms ( const DistMultiVec& X, Matrix>& norms ); @@ -235,9 +235,9 @@ void ColumnTwoNorms template void ColumnMaxNorms ( const Matrix& X, Matrix>& norms ); -template +template void ColumnMaxNorms -( const DistMatrix& X, DistMatrix,V,STAR>& norms ); +( const DistMatrix& X, DistMatrix,V,STAR,W>& norms ); template void ColumnMaxNorms ( const DistMultiVec& X, Matrix>& norms ); @@ -802,7 +802,7 @@ void DiagonalSolve template T Dot( const Matrix& A, const Matrix& B ); template -T Dot( const ElementalMatrix& A, const ElementalMatrix& B ); +T Dot( const AbstractDistMatrix& A, const AbstractDistMatrix& B ); template T Dot( const DistMultiVec& A, const DistMultiVec& B ); @@ -1155,9 +1155,9 @@ template void Hadamard( const Matrix& A, const Matrix& B, Matrix& C ); template void Hadamard -( const ElementalMatrix& A, - const ElementalMatrix& B, - ElementalMatrix& C ); +( const AbstractDistMatrix& A, + const AbstractDistMatrix& B, + AbstractDistMatrix& C ); template void Hadamard ( const DistMultiVec& A, @@ -1170,7 +1170,7 @@ template T HilbertSchmidt( const Matrix& A, const Matrix& B ); template T HilbertSchmidt -( const ElementalMatrix& A, const ElementalMatrix& C ); +( const AbstractDistMatrix& A, const AbstractDistMatrix& C ); template T HilbertSchmidt( const DistMultiVec& A, const DistMultiVec& B ); diff --git a/src/blas_like/level1/ColumnNorms.cpp b/src/blas_like/level1/ColumnNorms.cpp index 05bfc21b6a..9ac43012f6 100644 --- a/src/blas_like/level1/ColumnNorms.cpp +++ b/src/blas_like/level1/ColumnNorms.cpp @@ -103,9 +103,9 @@ void ColumnMaxNorms( const Matrix& X, Matrix>& norms ) } } -template +template void ColumnTwoNorms -( const DistMatrix& A, DistMatrix,V,STAR>& norms ) +( const DistMatrix& A, DistMatrix,V,STAR,W>& norms ) { EL_DEBUG_CSE norms.AlignWith( A ); @@ -118,9 +118,9 @@ void ColumnTwoNorms ColumnTwoNormsHelper( A.LockedMatrix(), norms.Matrix(), A.ColComm() ); } -template +template void ColumnMaxNorms -( const DistMatrix& A, DistMatrix,V,STAR>& norms ) +( const DistMatrix& A, DistMatrix,V,STAR,W>& norms ) { EL_DEBUG_CSE norms.AlignWith( A ); @@ -363,11 +363,17 @@ void ColumnTwoNorms #define PROTO_DIST(Field,U,V) \ template void ColumnTwoNorms \ - ( const DistMatrix& X, \ - DistMatrix,V,STAR>& norms ); \ + ( const DistMatrix& X, \ + DistMatrix,V,STAR,ELEMENT>& norms ); \ template void ColumnMaxNorms \ - ( const DistMatrix& X, \ - DistMatrix,V,STAR>& norms ); + ( const DistMatrix& X, \ + DistMatrix,V,STAR,ELEMENT>& norms ); \ + template void ColumnTwoNorms \ + ( const DistMatrix& X, \ + DistMatrix,V,STAR,BLOCK>& norms ); \ + template void ColumnMaxNorms \ + ( const DistMatrix& X, \ + DistMatrix,V,STAR,BLOCK>& norms ); #define PROTO(Field) \ template void ColumnTwoNorms \ diff --git a/src/blas_like/level1/HilbertSchmidt.cpp b/src/blas_like/level1/HilbertSchmidt.cpp index 65dd1e7be3..c38f19556b 100644 --- a/src/blas_like/level1/HilbertSchmidt.cpp +++ b/src/blas_like/level1/HilbertSchmidt.cpp @@ -41,7 +41,7 @@ Ring HilbertSchmidt( const Matrix& A, const Matrix& B ) template Ring HilbertSchmidt -( const ElementalMatrix& A, const ElementalMatrix& B ) +( const AbstractDistMatrix& A, const AbstractDistMatrix& B ) { EL_DEBUG_CSE if( A.Height() != B.Height() || A.Width() != B.Width() ) @@ -112,7 +112,7 @@ Ring HilbertSchmidt( const DistMultiVec& A, const DistMultiVec& B ) template Ring HilbertSchmidt \ ( const Matrix& A, const Matrix& B ); \ template Ring HilbertSchmidt \ - ( const ElementalMatrix& A, const ElementalMatrix& B ); \ + ( const AbstractDistMatrix& A, const AbstractDistMatrix& B ); \ template Ring HilbertSchmidt \ ( const DistMultiVec& A, const DistMultiVec& B ); diff --git a/tests/blas_like/ColumnNorms.cpp b/tests/blas_like/ColumnNorms.cpp new file mode 100644 index 0000000000..ef7f3d8251 --- /dev/null +++ b/tests/blas_like/ColumnNorms.cpp @@ -0,0 +1,97 @@ +/* + Copyright (c) 2009-2016, Jack Poulson + All rights reserved. + + This file is part of Elemental and is under the BSD 2-Clause License, + which can be found in the LICENSE file in the root directory, or at + http://opensource.org/licenses/BSD-2-Clause +*/ + +#include +using namespace El; + +template +void TestColumnTwoNorms(Int m, Int n, const Grid& g, bool print) { + // Generate random matrix to test. + DistMatrix A(g); + Uniform(A, m, n); + if (print) { + Print(A, "A"); + } + DistMatrix norms(g); + ColumnTwoNorms(A, norms); + if (print) { + Print(norms, "norms"); + } + for (Int j = 0; j < A.LocalWidth(); ++j) { + T got = norms.GetLocal(j, 0); + T expected = 0; + for (Int i = 0; i < A.LocalHeight(); ++i) { + T val = A.GetLocal(i, j); + expected += val * val; + } + expected = mpi::AllReduce(expected, g.ColComm()); + expected = Sqrt(expected); + if (Abs(got - expected) > 1e-5) { + Output("Results do not match, norms(", j, ")=", got, + " instead of ", expected); + RuntimeError("got != expected"); + } + } +} + +template +void TestColumnMaxNorms(Int m, Int n, const Grid& g, bool print) { + // Generate random matrix to test. + DistMatrix A(g); + Uniform(A, m, n); + if (print) { + Print(A, "A"); + } + DistMatrix norms(g); + ColumnMaxNorms(A, norms); + if (print) { + Print(norms, "norms"); + } + for (Int j = 0; j < A.LocalWidth(); ++j) { + T got = norms.GetLocal(j, 0); + T expected = 0; + for (Int i = 0; i < A.LocalHeight(); ++i) { + expected = Max(expected, Abs(A.GetLocal(i, j))); + } + T r; + mpi::AllReduce(&expected, &r, 1, mpi::MAX, g.ColComm()); + expected = r; + if (got != expected) { + Output("Results do not match, norms(", j, ")=", got, + " instead of ", expected); + RuntimeError("got != expected"); + } + } +} + +int main(int argc, char** argv) { + Environment env(argc, argv); + mpi::Comm comm = mpi::COMM_WORLD; + try { + const Int m = Input("--m", "height", 100); + const Int n = Input("--n", "width", 100); + const bool print = Input("--print", "print matrices?", false); + ProcessInput(); + PrintInputReport(); + + const Grid g(comm); + OutputFromRoot(comm, "Testing ColumnTwoNorms"); + TestColumnTwoNorms(m, n, g, print); + TestColumnTwoNorms(m, n, g, print); + TestColumnTwoNorms(m, n, g, print); + TestColumnTwoNorms(m, n, g, print); + OutputFromRoot(comm, "Testing ColumnMaxNorms"); + TestColumnMaxNorms(m, n, g, print); + TestColumnMaxNorms(m, n, g, print); + TestColumnMaxNorms(m, n, g, print); + TestColumnMaxNorms(m, n, g, print); + } catch (exception& e) { + ReportException(e); + } +} diff --git a/tests/blas_like/Dot.cpp b/tests/blas_like/Dot.cpp new file mode 100644 index 0000000000..2d9e3899a0 --- /dev/null +++ b/tests/blas_like/Dot.cpp @@ -0,0 +1,63 @@ +/* + Copyright (c) 2009-2016, Jack Poulson + All rights reserved. + + This file is part of Elemental and is under the BSD 2-Clause License, + which can be found in the LICENSE file in the root directory, or at + http://opensource.org/licenses/BSD-2-Clause +*/ + +#include +using namespace El; + +template +void TestDot(Int m, Int n, const Grid& g, bool print) { + // Generate random matrices to test. + DistMatrix A(g); + Uniform(A, m, n); + DistMatrix B(g); + Uniform(B, m, n); + if (print) { + Print(A, "A"); + Print(B, "B"); + } + // Do Dot. + T got = Dot(A, B); + if (print) { + OutputFromRoot(g.Comm(), "result=", got); + } + // Manually check results. + T expected = 0; + for (Int j = 0; j < A.LocalWidth(); ++j) { + for (Int i = 0; i < B.LocalHeight(); ++i) { + expected += A.GetLocal(i, j) * B.GetLocal(i, j); + } + } + expected = mpi::AllReduce(expected, g.Comm()); + if (Abs(got - expected) > 1e-6) { + Output("Results do not match, got=", got, + " instead of ", expected); + RuntimeError("got != expected"); + } +} + +int main(int argc, char** argv) { + Environment env(argc, argv); + mpi::Comm comm = mpi::COMM_WORLD; + try { + const Int m = Input("--m", "height", 100); + const Int n = Input("--n", "width", 100); + const bool print = Input("--print", "print matrices?", false); + ProcessInput(); + PrintInputReport(); + + const Grid g(comm); + OutputFromRoot(comm, "Testing Dot"); + TestDot(m, n, g, print); + TestDot(m, n, g, print); + TestDot(m, n, g, print); + TestDot(m, n, g, print); + } catch (exception& e) { + ReportException(e); + } +} diff --git a/tests/blas_like/Hadamard.cpp b/tests/blas_like/Hadamard.cpp new file mode 100644 index 0000000000..c1a1c1ceda --- /dev/null +++ b/tests/blas_like/Hadamard.cpp @@ -0,0 +1,64 @@ +/* + Copyright (c) 2009-2016, Jack Poulson + All rights reserved. + + This file is part of Elemental and is under the BSD 2-Clause License, + which can be found in the LICENSE file in the root directory, or at + http://opensource.org/licenses/BSD-2-Clause +*/ + +#include +using namespace El; + +template +void TestHadamard(Int m, Int n, const Grid& g, bool print) { + // Generate random matrices to test. + DistMatrix A(g); + Uniform(A, m, n); + DistMatrix B(g); + Uniform(B, m, n); + if (print) { + Print(A, "A"); + Print(B, "B"); + } + // Apply Hadamard. + DistMatrix C(g); + Hadamard(A, B, C); + mpi::Barrier(g.Comm()); + if (print) { + Print(C, "C"); + } + // Manually check results. + for (Int j = 0; j < A.LocalWidth(); ++j) { + for (Int i = 0; i < A.LocalHeight(); ++i) { + T got = C.GetLocal(i, j); + T expected = A.GetLocal(i, j) * B.GetLocal(i, j); + if (Abs(got - expected) > 1e-6) { + Output("Results do not match, C(", i, ",", j, ")=", got, + " instead of ", expected); + RuntimeError("got != expected"); + } + } + } +} + +int main(int argc, char** argv) { + Environment env(argc, argv); + mpi::Comm comm = mpi::COMM_WORLD; + try { + const Int m = Input("--m", "height", 100); + const Int n = Input("--n", "width", 100); + const bool print = Input("--print", "print matrices?", false); + ProcessInput(); + PrintInputReport(); + + const Grid g(comm); + OutputFromRoot(comm, "Testing Hadamard"); + TestHadamard(m, n, g, print); + TestHadamard(m, n, g, print); + TestHadamard(m, n, g, print); + TestHadamard(m, n, g, print); + } catch (exception& e) { + ReportException(e); + } +} From 4afe36a110f7adac87d7971d0f95b8952a144190 Mon Sep 17 00:00:00 2001 From: Nikoli Dryden Date: Fri, 24 Mar 2017 13:16:03 -0700 Subject: [PATCH 2/4] Add check for whether the same block size is used in Hadamard and HilbertSchmidt. --- include/El/blas_like/level1/Hadamard.hpp | 3 +++ src/blas_like/level1/HilbertSchmidt.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/include/El/blas_like/level1/Hadamard.hpp b/include/El/blas_like/level1/Hadamard.hpp index 4d741b1298..89ff1c52b7 100644 --- a/include/El/blas_like/level1/Hadamard.hpp +++ b/include/El/blas_like/level1/Hadamard.hpp @@ -60,6 +60,9 @@ void Hadamard LogicError("A, B, and C must share the same distribution"); if( A.ColAlign() != B.ColAlign() || A.RowAlign() != B.RowAlign() ) LogicError("A and B must be aligned"); + if ( A.BlockHeight() != B.BlockHeight() || + A.BlockWidth() != B.BlockWidth()) + LogicError("A and B must have the same block size"); C.AlignWith( A.DistData() ); C.Resize( A.Height(), A.Width() ); Hadamard( A.LockedMatrix(), B.LockedMatrix(), C.Matrix() ); diff --git a/src/blas_like/level1/HilbertSchmidt.cpp b/src/blas_like/level1/HilbertSchmidt.cpp index c38f19556b..ca7f2c3685 100644 --- a/src/blas_like/level1/HilbertSchmidt.cpp +++ b/src/blas_like/level1/HilbertSchmidt.cpp @@ -53,6 +53,9 @@ Ring HilbertSchmidt LogicError("A and B must have the same distribution"); if( A.ColAlign() != B.ColAlign() || A.RowAlign() != B.RowAlign() ) LogicError("Matrices must be aligned"); + if ( A.BlockHeight() != B.BlockHeight() || + A.BlockWidth() != B.BlockWidth()) + LogicError("A and B must have the same block size"); Ring innerProd; if( A.Participating() ) From be1c42a2b648dcbc88471ef278a82045bb09bd69 Mon Sep 17 00:00:00 2001 From: Nikoli Dryden Date: Sun, 26 Mar 2017 18:25:02 -0700 Subject: [PATCH 3/4] Test Hadamard, Dot, ColumnTwoNorms, and ColumnMaxNorms at higher precision and in complex variants. Clean up the syntax and use limits::Epsilon for checking error. --- tests/blas_like/ColumnNorms.cpp | 78 ++++++++++++++++++++++++--------- tests/blas_like/Dot.cpp | 60 +++++++++++++++++++------ tests/blas_like/Hadamard.cpp | 56 ++++++++++++++++++----- 3 files changed, 151 insertions(+), 43 deletions(-) diff --git a/tests/blas_like/ColumnNorms.cpp b/tests/blas_like/ColumnNorms.cpp index ef7f3d8251..e8411add93 100644 --- a/tests/blas_like/ColumnNorms.cpp +++ b/tests/blas_like/ColumnNorms.cpp @@ -11,28 +11,30 @@ using namespace El; template -void TestColumnTwoNorms(Int m, Int n, const Grid& g, bool print) { +void TestColumnTwoNorms(Int m, Int n, const Grid& g, bool print) +{ // Generate random matrix to test. DistMatrix A(g); Uniform(A, m, n); - if (print) { + if (print) Print(A, "A"); - } DistMatrix norms(g); ColumnTwoNorms(A, norms); - if (print) { + if (print) Print(norms, "norms"); - } - for (Int j = 0; j < A.LocalWidth(); ++j) { + for (Int j = 0; j < A.LocalWidth(); ++j) + { T got = norms.GetLocal(j, 0); T expected = 0; - for (Int i = 0; i < A.LocalHeight(); ++i) { + for (Int i = 0; i < A.LocalHeight(); ++i) + { T val = A.GetLocal(i, j); expected += val * val; } expected = mpi::AllReduce(expected, g.ColComm()); expected = Sqrt(expected); - if (Abs(got - expected) > 1e-5) { + if (Abs(got - expected) > 10 * limits::Epsilon>()) + { Output("Results do not match, norms(", j, ")=", got, " instead of ", expected); RuntimeError("got != expected"); @@ -41,28 +43,28 @@ void TestColumnTwoNorms(Int m, Int n, const Grid& g, bool print) { } template -void TestColumnMaxNorms(Int m, Int n, const Grid& g, bool print) { +void TestColumnMaxNorms(Int m, Int n, const Grid& g, bool print) +{ // Generate random matrix to test. DistMatrix A(g); Uniform(A, m, n); - if (print) { + if (print) Print(A, "A"); - } DistMatrix norms(g); ColumnMaxNorms(A, norms); - if (print) { + if (print) Print(norms, "norms"); - } - for (Int j = 0; j < A.LocalWidth(); ++j) { + for (Int j = 0; j < A.LocalWidth(); ++j) + { T got = norms.GetLocal(j, 0); T expected = 0; - for (Int i = 0; i < A.LocalHeight(); ++i) { + for (Int i = 0; i < A.LocalHeight(); ++i) expected = Max(expected, Abs(A.GetLocal(i, j))); - } T r; mpi::AllReduce(&expected, &r, 1, mpi::MAX, g.ColComm()); expected = r; - if (got != expected) { + if (got != expected) + { Output("Results do not match, norms(", j, ")=", got, " instead of ", expected); RuntimeError("got != expected"); @@ -70,10 +72,12 @@ void TestColumnMaxNorms(Int m, Int n, const Grid& g, bool print) { } } -int main(int argc, char** argv) { +int main(int argc, char** argv) +{ Environment env(argc, argv); mpi::Comm comm = mpi::COMM_WORLD; - try { + try + { const Int m = Input("--m", "height", 100); const Int n = Input("--n", "width", 100); const bool print = Input("--print", "print matrices?", false); @@ -86,12 +90,46 @@ int main(int argc, char** argv) { TestColumnTwoNorms(m, n, g, print); TestColumnTwoNorms(m, n, g, print); TestColumnTwoNorms(m, n, g, print); +#if defined(EL_HAVE_QD) && defined(EL_ENABLE_DOUBLEDOUBLE) + TestColumnTwoNorms(m, n, g, print); + TestColumnTwoNorms(m, n, g, print); +#endif +#if defined(EL_HAVE_QD) && defined(EL_ENABLE_QUADDOUBLE) + TestColumnTwoNorms(m, n, g, print); + TestColumnTwoNorms(m, n, g, print); +#endif +#if defined(EL_HAVE_QUAD) && defined(EL_ENABLE_QUAD) + TestColumnTwoNorms(m, n, g, print); + TestColumnTwoNorms(m, n, g, print); +#endif +#if defined(EL_HAVE_MPC) && defined(EL_ENABLE_BIGFLOAT) + TestColumnTwoNorms(m, n, g, print); + TestColumnTwoNorms(m, n, g, print); +#endif OutputFromRoot(comm, "Testing ColumnMaxNorms"); TestColumnMaxNorms(m, n, g, print); TestColumnMaxNorms(m, n, g, print); TestColumnMaxNorms(m, n, g, print); TestColumnMaxNorms(m, n, g, print); - } catch (exception& e) { +#if defined(EL_HAVE_QD) && defined(EL_ENABLE_DOUBLEDOUBLE) + TestColumnMaxNorms(m, n, g, print); + TestColumnMaxNorms(m, n, g, print); +#endif +#if defined(EL_HAVE_QD) && defined(EL_ENABLE_QUADDOUBLE) + TestColumnMaxNorms(m, n, g, print); + TestColumnMaxNorms(m, n, g, print); +#endif +#if defined(EL_HAVE_QUAD) && defined(EL_ENABLE_QUAD) + TestColumnMaxNorms(m, n, g, print); + TestColumnMaxNorms(m, n, g, print); +#endif +#if defined(EL_HAVE_MPC) && defined(EL_ENABLE_BIGFLOAT) + TestColumnMaxNorms(m, n, g, print); + TestColumnMaxNorms(m, n, g, print); +#endif + } + catch (exception& e) + { ReportException(e); } } diff --git a/tests/blas_like/Dot.cpp b/tests/blas_like/Dot.cpp index 2d9e3899a0..ce54b53b79 100644 --- a/tests/blas_like/Dot.cpp +++ b/tests/blas_like/Dot.cpp @@ -11,40 +11,44 @@ using namespace El; template -void TestDot(Int m, Int n, const Grid& g, bool print) { +void TestDot(Int m, Int n, const Grid& g, bool print) +{ // Generate random matrices to test. DistMatrix A(g); Uniform(A, m, n); DistMatrix B(g); Uniform(B, m, n); - if (print) { + if (print) + { Print(A, "A"); Print(B, "B"); } // Do Dot. T got = Dot(A, B); - if (print) { + if (print) OutputFromRoot(g.Comm(), "result=", got); - } // Manually check results. T expected = 0; - for (Int j = 0; j < A.LocalWidth(); ++j) { - for (Int i = 0; i < B.LocalHeight(); ++i) { - expected += A.GetLocal(i, j) * B.GetLocal(i, j); - } - } + for (Int j = 0; j < A.LocalWidth(); ++j) + for (Int i = 0; i < B.LocalHeight(); ++i) + expected += Conj(A.GetLocal(i, j)) * B.GetLocal(i, j); expected = mpi::AllReduce(expected, g.Comm()); - if (Abs(got - expected) > 1e-6) { + // The constant here is large because this is not an especially stable way + // to compute the dot product, but it provides a dumb implementation baseline. + if (Abs(got - expected) > 700 * limits::Epsilon>()) + { Output("Results do not match, got=", got, " instead of ", expected); RuntimeError("got != expected"); } } -int main(int argc, char** argv) { +int main(int argc, char** argv) +{ Environment env(argc, argv); mpi::Comm comm = mpi::COMM_WORLD; - try { + try + { const Int m = Input("--m", "height", 100); const Int n = Input("--n", "width", 100); const bool print = Input("--print", "print matrices?", false); @@ -55,9 +59,39 @@ int main(int argc, char** argv) { OutputFromRoot(comm, "Testing Dot"); TestDot(m, n, g, print); TestDot(m, n, g, print); + TestDot, ELEMENT>(m, n, g, print); + TestDot, BLOCK>(m, n, g, print); TestDot(m, n, g, print); TestDot(m, n, g, print); - } catch (exception& e) { + TestDot, ELEMENT>(m, n, g, print); + TestDot, BLOCK>(m, n, g, print); +#if defined(EL_HAVE_QD) && defined(EL_ENABLE_DOUBLEDOUBLE) + TestDot(m, n, g, print); + TestDot(m, n, g, print); + TestDot, ELEMENT>(m, n, g, print); + TestDot, BLOCK>(m, n, g, print); +#endif +#if defined(EL_HAVE_QD) && defined(EL_ENABLE_QUADDOUBLE) + TestDot(m, n, g, print); + TestDot(m, n, g, print); + TestDot, ELEMENT>(m, n, g, print); + TestDot, BLOCK>(m, n, g, print); +#endif +#if defined(EL_HAVE_QUAD) && defined(EL_ENABLE_QUAD) + TestDot(m, n, g, print); + TestDot(m, n, g, print); + TestDot, ELEMENT>(m, n, g, print); + TestDot, BLOCK>(m, n, g, print); +#endif +#if defined(EL_HAVE_MPC) && defined(EL_ENABLE_BIGFLOAT) + TestDot(m, n, g, print); + TestDot(m, n, g, print); + TestDot, ELEMENT>(m, n, g, print); + TestDot, BLOCK>(m, n, g, print); +#endif + } + catch (exception& e) + { ReportException(e); } } diff --git a/tests/blas_like/Hadamard.cpp b/tests/blas_like/Hadamard.cpp index c1a1c1ceda..73cc5fd83d 100644 --- a/tests/blas_like/Hadamard.cpp +++ b/tests/blas_like/Hadamard.cpp @@ -11,13 +11,15 @@ using namespace El; template -void TestHadamard(Int m, Int n, const Grid& g, bool print) { +void TestHadamard(Int m, Int n, const Grid& g, bool print) +{ // Generate random matrices to test. DistMatrix A(g); Uniform(A, m, n); DistMatrix B(g); Uniform(B, m, n); - if (print) { + if (print) + { Print(A, "A"); Print(B, "B"); } @@ -25,15 +27,17 @@ void TestHadamard(Int m, Int n, const Grid& g, bool print) { DistMatrix C(g); Hadamard(A, B, C); mpi::Barrier(g.Comm()); - if (print) { + if (print) Print(C, "C"); - } // Manually check results. - for (Int j = 0; j < A.LocalWidth(); ++j) { - for (Int i = 0; i < A.LocalHeight(); ++i) { + for (Int j = 0; j < A.LocalWidth(); ++j) + { + for (Int i = 0; i < A.LocalHeight(); ++i) + { T got = C.GetLocal(i, j); T expected = A.GetLocal(i, j) * B.GetLocal(i, j); - if (Abs(got - expected) > 1e-6) { + if (Abs(got - expected) > 10 * limits::Epsilon>()) + { Output("Results do not match, C(", i, ",", j, ")=", got, " instead of ", expected); RuntimeError("got != expected"); @@ -42,10 +46,12 @@ void TestHadamard(Int m, Int n, const Grid& g, bool print) { } } -int main(int argc, char** argv) { +int main(int argc, char** argv) +{ Environment env(argc, argv); mpi::Comm comm = mpi::COMM_WORLD; - try { + try + { const Int m = Input("--m", "height", 100); const Int n = Input("--n", "width", 100); const bool print = Input("--print", "print matrices?", false); @@ -56,9 +62,39 @@ int main(int argc, char** argv) { OutputFromRoot(comm, "Testing Hadamard"); TestHadamard(m, n, g, print); TestHadamard(m, n, g, print); + TestHadamard, ELEMENT>(m, n, g, print); + TestHadamard, BLOCK>(m, n, g, print); TestHadamard(m, n, g, print); TestHadamard(m, n, g, print); - } catch (exception& e) { + TestHadamard, ELEMENT>(m, n, g, print); + TestHadamard, BLOCK>(m, n, g, print); +#if defined(EL_HAVE_QD) && defined(EL_ENABLE_DOUBLEDOUBLE) + TestHadamard(m, n, g, print); + TestHadamard(m, n, g, print); + TestHadamard, ELEMENT>(m, n, g, print); + TestHadamard, BLOCK>(m, n, g, print); +#endif +#if defined(EL_HAVE_QD) && defined(EL_ENABLE_QUADDOUBLE) + TestHadamard(m, n, g, print); + TestHadamard(m, n, g, print); + TestHadamard, ELEMENT>(m, n, g, print); + TestHadamard, BLOCK>(m, n, g, print); +#endif +#if defined(EL_HAVE_QUAD) && defined(EL_ENABLE_QUAD) + TestHadamard(m, n, g, print); + TestHadamard(m, n, g, print); + TestHadamard, ELEMENT>(m, n, g, print); + TestHadamard, BLOCK>(m, n, g, print); +#endif +#if defined(EL_HAVE_MPC) && defined(EL_ENABLE_BIGFLOAT) + TestHadamard(m, n, g, print); + TestHadamard(m, n, g, print); + TestHadamard, ELEMENT>(m, n, g, print); + TestHadamard, BLOCK>(m, n, g, print); +#endif + } + catch (exception& e) + { ReportException(e); } } From e9139f4b8a57eaef37feb4bf255f459cd36eb701 Mon Sep 17 00:00:00 2001 From: Nikoli Dryden Date: Mon, 27 Mar 2017 16:39:15 -0700 Subject: [PATCH 4/4] Remove unneeded macro checks and use a more rigorous bound in the ColumnTwoNorms test. --- tests/blas_like/ColumnNorms.cpp | 21 ++++++++++----------- tests/blas_like/Dot.cpp | 8 +++----- tests/blas_like/Hadamard.cpp | 8 +++----- 3 files changed, 16 insertions(+), 21 deletions(-) diff --git a/tests/blas_like/ColumnNorms.cpp b/tests/blas_like/ColumnNorms.cpp index e8411add93..6d91fa0e97 100644 --- a/tests/blas_like/ColumnNorms.cpp +++ b/tests/blas_like/ColumnNorms.cpp @@ -33,7 +33,10 @@ void TestColumnTwoNorms(Int m, Int n, const Grid& g, bool print) } expected = mpi::AllReduce(expected, g.ColComm()); expected = Sqrt(expected); - if (Abs(got - expected) > 10 * limits::Epsilon>()) + // Compute max(expected, 1) to use relative bound. + // (std::max and El::Max don't support BigFloat. + T div = expected > 1 ? expected : 1; + if (Abs(got - expected) / div > m * n * 10 * limits::Epsilon>()) { Output("Results do not match, norms(", j, ")=", got, " instead of ", expected); @@ -90,19 +93,17 @@ int main(int argc, char** argv) TestColumnTwoNorms(m, n, g, print); TestColumnTwoNorms(m, n, g, print); TestColumnTwoNorms(m, n, g, print); -#if defined(EL_HAVE_QD) && defined(EL_ENABLE_DOUBLEDOUBLE) +#if defined(EL_HAVE_QD) TestColumnTwoNorms(m, n, g, print); TestColumnTwoNorms(m, n, g, print); -#endif -#if defined(EL_HAVE_QD) && defined(EL_ENABLE_QUADDOUBLE) TestColumnTwoNorms(m, n, g, print); TestColumnTwoNorms(m, n, g, print); #endif -#if defined(EL_HAVE_QUAD) && defined(EL_ENABLE_QUAD) +#if defined(EL_HAVE_QUAD) TestColumnTwoNorms(m, n, g, print); TestColumnTwoNorms(m, n, g, print); #endif -#if defined(EL_HAVE_MPC) && defined(EL_ENABLE_BIGFLOAT) +#if defined(EL_HAVE_MPC) TestColumnTwoNorms(m, n, g, print); TestColumnTwoNorms(m, n, g, print); #endif @@ -111,19 +112,17 @@ int main(int argc, char** argv) TestColumnMaxNorms(m, n, g, print); TestColumnMaxNorms(m, n, g, print); TestColumnMaxNorms(m, n, g, print); -#if defined(EL_HAVE_QD) && defined(EL_ENABLE_DOUBLEDOUBLE) +#if defined(EL_HAVE_QD) TestColumnMaxNorms(m, n, g, print); TestColumnMaxNorms(m, n, g, print); -#endif -#if defined(EL_HAVE_QD) && defined(EL_ENABLE_QUADDOUBLE) TestColumnMaxNorms(m, n, g, print); TestColumnMaxNorms(m, n, g, print); #endif -#if defined(EL_HAVE_QUAD) && defined(EL_ENABLE_QUAD) +#if defined(EL_HAVE_QUAD) TestColumnMaxNorms(m, n, g, print); TestColumnMaxNorms(m, n, g, print); #endif -#if defined(EL_HAVE_MPC) && defined(EL_ENABLE_BIGFLOAT) +#if defined(EL_HAVE_MPC) TestColumnMaxNorms(m, n, g, print); TestColumnMaxNorms(m, n, g, print); #endif diff --git a/tests/blas_like/Dot.cpp b/tests/blas_like/Dot.cpp index ce54b53b79..6ba62857ad 100644 --- a/tests/blas_like/Dot.cpp +++ b/tests/blas_like/Dot.cpp @@ -65,25 +65,23 @@ int main(int argc, char** argv) TestDot(m, n, g, print); TestDot, ELEMENT>(m, n, g, print); TestDot, BLOCK>(m, n, g, print); -#if defined(EL_HAVE_QD) && defined(EL_ENABLE_DOUBLEDOUBLE) +#if defined(EL_HAVE_QD) TestDot(m, n, g, print); TestDot(m, n, g, print); TestDot, ELEMENT>(m, n, g, print); TestDot, BLOCK>(m, n, g, print); -#endif -#if defined(EL_HAVE_QD) && defined(EL_ENABLE_QUADDOUBLE) TestDot(m, n, g, print); TestDot(m, n, g, print); TestDot, ELEMENT>(m, n, g, print); TestDot, BLOCK>(m, n, g, print); #endif -#if defined(EL_HAVE_QUAD) && defined(EL_ENABLE_QUAD) +#if defined(EL_HAVE_QUAD) TestDot(m, n, g, print); TestDot(m, n, g, print); TestDot, ELEMENT>(m, n, g, print); TestDot, BLOCK>(m, n, g, print); #endif -#if defined(EL_HAVE_MPC) && defined(EL_ENABLE_BIGFLOAT) +#if defined(EL_HAVE_MPC) TestDot(m, n, g, print); TestDot(m, n, g, print); TestDot, ELEMENT>(m, n, g, print); diff --git a/tests/blas_like/Hadamard.cpp b/tests/blas_like/Hadamard.cpp index 73cc5fd83d..0af0fa6468 100644 --- a/tests/blas_like/Hadamard.cpp +++ b/tests/blas_like/Hadamard.cpp @@ -68,25 +68,23 @@ int main(int argc, char** argv) TestHadamard(m, n, g, print); TestHadamard, ELEMENT>(m, n, g, print); TestHadamard, BLOCK>(m, n, g, print); -#if defined(EL_HAVE_QD) && defined(EL_ENABLE_DOUBLEDOUBLE) +#if defined(EL_HAVE_QD) TestHadamard(m, n, g, print); TestHadamard(m, n, g, print); TestHadamard, ELEMENT>(m, n, g, print); TestHadamard, BLOCK>(m, n, g, print); -#endif -#if defined(EL_HAVE_QD) && defined(EL_ENABLE_QUADDOUBLE) TestHadamard(m, n, g, print); TestHadamard(m, n, g, print); TestHadamard, ELEMENT>(m, n, g, print); TestHadamard, BLOCK>(m, n, g, print); #endif -#if defined(EL_HAVE_QUAD) && defined(EL_ENABLE_QUAD) +#if defined(EL_HAVE_QUAD) TestHadamard(m, n, g, print); TestHadamard(m, n, g, print); TestHadamard, ELEMENT>(m, n, g, print); TestHadamard, BLOCK>(m, n, g, print); #endif -#if defined(EL_HAVE_MPC) && defined(EL_ENABLE_BIGFLOAT) +#if defined(EL_HAVE_MPC) TestHadamard(m, n, g, print); TestHadamard(m, n, g, print); TestHadamard, ELEMENT>(m, n, g, print);