cu-sp-matrix-test.cc
Go to the documentation of this file.
1 // cudamatrix/cu-sp-matrix-test.cc
2 //
3 // Copyright 2013 Ehsan Variani
4 // Lucas Ondel
5 // Johns Hopkins University (author: Daniel Povey)
6 
7 // See ../../COPYING for clarification regarding multiple authors
8 //
9 // Licensed under the Apache License, Version 2.0 (the "License");
10 // you may not use this file except in compliance with the License.
11 // You may obtain a copy of the License at
12 
13 // http://www.apache.org/licenses/LICENSE-2.0
14 
15 // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
17 // WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
18 // MERCHANTABLITY OR NON-INFRINGEMENT.
19 // See the Apache 2 License for the specific language governing permissions and
20 // limitations under the License.
21 //
22 //
23 // UnitTests for testing cu-sp-matrix.h methods.
24 //
25 
26 #include <iostream>
27 #include <vector>
28 #include <cstdlib>
29 
30 #include "base/kaldi-common.h"
31 #include "cudamatrix/cu-device.h"
33 #include "cudamatrix/cu-vector.h"
34 #include "cudamatrix/cu-math.h"
35 
36 using namespace kaldi;
37 
38 namespace kaldi {
39 
40 /*
41  * Unit Tests
42  */
43 template<typename Real>
45  for (MatrixIndexT i = 1; i < 10; i++) {
46  MatrixIndexT dim = 10 * i;
47 
48  Matrix<Real> A(dim, dim);
49  A.SetRandn();
51 
52  CuMatrix<Real> C(A);
54 
55  SpMatrix<Real> E(dim);
56  D.CopyToSp(&E);
57 
58  SpMatrix<Real> F(D);
59 
60  AssertEqual(F, B);
61  //added by hxu, to test copy from SpMatrix to CuSpMatrix
62 
63  AssertEqual(B, E);
64 
65  KALDI_ASSERT(!B.IsUnit());
66  B.SetZero();
67  B.SetDiag(1.0);
68  KALDI_ASSERT(B.IsUnit());
69  }
70 }
71 
72 template<typename Real>
74 
75  for (int32 i = 0; i < 10; i++) {
76  int32 dim = 1 + Rand() % 10;
77  SpMatrix<Real> A(dim), B(dim);
78  A.SetRandn();
79  B.SetRandn();
80  BaseFloat threshold = 0.01;
81  for (int32 j = 0; j < 20; j++, threshold *= 1.3) {
82  bool b1 = A.ApproxEqual(B, threshold);
83  SpMatrix<Real> diff(A);
84  diff.AddSp(-1.0, B);
85  bool b2 = (diff.FrobeniusNorm() < threshold * std::max(A.FrobeniusNorm(),
86  B.FrobeniusNorm()));
87  KALDI_ASSERT(b1 == b2);
88  }
89  }
90 
91 }
92 
93 
94 
95 template<typename Real>
97  SpMatrix<Real> A(100);
98  A.SetRandn();
99 
100  CuSpMatrix<Real> B(100);
101  B.CopyFromSp(A);
102 
103  for (MatrixIndexT i = 0; i < A.NumRows(); i++) {
104  for (MatrixIndexT j = 0; j <= i; j++)
105  KALDI_ASSERT(std::abs(A(i, j) - B(i, j)) < 0.0001);
106  }
107 }
108 
109 template<typename Real>
111  for (MatrixIndexT i = 1; i < 10; i++) {
112  MatrixIndexT dim = 10*i;
113  SpMatrix<Real> A(dim);
114  A.SetRandn();
115  CuSpMatrix<Real> B(A);
116 
117  Matrix<Real> D(A);
118  A.AddToDiag(i);
119 
120  CuMatrix<Real> C(B);
121  B.AddToDiag(i);
122 
123  SpMatrix<Real> E(dim);
124  B.CopyToSp(&E);
125 
126  AssertEqual(A, E);
127  }
128 }
129 
130 
131 template<typename Real>
133  for (MatrixIndexT i = 1; i < 10; i++) {
134  SpCopyType copy_type = (i % 3 == 0 ? kTakeMean :
135  (i % 3 == 1 ? kTakeLower : kTakeUpper));
136  MatrixIndexT dim = 10 * i + Rand() % 5;
137  CuMatrix<Real> A(dim, dim);
138  A.SetRandn();
139  Matrix<Real> A2(A);
140 
141  CuSpMatrix<Real> B(A, copy_type);
142  SpMatrix<Real> B2(A2, copy_type);
143  SpMatrix<Real> B3(B);
144  if (!ApproxEqual(B2, B3) ) {
145  KALDI_ERR << "Matrices differ, A = " << A << ", B2 = " << B2 << ", B3(CUDA) = " << B3;
146  }
147  KALDI_ASSERT(B3.Trace() != 0);
148  }
149 }
150 
151 template<typename Real>
153  for (MatrixIndexT i = 1; i < 10; i++) {
154  MatrixIndexT dim = 10*i + Rand() % 5;
155  CuSpMatrix<Real> A(dim);
156  A.SetRandn();
157  KALDI_ASSERT(A.Trace() != 0.0); // true with probability 1...
158  SpMatrix<Real> B(A);
159 
160  CuMatrix<Real> D(A);
161  A.AddMat2(1.0, D, kTrans, 1.0);
162  A.AddToDiag(i);
163 
164  Matrix<Real> C(B);
165  B.AddMat2(1.0, C, kTrans, 1.0);
166  B.AddToDiag(i);
167 
168  CuSpMatrix<Real> Acopy(A);
169  A.Invert();
170  B.Invert();
171 
172  SpMatrix<Real> A2(A);
173  AssertEqual(A2, B);
174 
175  CuMatrix<Real> I(dim, dim);
176  I.AddMatMat(1.0, CuMatrix<Real>(Acopy), kNoTrans, CuMatrix<Real>(A), kNoTrans, 0.0);
177  KALDI_ASSERT(I.IsUnit(0.01));
178  }
179 }
180 
181 // TODO (variani) : fails for dim = 0
182 template<typename Real>
184  for (int32 i = 0; i < 50; i++) {
185  MatrixIndexT dim = 1 + Rand() % 200;
186  SpMatrix<Real> A(dim);
187  A.SetRandn();
188  CuSpMatrix<Real> B(A);
189 
190  Vector<Real> C(dim);
191  C.SetRandn();
192  CuVector<Real> D(C);
193  Real alpha = RandGauss();
194 
195  A.AddVec2(alpha, C);
196  B.AddVec2(alpha, D);
197 
198  SpMatrix<Real> E(dim);
199  B.CopyToSp(&E);
200 
201  AssertEqual(A, E);
202  }
203 }
204 
205 template<typename Real>
207  for (MatrixIndexT i = 1; i < 10; i++) {
208  MatrixIndexT dim_row = 15 * i + Rand() % 10;
209  MatrixIndexT dim_col = 7 *i + Rand() % 10;
210  Matrix<Real> A(dim_row, dim_col);
211  A.SetRandn();
212  CuMatrix<Real> B(A);
213 
214  SpMatrix<Real> C(dim_col);
215  C.SetRandn();
216  CuSpMatrix<Real> D(C);
217 
218  const Real alpha = 2.0;
219  const Real beta = 3.0;
220 
221  C.AddMat2(alpha, A, kTrans, beta);
222  D.AddMat2(alpha, B, kTrans, beta);
223 
224  SpMatrix<Real> E(dim_col);
225  D.CopyToSp(&E);
226 
227  AssertEqual(C, E);
228  }
229 }
230 
231 template<typename Real>
232 static void UnitTestCuSpMatrixAddSp() {
233  for (MatrixIndexT i = 1; i < 50; i++) {
234  MatrixIndexT dim = 7 * i + Rand() % 10;
235 
236  SpMatrix<Real> A(dim);
237  A.SetRandn();
238  CuSpMatrix<Real> B(A);
239 
240  SpMatrix<Real> C(dim);
241  C.SetRandn();
242  const CuSpMatrix<Real> D(C);
243 
244  const Real alpha = 2.0;
245 
246  A.AddSp(alpha, C);
247  B.AddSp(alpha, D);
248 
249  SpMatrix<Real> E(dim);
250  B.CopyToSp(&E);
251 
252  AssertEqual(A, E);
253  }
254 }
255 
256 template<typename Real, typename OtherReal>
258  for (MatrixIndexT i = 1; i < 2; i++) {
259  MatrixIndexT dim = 100 + Rand() % 255;
260 
261  SpMatrix<Real> A(dim);
262  A.SetRandn();
263  const CuSpMatrix<Real> B(A);
264  SpMatrix<OtherReal> C(dim);
265  C.SetRandn();
266  const CuSpMatrix<OtherReal> D(C);
267 
268  Real t1 = TraceSpSp(A, C), t2 = TraceSpSp(B, D);
269  KALDI_ASSERT(ApproxEqual(t1, t2));
270  }
271 }
272 
273 
274 template<typename Real>
276  for (MatrixIndexT i = 1; i < 10; i++) {
277  MatrixIndexT dim = 100 * i + Rand() % 255;
278  if (i % 5 == 0) dim = 0;
279  CuSpMatrix<Real> S1(dim), S2(dim), S4(dim);
280  S1.SetRandn();
281  S2.SetRandn();
282  S4.SetRandn();
283  SpMatrix<Real> S3(dim);
284  S3.SetUnit();
285  S1.SetUnit();
286  S2.SetZero();
287  S2.SetDiag(1.0);
288  S4.SetZero();
289  S4.AddToDiag(0.4);
290  S4.AddToDiag(0.6);
291  CuSpMatrix<Real> cu_S3(S3);
292  KALDI_LOG << "S1 norm is " << S1.FrobeniusNorm();
293  KALDI_LOG << "S2 norm is " << S2.FrobeniusNorm();
294  KALDI_LOG << "S3 norm is " << S3.FrobeniusNorm();
295  AssertEqual(S1, cu_S3);
296  AssertEqual(S2, cu_S3);
297  AssertEqual(S4, cu_S3);
298  }
299 }
300 
301 template<class Real>
302 static void UnitTestCuSpMatrixIO() {
303  for (int32 i = 0; i < 10; i++) {
304  int32 dimM = Rand() % 255;
305  if (i % 5 == 0) { dimM = 0; }
306  CuSpMatrix<Real> mat(dimM);
307  mat.SetRandn();
308  std::ostringstream os;
309  bool binary = (i % 4 < 2);
310  mat.Write(os, binary);
311 
312  CuSpMatrix<Real> mat2;
313  std::istringstream is(os.str());
314  mat2.Read(is, binary);
315  AssertEqual(mat, mat2);
316  }
317 }
318 
319 
320 
321 
322 template<typename Real, typename OtherReal>
323 static void UnitTestCuSpMatrixAddSp() {
324  for (MatrixIndexT i = 1; i < 10; i++) {
325  MatrixIndexT dim = 100 * i + Rand() % 255;
326 
327  SpMatrix<Real> A(dim);
328  A.SetRandn();
329  const CuSpMatrix<Real> B(A);
330  SpMatrix<OtherReal> C(dim);
331  C.SetRandn();
332  const CuSpMatrix<OtherReal> D(C);
333 
334  A.AddSp(1.0, C);
335  B.AddSp(1.0, D);
336 
337  AssertEqual(A, B);
338 
339  }
340 }
341 
342 template<typename Real> void CudaSpMatrixUnitTest() {
343  UnitTestCuSpMatrixIO<Real>();
344  UnitTestCuSpMatrixConstructor<Real>();
345  UnitTestCuSpMatrixOperator<Real>();
346  UnitTestCuSpMatrixApproxEqual<Real>();
347  UnitTestCuSpMatrixInvert<Real>();
348  UnitTestCuSpMatrixCopyFromMat<Real>();
349  UnitTestCuSpMatrixAddVec2<Real>();
350  UnitTestCuSpMatrixAddMat2<Real>();
351  UnitTestCuSpMatrixAddSp<Real>();
352  UnitTestCuSpMatrixAddToDiag<Real>();
353  UnitTestCuSpMatrixSetUnit<Real>();
354 }
355 
356 template<typename Real, typename OtherReal> void CudaSpMatrixUnitTest() {
357  UnitTestCuSpMatrixTraceSpSp<Real, OtherReal>();
358 
359 }
360 
361 } // namespace kaldi
362 
363 
364 int main() {
365  using namespace kaldi;
366  SetVerboseLevel(1);
367  int32 loop = 0;
368 #if HAVE_CUDA == 1
369  for (; loop < 2; loop++) {
370  CuDevice::Instantiate().SetDebugStrideMode(true);
371  if (loop == 0)
372  CuDevice::Instantiate().SelectGpuId("no"); // -1 means no GPU
373  else
374  CuDevice::Instantiate().SelectGpuId("yes"); // -2 .. automatic selection
375 #endif
376 
377  kaldi::CudaSpMatrixUnitTest<float>();
378  kaldi::CudaSpMatrixUnitTest<float, float>();
379 #if HAVE_CUDA == 1
380  if (CuDevice::Instantiate().DoublePrecisionSupported()) {
381  kaldi::CudaSpMatrixUnitTest<double>();
382  kaldi::CudaSpMatrixUnitTest<float, double>();
383  kaldi::CudaSpMatrixUnitTest<double, float>();
384  kaldi::CudaSpMatrixUnitTest<double, double>();
385  } else {
386  KALDI_WARN << "Double precision not supported";
387  }
388 #else
389  kaldi::CudaSpMatrixUnitTest<float, double>();
390  kaldi::CudaSpMatrixUnitTest<double, float>();
391  kaldi::CudaSpMatrixUnitTest<double, double>();
392 #endif
393 
394  if (loop == 0)
395  KALDI_LOG << "Tests without GPU use succeeded.";
396  else
397  KALDI_LOG << "Tests with GPU use (if available) succeeded.";
398 #if HAVE_CUDA == 1
399  }
400  CuDevice::Instantiate().PrintProfile();
401 #endif
402  return 0;
403 }
void AddMat2(const Real alpha, const MatrixBase< Real > &M, MatrixTransposeType transM, const Real beta)
rank-N update: if (transM == kNoTrans) (*this) = beta*(*this) + alpha * M * M^T, or (if transM == kTr...
Definition: sp-matrix.cc:1110
This code computes Goodness of Pronunciation (GOP) and extracts phone-level pronunciation feature for...
Definition: chain.dox:20
bool IsUnit(Real cutoff=1.0e-05) const
Definition: sp-matrix.cc:480
Packed symetric matrix class.
Definition: matrix-common.h:62
void CudaSpMatrixUnitTest()
static void UnitTestCuSpMatrixConstructor()
Real Trace() const
Definition: sp-matrix.cc:171
static void UnitTestCuSpMatrixAddMat2()
Real FrobeniusNorm() const
sqrt of sum of square elements.
Definition: sp-matrix.cc:513
void AddToDiag(Real r)
< Set the diagonal value to alpha
float RandGauss(struct RandomState *state=NULL)
Definition: kaldi-math.h:155
kaldi::int32 int32
A class for storing matrices.
Definition: kaldi-matrix.h:823
This class represents a matrix that&#39;s stored on the GPU if we have one, and in memory if not...
Definition: matrix-common.h:71
void Invert()
Note: the CuMatrix version of the Invert() function will only work for positive definite matrices; it...
Definition: cu-sp-matrix.cc:93
void SetUnit()
< Set to zero
MatrixIndexT NumRows() const
void SetRandn()
< Set to unit matrix.
static void UnitTestCuSpMatrixIO()
bool IsUnit(Real tol=0.001) const
Definition: cu-matrix.cc:629
void SetRandn()
< Set to unit matrix.
void SetVerboseLevel(int32 i)
This should be rarely used, except by programs using Kaldi as library; command-line programs set the ...
Definition: kaldi-error.h:64
static void UnitTestCuSpMatrixOperator()
void AddToDiag(const Real r)
void AddVec2(const Real alpha, const VectorBase< OtherReal > &v)
rank-one update, this <– this + alpha v v&#39;
Definition: sp-matrix.cc:946
int32 MatrixIndexT
Definition: matrix-common.h:98
void Read(std::istream &in, bool binary)
void UnitTestCuSpMatrixSetUnit()
void AddSp(const Real alpha, const SpMatrix< Real > &Ma)
Definition: sp-matrix.h:211
void SetDiag(const Real alpha)
void SetRandn()
Sets to random values of a normal distribution.
#define KALDI_ERR
Definition: kaldi-error.h:147
double TraceSpSp(const SpMatrix< double > &A, const SpMatrix< double > &B)
Definition: sp-matrix.cc:326
void AddMatMat(Real alpha, const CuMatrixBase< Real > &A, MatrixTransposeType transA, const CuMatrixBase< Real > &B, MatrixTransposeType transB, Real beta)
C = alpha * A(^T)*B(^T) + beta * C.
Definition: cu-matrix.cc:1291
#define KALDI_WARN
Definition: kaldi-error.h:150
static void UnitTestCuSpMatrixTraceSpSp()
int Rand(struct RandomState *state)
Definition: kaldi-math.cc:45
void SetRandn()
Set vector to random normally-distributed noise.
static void UnitTestCuSpMatrixApproxEqual()
void CopyToSp(SpMatrix< Real > *dst) const
Definition: cu-sp-matrix.h:95
void CopyFromSp(const CuSpMatrix< Real > &other)
Definition: cu-sp-matrix.h:85
void AddSp(const Real alpha, const CuSpMatrix< Real > &Ma)
Definition: cu-sp-matrix.h:127
static void UnitTestCuSpMatrixAddVec2()
A class representing a vector.
Definition: kaldi-vector.h:406
static void UnitTestCuSpMatrixAddSp()
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
int main()
static void AssertEqual(float a, float b, float relative_tolerance=0.001)
assert abs(a - b) <= relative_tolerance * (abs(a)+abs(b))
Definition: kaldi-math.h:276
static void UnitTestCuSpMatrixInvert(int32 dim)
static void UnitTestCuSpMatrixCopyFromMat(int32 dim, SpCopyType copy_type)
void Write(std::ostream &out, bool binary) const
void Invert(Real *logdet=NULL, Real *det_sign=NULL, bool inverse_needed=true)
matrix inverse.
Definition: sp-matrix.cc:219
#define KALDI_LOG
Definition: kaldi-error.h:153
static void UnitTestCuSpMatrixAddToDiag()
void AddMat2(const Real alpha, const CuMatrixBase< Real > &M, MatrixTransposeType transM, const Real beta)
static bool ApproxEqual(float a, float b, float relative_tolerance=0.001)
return abs(a - b) <= relative_tolerance * (abs(a)+abs(b)).
Definition: kaldi-math.h:265
void AddVec2(const Real alpha, const CuVectorBase< Real > &v)