MAGMA  magma-1.4.0
Matrix Algebra on GPU and Multicore Architectures
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
testing_util.cpp
Go to the documentation of this file.
1 /*
2  -- MAGMA (version 1.4.0) --
3  Univ. of Tennessee, Knoxville
4  Univ. of California, Berkeley
5  Univ. of Colorado, Denver
6  August 2013
7 
8  @precisions normal z -> c d s
9  @author Mark Gates
10 
11  Utilities for testing.
12 */
13 
14 #include <string.h>
15 #include <assert.h>
16 
17 #include "testings.h"
18 
19 // --------------------
20 // If condition is false, print error message and exit.
21 // Error message is formatted using printf, using any additional arguments.
22 extern "C"
23 void magma_assert( bool condition, const char* msg, ... )
24 {
25  if ( ! condition ) {
26  va_list va;
27  va_start( va, msg );
28  vprintf( msg, va );
29  exit(1);
30  }
31 }
32 
33 
34 // --------------------
35 const char *usage_short =
36 "Usage: %s [options] [-h|--help]\n\n";
37 
38 const char *usage =
39 "Options are:\n"
40 " --range start:stop:step\n"
41 " Adds test cases with range for sizes m,n,k. Can be repeated.\n"
42 " -N m[,n[,k]] Adds one test case with sizes m,n,k. Can be repeated.\n"
43 " If only m,n given then k=n. If only m given then n=k=m.\n"
44 " -m m Sets m for all tests, overriding -N and --range.\n"
45 " -n n Sets n for all tests, overriding -N and --range.\n"
46 " -k k Sets k for all tests, overriding -N and --range.\n"
47 " Default test sizes are the range 1088 : 10304 : 1024, that is, 1K+64 : 10K+64 : 1K.\n"
48 "\n"
49 " -c --[no]check Whether to check results. Some tests always check.\n"
50 " Also set with $MAGMA_TESTINGS_CHECK.\n"
51 " -c2 --check2 For getrf, check residual |Ax-b| instead of |PA-LU|.\n"
52 " -l --[no]lapack Whether to run lapack. Some tests always run lapack.\n"
53 " Also set with $MAGMA_RUN_LAPACK.\n"
54 " --[no]warmup Whether to warmup. Not yet implemented in most cases.\n"
55 " Also set with $MAGMA_WARMUP.\n"
56 " --[not]all Whether to test all combinations of flags, e.g., jobu.\n"
57 " --dev x GPU device to use, default 0.\n"
58 "\n"
59 "The following options apply to only some routines.\n"
60 " --nb x Block size, default set automatically.\n"
61 " --nrhs x Number of right hand sides, default 1.\n"
62 " --nstream x Number of CUDA streams, default 1.\n"
63 " --ngpu x Number of GPUs, default 1. Also set with $MAGMA_NUM_GPUS.\n"
64 " --niter x Number of iterations to repeat each test, default 1.\n"
65 " --nthread x Number of CPU threads, default 1.\n"
66 " --itype [123] Generalized Hermitian-definite eigenproblem type, default 1.\n"
67 " --work [123] SVD workspace size, from min (1) to max (3), default 1.\n"
68 " --version x version of routine, e.g., during development, default 1.\n"
69 " --fraction x fraction of eigenvectors to compute, default 1.\n"
70 " --tolerance x accuracy tolerance, multiplied by machine epsilon, default 30.\n"
71 " -L -U -F uplo = Lower*, Upper, or Full.\n"
72 " -[NTC][NTC] transA = NoTrans*, Trans, or ConjTrans (first letter) and\n"
73 " transB = NoTrans*, Trans, or ConjTrans (second letter).\n"
74 " -S[LR] side = Left*, Right.\n"
75 " -D[NU] diag = NonUnit*, Unit.\n"
76 " -U[NASO] jobu = No*, All, Some, or Overwrite; compute left singular vectors.\n"
77 " -V[NASO] jobvt = No*, All, Some, or Overwrite; compute right singular vectors.\n"
78 " -J[NV] jobz = No* or Vectors; compute eigenvectors.\n"
79 " -L[NV] jobvl = No* or Vectors; compute left eigenvectors.\n"
80 " -R[NV] jobvr = No* or Vectors; compute right eigenvectors.\n"
81 " * default values\n";
82 
83 extern "C"
84 void parse_opts( int argc, char** argv, magma_opts *opts )
85 {
86  // negative flag indicating -m, -n, -k not given
87  int m = -1;
88  int n = -1;
89  int k = -1;
90 
91  // fill in default values
92  opts->device = 0;
93  opts->nb = 0; // auto
94  opts->nrhs = 1;
95  opts->nstream = 1;
96  opts->ngpu = magma_num_gpus();
97  opts->niter = 1;
98  opts->nthread = 1;
99  opts->itype = 1;
100  opts->svd_work = 1;
101  opts->version = 1;
102  opts->fraction = 1.;
103  opts->tolerance = 30.;
104 
105  opts->check = (getenv("MAGMA_TESTINGS_CHECK") != NULL);
106  opts->lapack = (getenv("MAGMA_RUN_LAPACK") != NULL);
107  opts->warmup = (getenv("MAGMA_WARMUP") != NULL);
108  opts->all = (getenv("MAGMA_RUN_ALL") != NULL);
109 
110  opts->uplo = MagmaLower; // potrf, etc.
111  opts->transA = MagmaNoTrans; // gemm, etc.
112  opts->transB = MagmaNoTrans; // gemm
113  opts->side = MagmaLeft; // trsm, etc.
114  opts->diag = MagmaNonUnit; // trsm, etc.
115  opts->jobu = MagmaNoVec; // gesvd: no left singular vectors
116  opts->jobvt = MagmaNoVec; // gesvd: no right singular vectors
117  opts->jobz = MagmaNoVec; // heev: no eigen vectors
118  opts->jobvr = MagmaNoVec; // geev: no right eigen vectors
119  opts->jobvl = MagmaNoVec; // geev: no left eigen vectors
120 
121  printf( usage_short, argv[0] );
122 
123  int ndevices;
124  cudaGetDeviceCount( &ndevices );
125 
126  int info;
127  int ntest = 0;
128  for( int i = 1; i < argc; ++i ) {
129  // ----- matrix size
130  // each -N fills in next entry of msize, nsize, ksize and increments ntest
131  if ( strcmp("-N", argv[i]) == 0 && i+1 < argc ) {
132  magma_assert( ntest < MAX_NTEST, "error: -N %s, max number of tests exceeded, ntest=%d.\n",
133  argv[i], ntest );
134  i++;
135  int m2, n2, k2;
136  info = sscanf( argv[i], "%d,%d,%d", &m2, &n2, &k2 );
137  if ( info == 3 && m2 >= 0 && n2 >= 0 && k2 >= 0 ) {
138  opts->msize[ ntest ] = m2;
139  opts->nsize[ ntest ] = n2;
140  opts->ksize[ ntest ] = k2;
141  }
142  else if ( info == 2 && m2 >= 0 && n2 >= 0 ) {
143  opts->msize[ ntest ] = m2;
144  opts->nsize[ ntest ] = n2;
145  opts->ksize[ ntest ] = n2; // implicitly
146  }
147  else if ( info == 1 && m2 >= 0 ) {
148  opts->msize[ ntest ] = m2;
149  opts->nsize[ ntest ] = m2; // implicitly
150  opts->ksize[ ntest ] = m2; // implicitly
151  }
152  else {
153  fprintf( stderr, "error: -N %s is invalid; ensure m >= 0, n >= 0, k >= 0.\n",
154  argv[i] );
155  exit(1);
156  }
157  ntest++;
158  }
159  // --range start:stop:step fills in msize[ntest:], nsize[ntest:], ksize[ntest:]
160  // with given range and updates ntest
161  else if ( strcmp("--range", argv[i]) == 0 && i+1 < argc ) {
162  i++;
163  int start, stop, step;
164  info = sscanf( argv[i], "%d:%d:%d", &start, &stop, &step );
165  if ( info == 3 && start >= 0 && stop >= 0 && step != 0 ) {
166  for( int n = start; (step > 0 ? n <= stop : n >= stop); n += step ) {
167  if ( ntest >= MAX_NTEST ) {
168  printf( "warning: --range %s, max number of tests reached, ntest=%d.\n",
169  argv[i], ntest );
170  break;
171  }
172  opts->msize[ ntest ] = n;
173  opts->nsize[ ntest ] = n;
174  opts->ksize[ ntest ] = n;
175  ntest++;
176  }
177  }
178  else {
179  fprintf( stderr, "error: --range %s is invalid; ensure start >= 0, stop >= start, step > 0.\n",
180  argv[i] );
181  exit(1);
182  }
183  }
184  // save m, n, k if -m, -n, -k is given; applied after loop
185  else if ( strcmp("-m", argv[i]) == 0 && i+1 < argc ) {
186  m = atoi( argv[++i] );
187  magma_assert( m >= 0, "error: -m %s is invalid; ensure m >= 0.\n", argv[i] );
188  }
189  else if ( strcmp("-n", argv[i]) == 0 && i+1 < argc ) {
190  n = atoi( argv[++i] );
191  magma_assert( n >= 0, "error: -n %s is invalid; ensure n >= 0.\n", argv[i] );
192  }
193  else if ( strcmp("-k", argv[i]) == 0 && i+1 < argc ) {
194  k = atoi( argv[++i] );
195  magma_assert( k >= 0, "error: -k %s is invalid; ensure k >= 0.\n", argv[i] );
196  }
197 
198  // ----- scalar arguments
199  else if ( strcmp("--dev", argv[i]) == 0 && i+1 < argc ) {
200  opts->device = atoi( argv[++i] );
201  magma_assert( opts->device >= 0 && opts->device < ndevices,
202  "error: --dev %s is invalid; ensure dev in [0,%d].\n", argv[i], ndevices-1 );
203  }
204  else if ( strcmp("--nrhs", argv[i]) == 0 && i+1 < argc ) {
205  opts->nrhs = atoi( argv[++i] );
206  magma_assert( opts->nrhs >= 0,
207  "error: --nrhs %s is invalid; ensure nrhs >= 0.\n", argv[i] );
208  }
209  else if ( strcmp("--nb", argv[i]) == 0 && i+1 < argc ) {
210  opts->nb = atoi( argv[++i] );
211  magma_assert( opts->nb > 0,
212  "error: --nb %s is invalid; ensure nb > 0.\n", argv[i] );
213  }
214  else if ( strcmp("--ngpu", argv[i]) == 0 && i+1 < argc ) {
215  opts->ngpu = atoi( argv[++i] );
216  magma_assert( opts->ngpu <= MagmaMaxGPUs,
217  "error: --ngpu %s exceeds MagmaMaxGPUs, %d.\n", argv[i], MagmaMaxGPUs );
218  magma_assert( opts->ngpu <= ndevices,
219  "error: --ngpu %s exceeds number of CUDA devices, %d.\n", argv[i], ndevices );
220  magma_assert( opts->ngpu > 0,
221  "error: --ngpu %s is invalid; ensure ngpu > 0.\n", argv[i] );
222  // save in environment variable, so magma_num_gpus() picks it up
223  setenv( "MAGMA_NUM_GPUS", argv[i], true );
224  }
225  else if ( strcmp("--nstream", argv[i]) == 0 && i+1 < argc ) {
226  opts->nstream = atoi( argv[++i] );
227  magma_assert( opts->nstream > 0,
228  "error: --nstream %s is invalid; ensure nstream > 0.\n", argv[i] );
229  }
230  else if ( strcmp("--niter", argv[i]) == 0 && i+1 < argc ) {
231  opts->niter = atoi( argv[++i] );
232  magma_assert( opts->niter > 0,
233  "error: --niter %s is invalid; ensure niter > 0.\n", argv[i] );
234  }
235  else if ( strcmp("--nthread", argv[i]) == 0 && i+1 < argc ) {
236  opts->nthread = atoi( argv[++i] );
237  magma_assert( opts->nthread > 0,
238  "error: --nthread %s is invalid; ensure nthread > 0.\n", argv[i] );
239  }
240  else if ( strcmp("--itype", argv[i]) == 0 && i+1 < argc ) {
241  opts->itype = atoi( argv[++i] );
242  magma_assert( opts->itype >= 1 && opts->itype <= 3,
243  "error: --itype %s is invalid; ensure itype in [1,2,3].\n", argv[i] );
244  }
245  else if ( strcmp("--work", argv[i]) == 0 && i+1 < argc ) {
246  opts->svd_work = atoi( argv[++i] );
247  magma_assert( opts->svd_work >= 1 && opts->svd_work <= 3,
248  "error: --work %s is invalid; ensure work in [1,2,3].\n", argv[i] );
249  }
250  else if ( strcmp("--version", argv[i]) == 0 && i+1 < argc ) {
251  opts->version = atoi( argv[++i] );
252  magma_assert( opts->version >= 1,
253  "error: --version %s is invalid; ensure version > 0.\n", argv[i] );
254  }
255  else if ( strcmp("--fraction", argv[i]) == 0 && i+1 < argc ) {
256  opts->fraction = atof( argv[++i] );
257  magma_assert( opts->fraction >= 0 && opts->fraction <= 1,
258  "error: --fraction %s is invalid; ensure fraction in [0,1].\n", argv[i] );
259  }
260  else if ( strcmp("--tolerance", argv[i]) == 0 && i+1 < argc ) {
261  opts->tolerance = atof( argv[++i] );
262  magma_assert( opts->tolerance >= 0 && opts->tolerance <= 1000,
263  "error: --tolerance %s is invalid; ensure tolerance in [0,1000].\n", argv[i] );
264  }
265 
266  // ----- boolean arguments
267  // check results
268  else if ( strcmp("-c", argv[i]) == 0 ||
269  strcmp("--check", argv[i]) == 0 ) { opts->check = 1; }
270  else if ( strcmp("-c2", argv[i]) == 0 ||
271  strcmp("--check2", argv[i]) == 0 ) { opts->check = 2; }
272  else if ( strcmp("--nocheck", argv[i]) == 0 ) { opts->check = 0; }
273  else if ( strcmp("-l", argv[i]) == 0 ||
274  strcmp("--lapack", argv[i]) == 0 ) { opts->lapack = true; }
275  else if ( strcmp("--nolapack", argv[i]) == 0 ) { opts->lapack = false; }
276  else if ( strcmp("--warmup", argv[i]) == 0 ) { opts->warmup = true; }
277  else if ( strcmp("--nowarmup", argv[i]) == 0 ) { opts->warmup = false; }
278  else if ( strcmp("--all", argv[i]) == 0 ) { opts->all = true; }
279  else if ( strcmp("--notall", argv[i]) == 0 ) { opts->all = false; }
280 
281  // ----- lapack flag arguments
282  else if ( strcmp("-L", argv[i]) == 0 ) { opts->uplo = MagmaLower; }
283  else if ( strcmp("-U", argv[i]) == 0 ) { opts->uplo = MagmaUpper; }
284  else if ( strcmp("-F", argv[i]) == 0 ) { opts->uplo = MagmaUpperLower; }
285 
286  else if ( strcmp("-NN", argv[i]) == 0 ) { opts->transA = MagmaNoTrans; opts->transB = MagmaNoTrans; }
287  else if ( strcmp("-NT", argv[i]) == 0 ) { opts->transA = MagmaNoTrans; opts->transB = MagmaTrans; }
288  else if ( strcmp("-NC", argv[i]) == 0 ) { opts->transA = MagmaNoTrans; opts->transB = MagmaConjTrans; }
289  else if ( strcmp("-TN", argv[i]) == 0 ) { opts->transA = MagmaTrans; opts->transB = MagmaNoTrans; }
290  else if ( strcmp("-TT", argv[i]) == 0 ) { opts->transA = MagmaTrans; opts->transB = MagmaTrans; }
291  else if ( strcmp("-TC", argv[i]) == 0 ) { opts->transA = MagmaTrans; opts->transB = MagmaConjTrans; }
292  else if ( strcmp("-CN", argv[i]) == 0 ) { opts->transA = MagmaConjTrans; opts->transB = MagmaNoTrans; }
293  else if ( strcmp("-CT", argv[i]) == 0 ) { opts->transA = MagmaConjTrans; opts->transB = MagmaTrans; }
294  else if ( strcmp("-CC", argv[i]) == 0 ) { opts->transA = MagmaConjTrans; opts->transB = MagmaConjTrans; }
295 
296  else if ( strcmp("-SL", argv[i]) == 0 ) { opts->side = MagmaLeft; }
297  else if ( strcmp("-SR", argv[i]) == 0 ) { opts->side = MagmaRight; }
298 
299  else if ( strcmp("-DN", argv[i]) == 0 ) { opts->diag = MagmaNonUnit; }
300  else if ( strcmp("-DU", argv[i]) == 0 ) { opts->diag = MagmaUnit; }
301 
302  else if ( strcmp("-UA", argv[i]) == 0 ) { opts->jobu = MagmaAllVec; }
303  else if ( strcmp("-US", argv[i]) == 0 ) { opts->jobu = MagmaSomeVec; }
304  else if ( strcmp("-UO", argv[i]) == 0 ) { opts->jobu = MagmaOverwriteVec; }
305  else if ( strcmp("-UN", argv[i]) == 0 ) { opts->jobu = MagmaNoVec; }
306 
307  else if ( strcmp("-VA", argv[i]) == 0 ) { opts->jobvt = MagmaAllVec; }
308  else if ( strcmp("-VS", argv[i]) == 0 ) { opts->jobvt = MagmaSomeVec; }
309  else if ( strcmp("-VO", argv[i]) == 0 ) { opts->jobvt = MagmaOverwriteVec; }
310  else if ( strcmp("-VN", argv[i]) == 0 ) { opts->jobvt = MagmaNoVec; }
311 
312  else if ( strcmp("-JN", argv[i]) == 0 ) { opts->jobz = MagmaNoVec; }
313  else if ( strcmp("-JV", argv[i]) == 0 ) { opts->jobz = MagmaVec; }
314 
315  else if ( strcmp("-LN", argv[i]) == 0 ) { opts->jobvl = MagmaNoVec; }
316  else if ( strcmp("-LV", argv[i]) == 0 ) { opts->jobvl = MagmaVec; }
317 
318  else if ( strcmp("-RN", argv[i]) == 0 ) { opts->jobvr = MagmaNoVec; }
319  else if ( strcmp("-RV", argv[i]) == 0 ) { opts->jobvr = MagmaVec; }
320 
321  // ----- usage
322  else if ( strcmp("-h", argv[i]) == 0 ||
323  strcmp("--help", argv[i]) == 0 ) {
324  fprintf( stderr, usage, argv[0], MAX_NTEST );
325  exit(0);
326  }
327  else {
328  fprintf( stderr, "error: unrecognized option %s\n", argv[i] );
329  exit(1);
330  }
331  }
332 
333  // if -N or --range not given, use default range
334  if ( ntest == 0 ) {
335  int n2 = 1024 + 64;
336  for( int i = 0; i < MAX_NTEST; ++i ) {
337  opts->msize[i] = n2;
338  opts->nsize[i] = n2;
339  opts->ksize[i] = n2;
340  n2 += 1024;
341  }
342  ntest = 10;
343  }
344  assert( ntest <= MAX_NTEST );
345  opts->ntest = ntest;
346 
347  // fill in msize[:], nsize[:], ksize[:] if -m, -n, -k were given
348  if ( m >= 0 ) {
349  for( int j = 0; j < MAX_NTEST; ++j ) {
350  opts->msize[j] = m;
351  }
352  }
353  if ( n >= 0 ) {
354  for( int j = 0; j < MAX_NTEST; ++j ) {
355  opts->nsize[j] = n;
356  }
357  }
358  if ( k >= 0 ) {
359  for( int j = 0; j < MAX_NTEST; ++j ) {
360  opts->ksize[j] = k;
361  }
362  }
363 
364  // find max dimensions
365  opts->mmax = 0;
366  opts->nmax = 0;
367  opts->kmax = 0;
368  for( int i = 0; i < ntest; ++i ) {
369  opts->mmax = max( opts->mmax, opts->msize[i] );
370  opts->nmax = max( opts->nmax, opts->nsize[i] );
371  opts->kmax = max( opts->kmax, opts->ksize[i] );
372  }
373 
374  // jobu=O, job
375  if ( opts->jobu == MagmaOverwriteVec && opts->jobvt == MagmaOverwriteVec ) {
376  printf( "jobu and jobvt cannot both be Overwrite.\n" );
377  exit(1);
378  }
379 
380  // set device
381  magma_setdevice( opts->device );
382 }
383 // end parse_opts
void parse_opts(int argc, char **argv, magma_opts *opts)
magma_vec_t jobvt
Definition: testings.h:159
#define MagmaUpperLower
Definition: magma.h:63
magma_int_t ntest
Definition: testings.h:124
#define MagmaLeft
Definition: magma.h:68
magma_int_t magma_num_gpus(void)
Definition: auxiliary.cpp:83
#define MagmaUpper
Definition: magma.h:61
#define MAX_NTEST
Definition: testings.h:119
magma_int_t nstream
Definition: testings.h:136
magma_diag_t diag
Definition: testings.h:157
magma_trans_t transA
Definition: testings.h:154
magma_int_t niter
Definition: testings.h:138
magma_vec_t jobz
Definition: testings.h:160
#define MagmaSomeVec
Definition: magma_types.h:338
int warmup
Definition: testings.h:149
#define MagmaVec
Definition: magma_types.h:335
magma_int_t svd_work
Definition: testings.h:141
magma_vec_t jobvr
Definition: testings.h:161
magma_int_t ngpu
Definition: testings.h:137
magma_int_t nrhs
Definition: testings.h:135
void magma_setdevice(magma_device_t dev)
magma_int_t version
Definition: testings.h:142
int check
Definition: testings.h:147
#define MagmaNoVec
Definition: magma_types.h:334
#define MagmaLower
Definition: magma.h:62
#define MagmaOverwriteVec
Definition: magma_types.h:339
magma_side_t side
Definition: testings.h:156
#define MagmaMaxGPUs
Definition: magma_types.h:255
magma_vec_t jobvl
Definition: testings.h:162
#define MagmaConjTrans
Definition: magma.h:59
double fraction
Definition: testings.h:143
#define MagmaTrans
Definition: magma.h:58
magma_int_t nb
Definition: testings.h:134
magma_int_t nmax
Definition: testings.h:129
#define MagmaNonUnit
Definition: magma.h:65
const char * usage_short
const char * usage
magma_int_t nsize[MAX_NTEST]
Definition: testings.h:126
magma_int_t nthread
Definition: testings.h:139
magma_int_t kmax
Definition: testings.h:130
magma_int_t itype
Definition: testings.h:140
magma_int_t device
Definition: testings.h:133
#define MagmaAllVec
Definition: magma_types.h:337
magma_trans_t transB
Definition: testings.h:155
#define MagmaRight
Definition: magma.h:69
magma_int_t mmax
Definition: testings.h:128
#define MagmaUnit
Definition: magma.h:66
magma_int_t ksize[MAX_NTEST]
Definition: testings.h:127
void magma_assert(bool condition, const char *msg,...)
magma_vec_t jobu
Definition: testings.h:158
#define MagmaNoTrans
Definition: magma.h:57
#define max(a, b)
Definition: common_magma.h:82
magma_uplo_t uplo
Definition: testings.h:153
magma_int_t msize[MAX_NTEST]
Definition: testings.h:125
double tolerance
Definition: testings.h:144
int lapack
Definition: testings.h:148