MyraMath
pgemm


Source: tests/pdense/pgemm.cpp

1 // ========================================================================= //
2 // This file is part of MyraMath, copyright (c) 2014-2019 by Ryan A Chilton //
3 // and distributed by MyraCore, LLC. See LICENSE.txt for license terms. //
4 // ========================================================================= //
5 
11 // Containers.
12 #include <myramath/dense/Matrix.h>
14 
15 // Serial algorithms.
17 #include <myramath/dense/gemm.h>
19 
20 // Parallel algorithms.
21 #include <myramath/pdense/pgemm.h>
23 
24 // Reporting.
25 #include <tests/myratest.h>
26 
27 using namespace myra;
28 typedef pdense::Options Options;
29 
30 namespace {
31 
32 template<class Number> void test_detail(int I, int J, int K, char op_A, char op_B, typename ReflectPrecision<Number>::type tolerance)
33  {
34  // Construct random A.
35  std::pair<int,int> A_size(I,J);
36  if (op_A == 'T' || op_A == 'H')
37  std::swap(A_size.first,A_size.second);
38  auto A = Matrix<Number>::random(A_size.first,A_size.second);
39  // Construct random B.
40  std::pair<int,int> B_size(J,K);
41  if (op_B == 'T' || op_B == 'H')
42  std::swap(B_size.first,B_size.second);
43  auto B = Matrix<Number>::random(B_size.first,B_size.second);
44  // Construct random C1 such that C = beta*C + alpha*op(A)*op(B) is well formed.
45  auto C1 = Matrix<Number>::random(I,K);
46  // Copy into C2.
47  Matrix<Number> C2 = C1;
48  // Randomize alpha/beta.
49  Number alpha = random<Number>();
50  Number beta = random<Number>();
51  Options options = Options::create().set_blocksize(64);
52  // Update C1/C2 using gemm/pgemm.
53  gemm_inplace(C1, A, op_A, B, op_B, alpha, beta);
54  pgemm_inplace(C2, A, op_A, B, op_B, alpha, beta, options);
55  // Check error between C1 and C2.
56  typedef typename ReflectPrecision<Number>::type Precision;
57  Precision error = frobenius(C1-C2)/frobenius(C1);
58  myra::out() << " |A^" << op_A << " * B^" << op_B << "|, gemm-pgemm = " << error << std::endl;
59  REQUIRE(error < tolerance);
60  }
61 
62 template<class Number> void test(int I, int J, int K, typename ReflectPrecision<Number>::type tolerance)
63  {
64  myra::out() << typestring<Number>() << std::endl;
65  test_detail<Number>(I,J,K,'N','N',tolerance); // C = A * B
66  test_detail<Number>(I,J,K,'N','T',tolerance); // C = A * B^T
67  test_detail<Number>(I,J,K,'N','H',tolerance); // C = A * B^H
68  test_detail<Number>(I,J,K,'T','N',tolerance); // C = A^T * B
69  test_detail<Number>(I,J,K,'T','T',tolerance); // C = A^T * B^T
70  test_detail<Number>(I,J,K,'T','H',tolerance); // C = A^T * B^H
71  test_detail<Number>(I,J,K,'H','N',tolerance); // C = A^H * B
72  test_detail<Number>(I,J,K,'H','T',tolerance); // C = A^H * B^T
73  test_detail<Number>(I,J,K,'H','H',tolerance); // C = A^H * B^H
74  }
75 
76 } // namespace
77 
78 ADD_TEST("pgemm","[pdense][parallel]")
79  {
80  int I = 207;
81  int J = 139;
82  int K = 162;
83  test<NumberS> (I,J,K,1.0e-4f);
84  test<NumberD> (I,J,K,1.0e-9);
85  test<NumberC> (I,J,K,1.0e-4f);
86  test<NumberZ> (I,J,K,1.0e-9);
87  }
Interface class for representing subranges of dense Matrix&#39;s.
Tabulates an IxJ matrix. Allows random access, has column major layout to be compatible with BLAS/LAP...
Definition: bdsqr.h:20
Routines for computing Frobenius norms of various algebraic containers.
static Matrix< Number > random(int I, int J)
Generates a random Matrix of specified size.
Definition: Matrix.cpp:353
Options pack for routines in /pdense.
Definition: Options.h:24
Definition: syntax.dox:1
General purpose dense matrix container, O(i*j) storage.
Options pack for routines in /pdense.
Reflects Precision trait for a Number, scalar Number types should specialize it.
Definition: Number.h:33
Simplistic random number functions.
Thread-parallel version of dense/gemm.h, Matrix*Matrix multiplication.
Variety of routines all for dense Matrix*Matrix multiplies. Delegates to the BLAS.


Results: [PASS]

float
|A^N * B^N|, gemm-pgemm = 1.91876e-07
|A^N * B^T|, gemm-pgemm = 1.90779e-07
|A^N * B^H|, gemm-pgemm = 1.91628e-07
|A^T * B^N|, gemm-pgemm = 6.6212e-08
|A^T * B^T|, gemm-pgemm = 1.91143e-07
|A^T * B^H|, gemm-pgemm = 1.89745e-07
|A^H * B^N|, gemm-pgemm = 1.83065e-07
|A^H * B^T|, gemm-pgemm = 1.75062e-07
|A^H * B^H|, gemm-pgemm = 1.92316e-07
double
|A^N * B^N|, gemm-pgemm = 0
|A^N * B^T|, gemm-pgemm = 0
|A^N * B^H|, gemm-pgemm = 0
|A^T * B^N|, gemm-pgemm = 0
|A^T * B^T|, gemm-pgemm = 0
|A^T * B^H|, gemm-pgemm = 0
|A^H * B^N|, gemm-pgemm = 0
|A^H * B^T|, gemm-pgemm = 0
|A^H * B^H|, gemm-pgemm = 0
std::complex<float>
|A^N * B^N|, gemm-pgemm = 1.94059e-07
|A^N * B^T|, gemm-pgemm = 1.94295e-07
|A^N * B^H|, gemm-pgemm = 1.93059e-07
|A^T * B^N|, gemm-pgemm = 1.92857e-07
|A^T * B^T|, gemm-pgemm = 1.95841e-07
|A^T * B^H|, gemm-pgemm = 1.96164e-07
|A^H * B^N|, gemm-pgemm = 1.93078e-07
|A^H * B^T|, gemm-pgemm = 1.92529e-07
|A^H * B^H|, gemm-pgemm = 1.95202e-07
std::complex<double>
|A^N * B^N|, gemm-pgemm = 0
|A^N * B^T|, gemm-pgemm = 0
|A^N * B^H|, gemm-pgemm = 0
|A^T * B^N|, gemm-pgemm = 0
|A^T * B^T|, gemm-pgemm = 0
|A^T * B^H|, gemm-pgemm = 0
|A^H * B^N|, gemm-pgemm = 0
|A^H * B^T|, gemm-pgemm = 0
|A^H * B^H|, gemm-pgemm = 0


Go back to Summary of /test programs.