@@ -36,6 +36,7 @@ namespace chase
3636 timings are stored in a vector of objects derived by the class
3737 template `std::chrono::duration`.
3838 */
39+ template <class T >
3940class ChasePerfData
4041{
4142public:
@@ -114,61 +115,58 @@ class ChasePerfData
114115 std::size_t get_flops (std::size_t N)
115116 {
116117 std::size_t flop_count = 0 ;
118+ int factor = std::pow (4 , int (sizeof (T) / sizeof (Base<T>)) - 1 ) ;
117119 for (auto block : chase_iter_blocksizes)
118120 {
119121 // QR //
120-
121- // https://software.intel.com/en-us/mkl-developer-reference-fortran-2018-beta-geqrf
122- // QR m=N n=block
123- // (2/3)n^2(3m-n) *4
124- flop_count += (8 . / 3 .) *
125- static_cast <double >(block * block * (3 * N - block));
126-
127- // https://software.intel.com/en-us/mkl-developer-reference-c-2018-beta-ungqr
128- // m = N, n=k=block
129- // (8/3)*n^2*(3m - n)
130- flop_count += (8 . / 3 .) * static_cast <double >(block * block *
131- (3 * N - block) * 4 );
132-
133- // RR //
122+ // assume always to use cholqr-2
123+ // syrk
124+ flop_count += 2 . * N * block * block;
125+ // cholesky factorizatin
126+ flop_count += 2 . * block * block * block;
127+ // dtrsm
128+ flop_count += 2 . * N * block * block;
129+
130+ // RR //
134131
135132 // W = H*V
136133 // https://software.intel.com/en-us/mkl-developer-reference-fortran-2018-beta-gemm
137134 // 8MNK + 18MN
138135 // m = N, k = N, n = block
139- flop_count += 8 * N * block * N + 18 * N * block ;
136+ flop_count += 2 * N * block * N;
140137
141138 // A = W' * W
142139 // 8MNK + 18MN
143140 // m = block, k = N, n = block
144- flop_count += 8 * block * block * N + 18 * block * block ;
141+ flop_count += 2 * block * block * N;
145142
146- // reduction to tridiagonal
147- // https://software.intel.com/en-us/mkl-developer-reference-fortran-2018-beta-hetrd
148- // (16/3)n^3
149- flop_count += 16 . / 3 . * static_cast <double >(block * block * block);
143+ // https://en.wikipedia.org/wiki/Divide-and-conquer_eigenvalue_algorithm
144+ // 4M^3
145+ flop_count += 4 * block * block * block;
150146
151147 // W = V*Z
152- // 8MNK + 18MN
153- flop_count += 8 * N * block * block + 18 * N * block;
148+ // 2MNK
149+ flop_count += 2 * N * block * block;
154150
155151 // resid //
156152 // W = H*V
157- flop_count += 8 * N * block * N + 18 * N * block ;
153+ flop_count += 2 * N * block * N;
158154
159155 // V[:,i] - lambda W[:,i]
160156 // 3*block
161157 flop_count += 3 * block * N;
162158
163159 // ||V[:,i]||
164- // 4* N
165- flop_count += 4 * N * block;
160+ // N
161+ flop_count += N * block;
166162 }
167163
168164 // filter
169165 // 8MNK + 18MN
170166 flop_count +=
171- 8 * N * chase_filtered_vecs * N + 16 * N * chase_filtered_vecs;
167+ 2 * N * chase_filtered_vecs * N;
168+
169+ flop_count *= factor;
172170
173171 return flop_count / 1e9 ;
174172 }
@@ -190,8 +188,9 @@ class ChasePerfData
190188 */
191189 std::size_t get_filter_flops (std::size_t N)
192190 {
193- return (8 * N * chase_filtered_vecs * N +
194- 16 * N * chase_filtered_vecs) /
191+ int factor = std::pow (4 , int (sizeof (T) / sizeof (Base<T>)) - 1 ) ;
192+
193+ return 2 * factor * N * chase_filtered_vecs * N /
195194 1e9 ;
196195 }
197196
@@ -261,8 +260,8 @@ class ChasePerfData
261260 {
262261 std::size_t flops = get_flops (N);
263262 std::size_t filter_flops = get_filter_flops (N);
264- std::cout << " | " << static_cast <double >(flops);
265- std::cout << " | " << static_cast <double >(filter_flops);
263+ std::cout << " | " << std::setw ( 11 ) << static_cast <double >(flops);
264+ std::cout << " | " << std::setw ( 15 ) << static_cast <double >(filter_flops);
266265 }
267266
268267 std::cout << " | " << std::setw (5 ) << nprocs;
@@ -338,15 +337,15 @@ class PerformanceDecoratorChase : public chase::Chase<T>
338337 void initVecs (bool random)
339338 {
340339 chase_->initVecs (random);
341- perf_.start_clock (ChasePerfData::TimePtrs::Lanczos);
340+ perf_.start_clock (ChasePerfData<T> ::TimePtrs::Lanczos);
342341 }
343342
344343 void Shift (T c, bool isunshift = false )
345344 {
346345 if (isunshift)
347- perf_.end_clock (ChasePerfData::TimePtrs::Filter);
346+ perf_.end_clock (ChasePerfData<T> ::TimePtrs::Filter);
348347 else
349- perf_.start_clock (ChasePerfData::TimePtrs::Filter);
348+ perf_.start_clock (ChasePerfData<T> ::TimePtrs::Filter);
350349
351350 chase_->Shift (c, isunshift);
352351 }
@@ -358,29 +357,29 @@ class PerformanceDecoratorChase : public chase::Chase<T>
358357
359358 void QR (std::size_t fixednev, Base<T> cond)
360359 {
361- perf_.start_clock (ChasePerfData::TimePtrs::Qr);
360+ perf_.start_clock (ChasePerfData<T> ::TimePtrs::Qr);
362361 chase_->QR (fixednev, cond);
363- perf_.end_clock (ChasePerfData::TimePtrs::Qr);
362+ perf_.end_clock (ChasePerfData<T> ::TimePtrs::Qr);
364363 }
365364
366365 void RR (Base<T>* ritzv, std::size_t block)
367366 {
368- perf_.start_clock (ChasePerfData::TimePtrs::Rr);
367+ perf_.start_clock (ChasePerfData<T> ::TimePtrs::Rr);
369368 chase_->RR (ritzv, block);
370369 perf_.add_iter_blocksize (block);
371- perf_.end_clock (ChasePerfData::TimePtrs::Rr);
370+ perf_.end_clock (ChasePerfData<T> ::TimePtrs::Rr);
372371 }
373372 void Resd (Base<T>* ritzv, Base<T>* resd, std::size_t fixednev)
374373 {
375- perf_.start_clock (ChasePerfData::TimePtrs::Resids_Locking);
374+ perf_.start_clock (ChasePerfData<T> ::TimePtrs::Resids_Locking);
376375 chase_->Resd (ritzv, resd, fixednev);
377376 // We end with ->chase_->Lock()
378377 }
379378 void Lanczos (std::size_t m, Base<T>* upperb)
380379 {
381- perf_.start_clock (ChasePerfData::TimePtrs::Lanczos);
380+ perf_.start_clock (ChasePerfData<T> ::TimePtrs::Lanczos);
382381 chase_->Lanczos (m, upperb);
383- perf_.end_clock (ChasePerfData::TimePtrs::Lanczos);
382+ perf_.end_clock (ChasePerfData<T> ::TimePtrs::Lanczos);
384383 }
385384 void Lanczos (std::size_t M, std::size_t idx, Base<T>* upperb,
386385 Base<T>* ritzv, Base<T>* Tau, Base<T>* ritzV)
@@ -390,21 +389,21 @@ class PerformanceDecoratorChase : public chase::Chase<T>
390389 void LanczosDos (std::size_t idx, std::size_t m, T* ritzVc)
391390 {
392391 chase_->LanczosDos (idx, m, ritzVc);
393- perf_.end_clock (ChasePerfData::TimePtrs::Lanczos);
392+ perf_.end_clock (ChasePerfData<T> ::TimePtrs::Lanczos);
394393 }
395394
396395 void Swap (std::size_t i, std::size_t j) { chase_->Swap (i, j); }
397396 void Lock (std::size_t new_converged)
398397 {
399398 chase_->Lock (new_converged);
400- perf_.end_clock (ChasePerfData::TimePtrs::Resids_Locking);
399+ perf_.end_clock (ChasePerfData<T> ::TimePtrs::Resids_Locking);
401400 perf_.add_iter_count (1 );
402401 }
403402 void Start ()
404403 {
405404 chase_->Start ();
406405 perf_.Reset ();
407- perf_.start_clock (ChasePerfData::TimePtrs::All);
406+ perf_.start_clock (ChasePerfData<T> ::TimePtrs::All);
408407 perf_.set_nprocs (chase_->get_nprocs ());
409408 }
410409
@@ -413,7 +412,7 @@ class PerformanceDecoratorChase : public chase::Chase<T>
413412 void End ()
414413 {
415414 chase_->End ();
416- perf_.end_clock (ChasePerfData::TimePtrs::All);
415+ perf_.end_clock (ChasePerfData<T> ::TimePtrs::All);
417416 }
418417
419418 std::size_t GetN () const { return chase_->GetN (); }
@@ -422,15 +421,15 @@ class PerformanceDecoratorChase : public chase::Chase<T>
422421 Base<T>* GetRitzv () { return chase_->GetRitzv (); }
423422 Base<T>* GetResid () { return chase_->GetResid (); }
424423 ChaseConfig<T>& GetConfig () { return chase_->GetConfig (); }
425- ChasePerfData& GetPerfData () { return perf_; }
424+ ChasePerfData<T> & GetPerfData () { return perf_; }
426425
427426#ifdef CHASE_OUTPUT
428427 void Output (std::string str) { chase_->Output (str); }
429428#endif
430429
431430private:
432431 Chase<T>* chase_;
433- ChasePerfData perf_;
432+ ChasePerfData<T> perf_;
434433};
435434
436435} // namespace chase
0 commit comments