Triumvirate C++ API 0.5.0.post1.dev301+g026f21751
Three-point clustering measurements in large-scale structure analyses.
Loading...
Searching...
No Matches
monitor.cpp
Go to the documentation of this file.
1// Triumvirate: Three-Point Clustering Measurements in LSS
2//
3// Copyright (C) 2023 Mike S Wang & Naonori S Sugiyama [GPL-3.0-or-later]
4//
5// This file is part of the Triumvirate program. See the COPYRIGHT
6// and LICENCE files at the top-level directory of this distribution
7// for details of copyright and licensing.
8//
9// This program is free software: you can redistribute it and/or modify it
10// under the terms of the GNU General Public License as published by
11// the Free Software Foundation, either version 3 of the License, or
12// (at your option) any later version.
13//
14// This program is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17// See the GNU General Public License for more details.
18//
19// You should have received a copy of the GNU General Public License
20// along with this program. If not, see <https://www.gnu.org/licenses/>.
21
28
29#include "monitor.hpp"
30
31namespace trv {
32namespace sys {
33
34// ***********************************************************************
35// Program helpers
36// ***********************************************************************
37
38bool has_extension(const std::string& fname, const std::string& fext) {
39 if (fname.length() >= fext.length()) {
40 return (fname.rfind(fext) == (fname.length() - fext.length()));
41 }
42 return false;
43}
44
45std::string join_strings(
46 const std::vector<std::string>& strings,
47 const std::string& delimiter
48) {
49 std::ostringstream oss;
50 for (auto it = strings.begin(); it != strings.end(); ++it) {
51 oss << *it;
52 if (std::next(it) != strings.end()) {
53 oss << delimiter;
54 }
55 }
56 return oss.str();
57}
58
59std::vector<std::string> split_string(
60 const std::string& str,
61 const std::string& delimiter
62) {
63 if (str.empty()) {
64 return {};
65 }
66 if (delimiter.empty()) {
67 return {str};
68 }
69
70 std::string fullstr = {str};
71 std::string substr;
72 std::size_t dlpos = 0;
73
74 std::vector<std::string> strings;
75 while ((dlpos = fullstr.find(delimiter)) != std::string::npos) {
76 substr = fullstr.substr(0, dlpos);
77 fullstr.erase(0, dlpos + delimiter.length());
78 strings.push_back(substr);
79 }
80 if (!fullstr.empty()) {
81 strings.push_back(fullstr);
82 }
83
84 return strings;
85}
86
87
88// ***********************************************************************
89// Program tracking
90// ***********************************************************************
91
92int currTask = 0;
93
94double gbytesMem = 0.;
95double gbytesMaxMem = 0.;
96
97double gbytesMemGPU = 0.;
98double gbytesMaxMemGPU = 0.;
99
102float count_grid = 0.;
105float max_count_grid = 0.;
106
107int count_fft = 0;
109
112
113auto clockStart = std::chrono::steady_clock::now();
114
118
119#if defined(TRV_USE_HIP)
120double worksize_in_gb(
121 hipfftHandle plan,
122 hipfftType ffttype,
123 int nx, int ny, int nz,
124 std::vector<int> gpus
125) {
126 std::vector<std::size_t> worksizes(gpus.size());
127 HIPFFT_EXEC(hipfftGetSize3d(plan, nx, ny, nz, ffttype, worksizes.data()));
128
129 std::size_t totsize = 0;
130 for (std::size_t id = 0; id < gpus.size(); ++id) {
131 totsize += worksizes[id];
132 }
133
134 const double BYTES_PER_GBYTES = 1073741824.; // 1024³ bytes per gibibyte
135 double worksize_gb = double(totsize) / BYTES_PER_GBYTES;
136
137 return worksize_gb;
138}
139#elif defined(TRV_USE_CUDA) // !TRV_USE_HIP && TRV_USE_CUDA
140double worksize_in_gb(
141 cufftHandle plan,
142 cufftType ffttype,
143 int nx, int ny, int nz,
144 std::size_t* worksizes,
145 std::vector<int> gpus
146) {
147 std::size_t totsize = 0;
148 if (gpus.size() == 1) {
149 CUFFT_EXEC(cufftGetSize3d(plan, nx, ny, nz, ffttype, &totsize));
150 } else {
151 CUFFT_EXEC(cufftGetSize3d(plan, nx, ny, nz, ffttype, worksizes));
152
153 for (std::size_t id = 0; id < gpus.size(); ++id) {
154 totsize += worksizes[id];
155 }
156 }
157
158 const double BYTES_PER_GBYTES = 1073741824.; // 1024³ bytes per gibibyte
159 double worksize_gb = double(totsize) / BYTES_PER_GBYTES;
160
161 return worksize_gb;
162}
163#endif // TRV_USE_HIP
164
176
188
189std::string show_current_datetime(bool utc) {
190 // Get current time.
191 auto now = std::chrono::system_clock::now();
192 auto timenow = std::chrono::system_clock::to_time_t(now);
193
194 // Format timestamp.
195 char buffer[21];
196 if (utc) {
197 std::strftime(
198 buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%SZ", std::gmtime(&timenow)
199 );
200 } else {
201 std::strftime(
202 buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", std::localtime(&timenow)
203 );
204 };
205
206 // Print timestamp to string.
207 std::string timestamp = std::string(buffer);
208
209 return timestamp;
210}
211
212std::string show_elapsed_time(double elapsed_time_in_seconds) {
213 // Round time to an integer number of seconds.
214 int time = int(elapsed_time_in_seconds);
215
216 // Calculate the hour, minute and second and convert to strings.
217 std::string h = std::to_string(time / 3600);
218 std::string m = std::to_string((time % 3600) / 60);
219 std::string s = std::to_string(time % 60);
220
221 // Format the strings.
222 std::string hh;
223 if (h.length() < 2) {
224 hh = std::string(2 - h.length(), '0') + h;
225 } else {
226 hh = h;
227 }
228
229 std::string mm = std::string(2 - m.length(), '0') + m;
230 std::string ss = std::string(2 - s.length(), '0') + s;
231
232 // Form the elapsed time string.
233 std::string elapsed_time = hh + ":" + mm + ":" + ss;
234
235 return elapsed_time;
236}
237
238std::string show_timestamp() {
239 // Calculate the elapsed time in seconds.
240 double elapsed_time = double(
241 std::chrono::duration_cast<std::chrono::seconds>(
242 std::chrono::steady_clock::now() - clockStart
243 ).count()
244 );
245
246 // Format the timestamp.
247 char timestamp_[128];
248 std::snprintf(
249 timestamp_, sizeof(timestamp_), "%s (+%s)",
250 show_current_datetime().c_str(), show_elapsed_time(elapsed_time).c_str()
251 );
252
253 std::string timestamp(timestamp_);
254
255 return timestamp;
256}
257
259 int num_gpus = 0;
260#if defined(TRV_USE_HIP)
261 HIP_EXEC(hipGetDeviceCount(&num_gpus));
262#elif defined(TRV_USE_CUDA) // !TRV_USE_HIP && TRV_USE_CUDA
263 CUDA_EXEC(cudaGetDeviceCount(&num_gpus));
264#endif // TRV_USE_HIP
265
266 if (sys) {
267 return num_gpus;
268 }
269
270 int max_gpus = num_gpus;
271
272 char* env_gpu_maxnum = std::getenv("TRV_GPU_MAXNUM");
273 if (env_gpu_maxnum != nullptr) {
274 std::string gpu_maxnum(env_gpu_maxnum);
275 std::regex re_int("^[0-9]+$");
276 if (std::regex_match(gpu_maxnum, re_int)) {
277 max_gpus = std::stoi(gpu_maxnum);
278 }
279 }
280
281 return num_gpus > max_gpus ? max_gpus : num_gpus;
282}
283
284std::vector<int> get_gpu_ids() {
285 std::vector<int> gpu_ids;
286 for (int i = 0; i < get_gpu_count(); ++i) {
287 gpu_ids.push_back(i);
288 }
289 return gpu_ids;
290}
291
293 bool sys = true;
294 return (get_gpu_count(sys) > 0);
295}
296
298 if (!(get_gpu_count() > 0)) {
299 return false;
300 }
301
302 // Check for environmental variable override.
303 char* env_gpu_mode = std::getenv("TRV_GPU_MODE");
304 if (env_gpu_mode != nullptr) {
305 std::string gpu_mode(env_gpu_mode);
306 // If ``TRV_GPU_MODE`` is set to "false", "no", "off" or "0",
307 // then GPU mode is disabled.
308 if (
309 gpu_mode == "false"
310 || gpu_mode == "no"
311 || gpu_mode == "off"
312 || gpu_mode == "0"
313 ) {
314 return false;
315 }
316 }
317
318 // By default, GPU mode is enabled.
319 return true;
320}
321
323 return (get_gpu_count() == 1);
324}
325
326void exit_fatal(const std::string& msg) {
327 if (is_colourable()) {
328 std::cout << "\n\033[1;37;41mFATAL\033[0m: " << msg << std::endl;
329 } else {
330 std::cout << "\nFATAL: " << msg << std::endl;
331 }
332
333 std::exit(EXIT_FAILURE);
334}
335
339
340Logger::Logger(int level) {
341 Logger::reset_level(level);
342}
343
345 this->level_limit = level;
346}
347
348void Logger::reset_level(int level) {
349 this->level_limit = level;
350}
351
352void Logger::emit(
353 std::string log_type, const char* fmt_string, std::va_list args
354) {
355 char log_mesg_buf[4096];
356 std::vsnprintf(log_mesg_buf, sizeof(log_mesg_buf), fmt_string, args);
357
358 if (log_type.empty()) {
359 std::printf(
360 "[%s%s] %s\n",
361 trv::sys::show_timestamp().c_str(), SHOW_CPPSTATE,
362 log_mesg_buf
363 );
364 } else {
365 std::printf(
366 "[%s %s%s] %s\n",
367 trv::sys::show_timestamp().c_str(), log_type.c_str(), SHOW_CPPSTATE,
368 log_mesg_buf
369 );
370 }
371}
372
373void Logger::log(LogLevel entry_level, const char* fmt_string, ...) {
374 Logger::log(static_cast<int>(entry_level), fmt_string);
375}
376
377void Logger::log(int level_entry, const char* fmt_string, ...) {
378 if (level_entry >= this->level_limit) {
379 // CAVEAT: See @ref trv::sys::LogLevel.
380 level_entry /= 10;
381
382 std::string log_type;
383
384 if (is_colourable()) {
385 // Use colours in interactive mode.
386 switch (level_entry) {
387 case LogLevel::NSET:
388 log_type = "";
389 break;
390 case LogLevel::DBUG:
391 log_type = "\033[0;36mDBUG\033[0m"; // cyan
392 break;
393 case LogLevel::STAT:
394 log_type = "\033[0;34mSTAT\033[0m"; // blue
395 break;
396 case LogLevel::INFO:
397 log_type = "\033[0;32mINFO\033[0m"; // green
398 break;
399 case LogLevel::WARN:
400 log_type = "\033[0;33mWARN\033[0m"; // yellow
401 break;
402 case LogLevel::ERRO:
403 log_type = "\033[0;31mERRO\033[0m"; // red
404 break;
405 default:
406 throw InvalidParameterError("Unsupported log level.");
407 }
408 } else {
409 // No colours otherwise.
410 switch (level_entry) {
411 case LogLevel::NSET:
412 log_type = "";
413 break;
414 case LogLevel::DBUG:
415 log_type = "DBUG";
416 break;
417 case LogLevel::STAT:
418 log_type = "STAT";
419 break;
420 case LogLevel::INFO:
421 log_type = "INFO";
422 break;
423 case LogLevel::WARN:
424 log_type = "WARN";
425 break;
426 case LogLevel::ERRO:
427 log_type = "ERRO";
428 break;
429 default:
430 throw InvalidParameterError("Unsupported log level.");
431 }
432 }
433
434 std::va_list args;
435 va_start(args, fmt_string);
436 Logger::emit(log_type, fmt_string, args);
437 va_end(args);
438 }
439}
440
441void Logger::debug(const char* fmt_string, ...) {
442 if (this->level_limit <= LogLevel::DBUG) {
443 std::va_list args;
444 va_start(args, fmt_string);
445 if (is_colourable()) {
446 Logger::emit("\033[0;36mDBUG\033[0m", fmt_string, args);
447 } else {
448 Logger::emit("DBUG", fmt_string, args);
449 }
450 va_end(args);
451 }
452}
453
454void Logger::stat(const char* fmt_string, ...) {
455 if (this->level_limit <= LogLevel::STAT) {
456 std::va_list args;
457 va_start(args, fmt_string);
458 if (is_colourable()) {
459 Logger::emit("\033[0;34mSTAT\033[0m", fmt_string, args);
460 } else {
461 Logger::emit("STAT", fmt_string, args);
462 }
463 va_end(args);
464 }
465}
466
467void Logger::info(const char* fmt_string, ...) {
468 if (this->level_limit <= LogLevel::INFO) {
469 std::va_list args;
470 va_start(args, fmt_string);
471 if (is_colourable()) {
472 Logger::emit("\033[0;32mINFO\033[0m", fmt_string, args);
473 } else {
474 Logger::emit("INFO", fmt_string, args);
475 }
476 va_end(args);
477 }
478}
479
480void Logger::warn(const char* fmt_string, ...) {
481 if (this->level_limit <= LogLevel::WARN) {
482 std::va_list args;
483 va_start(args, fmt_string);
484 if (is_colourable()) {
485 Logger::emit("\033[0;33mWARN\033[0m", fmt_string, args);
486 } else {
487 Logger::emit("WARN", fmt_string, args);
488 }
489 va_end(args);
490 }
491}
492
493void Logger::error(const char* fmt_string, ...) {
494 if (this->level_limit <= LogLevel::ERRO) {
495 std::va_list args;
496 va_start(args, fmt_string);
497 if (is_colourable()) {
498 Logger::emit("\033[1;31mERRO\033[0m", fmt_string, args);
499 } else {
500 Logger::emit("ERRO", fmt_string, args);
501 }
502 va_end(args);
503 }
504}
505
507 char* ev_term = std::getenv("TERM");
508 char* ev_interactive = std::getenv("TRV_INTERACTIVE");
509 if (ev_term == nullptr || ev_interactive == nullptr) {
510 return false;
511 }
512 if (std::strstr(ev_term, "color") == nullptr) {
513 return false;
514 }
515 std::string str_interactive = std::string(ev_interactive);
516 return (
517 str_interactive == "true" ||
518 str_interactive == "yes" ||
519 str_interactive == "1" ||
520 str_interactive == "on"
521 );
522}
523
525 this->name = name;
526
527 if (task_count < 1) {
529 "Progress bar must count at least one task in total."
530 );
531 }
532 this->task_count = task_count;
533
534 this->set_default_pcpt_nodes();
535}
536
538 if (width < 1) {
539 throw InvalidParameterError("Progress bar width must be at least 1.");
540 }
541 this->bar_width = width;
542}
543
544void ProgressBar::set_nodes(std::vector<float> nodes) {
545 if (nodes.size() < 1) {
547 "Progress bar nodes must have at least one element."
548 );
549 }
550 this->nodes = nodes;
551}
552
556 "Progress bar task index must be non-negative and "
557 "within the total task count."
558 );
559 }
560 this->task_idx = task_idx;
561
562 float progress = float(this->task_idx) / float(this->task_count);
563 this->set_progress(progress);
564}
565
569 "Progress bar progress must be within the range [0, 1]."
570 );
571 }
572 this->progress = progress;
573
574 this->next_node_idx = 0;
575 while (this->progress > this->nodes[this->next_node_idx]) {
576 this->next_node_idx += 1;
577 }
578}
579
580void ProgressBar::update(int task_idx_now) {
581 this->task_idx = task_idx_now;
582 float progress_now = float(this->task_idx) / float(this->task_count);
583 this->update(progress_now);
584}
585
586void ProgressBar::update(float progress_now) {
587 this->progress = progress_now;
588
589 if (this->progress <= 1.) {
590 if (this->progress >= this->nodes[this->next_node_idx]) {
591 int pos = this->bar_width * this->progress;
592
593 // Print the timestamped status.
594 std::cout << "[";
595 std::cout << trv::sys::show_timestamp();
596 if (is_colourable()) {
597 std::cout << " \033[0;34mSTAT\033[0m";
598 } else {
599 std::cout << " STAT";
600 }
601 std::cout << "] ";
602
603 // Print the progress bar.
604 std::cout << "[";
605 if (is_colourable()) {
606 std::cout << "\033[0;34m";
607 }
608 for (int ichar = 0; ichar < this->bar_width; ichar++) {
609 if (ichar < pos) {
610 std::cout << "=";
611 } else
612 if (ichar == pos) {
613 std::cout << ">";
614 } else {
615 std::cout << " ";
616 }
617 }
618 if (is_colourable()) {
619 std::cout << "\033[0m";
620 }
621 std::cout << "] " << int(progress * 100.) << "%";
622
623 // Print the progress bar name.
624 if (this->name != "") {
625 std::cout << " < " << this->name;
626 }
627
628 // Flush the progress-bar line.
629 std::cout << "\r";
630 std::cout.flush();
631
632 this->next_node_idx += 1;
633 }
634 } else {
635 throw InvalidDataError(
636 "Progress bar has already completed: progress %f > 1.", this->progress
637 );
638 }
639 if (this->progress == 1.) {std::cout << std::endl;}
640}
641
642void ProgressBar::set_default_pcpt_nodes() {
643 this->nodes.resize(101, 0.);
644 for (int pcpt = 0; pcpt <= 100; ++pcpt) {
645 this->nodes.push_back(float(pcpt) / 100.);
646 }
647}
648
649std::vector<float> set_nodes_by_str(std::string interval_str) {
650 try {
651 std::stof(interval_str);
652 } catch (const std::invalid_argument& e) {
654 "Progress bar interval must be a float number."
655 );
656 }
657
658 float interval = std::stof(interval_str);
659 if (!(0. < interval && interval < 100.)) {
661 "Progress bar interval must be in (0, 100) interval."
662 );
663 }
664 interval /= 100.;
665
666 std::vector<float> nodes = {interval};
667 while (nodes.back() < 1.) {
668 if (nodes.back() + interval < 1.) {
669 nodes.push_back(nodes.back() + interval);
670 } else {
671 nodes.push_back(1.);
672 }
673 }
674
675 return nodes;
676}
677
678
679// ***********************************************************************
680// Program exceptions
681// ***********************************************************************
682
683UnimplementedError::UnimplementedError(const char* fmt_string, ...):
684 std::logic_error(
685 "Unimplemented error." // mandatory default error message
686 ) {
687 std::va_list args;
688
689 char err_mesg_buf[4096];
690 va_start(args, fmt_string);
691 std::vsnprintf(err_mesg_buf, sizeof(err_mesg_buf), fmt_string, args);
692 va_end(args);
693
694 this->err_mesg = std::string(err_mesg_buf);
695}
696
697const char* UnimplementedError::what() const noexcept {
698 return this->err_mesg.c_str();
699}
700
701IOError::IOError(const char* fmt_string, ...) : std::runtime_error(
702 "I/O error." // mandatory default error message
703) {
704 std::va_list args;
705
706 char err_mesg_buf[4096];
707 va_start(args, fmt_string);
708 std::vsnprintf(err_mesg_buf, sizeof(err_mesg_buf), fmt_string, args);
709 va_end(args);
710
711 this->err_mesg = std::string(err_mesg_buf);
712}
713
714const char* IOError::what() const noexcept {return this->err_mesg.c_str();}
715
717std::invalid_argument(
718 "Invalid parameter error." // mandatory default error message
719) {
720 std::va_list args;
721
722 char err_mesg_buf[4096];
723 va_start(args, fmt_string);
724 std::vsnprintf(err_mesg_buf, sizeof(err_mesg_buf), fmt_string, args);
725 va_end(args);
726
727 this->err_mesg = std::string(err_mesg_buf);
728}
729
730const char* InvalidParameterError::what() const noexcept {
731 return this->err_mesg.c_str();
732}
733
734InvalidDataError::InvalidDataError(const char* fmt_string, ...):
735std::runtime_error(
736 "Invalid data error." // mandatory default error message
737) {
738 std::va_list args;
739
740 char err_mesg_buf[4096];
741 va_start(args, fmt_string);
742 std::vsnprintf(err_mesg_buf, sizeof(err_mesg_buf), fmt_string, args);
743 va_end(args);
744
745 this->err_mesg = std::string(err_mesg_buf);
746}
747
748const char* InvalidDataError::what() const noexcept {
749 return this->err_mesg.c_str();
750}
751
752
753// ***********************************************************************
754// Program notices
755// ***********************************************************************
756
757std::string get_build_datetime() {
758 // Define helper functions.
759 auto convert_month_from_name_to_num = [](const std::string& month) -> int {
760 if (month == "Jan") return 1;
761 if (month == "Feb") return 2;
762 if (month == "Mar") return 3;
763 if (month == "Apr") return 4;
764 if (month == "May") return 5;
765 if (month == "Jun") return 6;
766 if (month == "Jul") return 7;
767 if (month == "Aug") return 8;
768 if (month == "Sep") return 9;
769 if (month == "Oct") return 10;
770 if (month == "Nov") return 11;
771 if (month == "Dec") return 12;
772 return 0;
773 };
774
775 // Parse macros.
776 std::string month_str = std::string(__DATE__).substr(0, 3);
777 int month = convert_month_from_name_to_num(month_str);
778
779 int day = std::stoi(std::string(__DATE__).substr(4, 2));
780 int year = std::stoi(std::string(__DATE__).substr(7, 4));
781
782 int hour = std::stoi(std::string(__TIME__).substr(0, 2));
783 int minute = std::stoi(std::string(__TIME__).substr(3, 2));
784 int second = std::stoi(std::string(__TIME__).substr(6, 2));
785
786 int hour_tzoffset = 0;
787 int minute_tzoffset = 0;
788 int status_tzoffset = 0;
789 try {
790 if (
791 std::strlen(__TZOFFSET__) == 5
792 && (__TZOFFSET__[0] == '+' || __TZOFFSET__[0] == '-')
793 ) {
794 int _tzos_sign = (__TZOFFSET__[0] == '-') ? -1 : 1;
795 int _hr_tzoffset = std::stoi(std::string(__TZOFFSET__).substr(1, 2));
796 int _min_tzoffset = std::stoi(std::string(__TZOFFSET__).substr(3, 2));
797 if (
798 0 <= hour_tzoffset && hour_tzoffset < 24
799 && 0 <= minute_tzoffset && minute_tzoffset < 60
800 ) {
801 hour_tzoffset = _tzos_sign * _hr_tzoffset;
802 minute_tzoffset = _tzos_sign * _min_tzoffset;
803 } else {
804 status_tzoffset = 1;
805 }
806 } else {
807 status_tzoffset = 1;
808 }
809 } catch (const std::invalid_argument& e) {
810 status_tzoffset = 1;
811 } catch (const std::out_of_range& e) {
812 status_tzoffset = 1;
813 }
814
815 if (status_tzoffset == 0) {
816 hour -= hour_tzoffset;
817 minute -= minute_tzoffset;
818 if (minute < 0) {
819 minute += 60;
820 hour -= 1;
821 } else
822 if (minute >= 60) {
823 minute -= 60;
824 hour += 1;
825 }
826 if (hour < 0) {
827 hour += 24;
828 day -= 1;
829 } else
830 if (hour >= 24) {
831 hour -= 24;
832 day += 1;
833 }
834 }
835
836 // Convert to timestamp.
837 std::tm bdtm = {};
838 bdtm.tm_year = year - 1900;
839 bdtm.tm_mon = month - 1;
840 bdtm.tm_mday = day;
841 bdtm.tm_hour = hour;
842 bdtm.tm_min = minute;
843 bdtm.tm_sec = second;
844
845 // Format string.
846 char bdt[21];
847 if (status_tzoffset == 0) {
848 std::strftime(bdt, sizeof(bdt), "%Y-%m-%dT%H:%M:%SZ", &bdtm);
849 } else {
850 std::strftime(bdt, sizeof(bdt), "%Y-%m-%dT%H:%M:%S", &bdtm);
851 }
852
853 return std::string(bdt);
854}
855
857 std::printf(
858 "Triumvirate: Three-Point Clustering Measurements in LSS\n"
859 "\n"
860 "\033[1mUsage:\033[0m triumvirate [-h] [-V] <parameter-ini-file>\n"
861 "\n"
862 "\033[1mPositional arguments:\033[0m\n"
863 " <parameter-ini-file> path to the parameter INI file\n"
864 "\n"
865 "\033[1mOptions:\033[0m\n"
866 " -h, --help show help message and exit\n"
867 " -V, --version show version and licensing information and exit\n"
868 );
869}
870
872 std::printf("\n");
873 std::printf(
874 " //\\ ___ __ __ ___ ___ \n"
875 " // \\ | |__) | | | |\\/| \\ / | |__) /\\ | |__ \n"
876 " // \\ | | \\ | \\__/ | | \\/ | | \\ /~~\\ | |___ \n"
877 " // \\ \n"
878 " //________\\ "
879 );
880 if (is_colourable()) {
881 std::printf(
882 "• \033[1mThree-Point Clustering Measurements in LSS\033[0m • \n"
883 );
884 } else {
885 std::printf("• Three-Point Clustering Measurements in LSS • \n");
886 }
887 std::printf("\n");
888}
889
890void display_prog_licence(bool brief) {
891 std::printf("Copyright (C) 2023 Mike S Wang & Naonori S Sugiyama\n");
892 std::printf("\n");
893 if (brief) {
894 if (is_colourable()) {
895 std::printf("\033[1mLICENCE NOTICE\033[0m >\n\n");
896 } else {
897 std::printf("LICENCE NOTICE >\n\n");
898 }
899 std::printf(
900 "This program comes with ABSOLUTELY NO WARRANTY. This is \n"
901 "free software, and you are welcome to redistribute it under \n"
902 "certain conditions; run `triumvirate --version` for details.\n"
903 );
904 } else {
905 if (is_colourable()) {
906 std::printf("\033[1mLICENCE\033[0m >\n\n");
907 std::printf("\033[2mGPL-3.0-or-later\033[0m\n\n");
908 } else {
909 std::printf("LICENCE >\n\n");
910 std::printf("GPL-3.0-or-later\n\n");
911 }
912 std::printf(
913 "This program is free software: you can redistribute it and/or modify \n"
914 "it under the terms of the GNU General Public License as published by \n"
915 "the Free Software Foundation, either version 3 of the License, or \n"
916 "(at your option) any later version. \n"
917 " \n"
918 "This program is distributed in the hope that it will be useful, but \n"
919 "WITHOUT ANY WARRANTY; without even the implied warranty of \n"
920 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU \n"
921 "General Public License for more details. \n"
922 " \n"
923 "You should have received a copy of the GNU General Public License \n"
924 "along with this program. If not, see <https://www.gnu.org/licenses/>.\n"
925 );
926 }
927 std::printf("\n");
928}
929
930void display_prog_info(bool runtime) {
931 if (runtime) {
932 if (is_colourable()) {
933 std::printf("\033[1mRUNTIME INFORMATION\033[0m >\n\n");
934 } else {
935 std::printf("RUNTIME INFORMATION >\n\n");
936 }
937 } else {
938 if (is_colourable()) {
939 std::printf("\033[1mPROGRAM INFORMATION\033[0m >\n\n");
940 } else {
941 std::printf("PROGRAM INFORMATION >\n\n");
942 }
943 }
944
945 std::printf("Triumvirate version: %s\n", __TRV_VERSION__);
946
947 std::printf("GSL version: %s\n", GSL_VERSION);
948
949#if defined(TRV_USE_HIP)
950 std::string hipfft_version =
951 std::to_string(HIPFFT_MAJOR_VERSION) + "." +
952 std::to_string(HIPFFT_MINOR_VERSION) + "." +
953 std::to_string(HIPFFT_PATCH_LEVEL);
954 std::printf("hipFFT version: %s\n", hipfft_version.c_str());
955#elif defined(TRV_USE_CUDA) // !TRV_USE_HIP && TRV_USE_CUDA
956 std::string cufft_version =
957 std::to_string(CUFFT_VER_MAJOR) + "." +
958 std::to_string(CUFFT_VER_MINOR) + "." +
959 std::to_string(CUFFT_VER_PATCH) + "." +
960 std::to_string(CUFFT_VER_BUILD);
961 std::printf("cuFFT version: %s\n", cufft_version.c_str());
962#else // !TRV_USE_HIP && !TRV_USE_CUDA
963 std::printf("FFTW version: %s\n", fftw_version);
964#endif // TRV_USE_HIP
965
966 std::printf("OpenMP version: %s\n", _OMP_VERSION.c_str());
967
968#ifdef TRV_USE_H5
969 unsigned hdf5_major, hdf5_minor, hdf5_release;
970 H5get_libversion(&hdf5_major, &hdf5_minor, &hdf5_release);
971 std::printf(
972 "HDF5 version: %d.%d.%d\n", hdf5_major, hdf5_minor, hdf5_release
973 );
974#endif // TRV_USE_H5
975
976 std::printf("Build timestamp: %s\n", get_build_datetime().c_str());
977
978 if (runtime) {
979 std::printf("CPU thread count: %d\n", _OMP_NTHREADS);
980
981 std::string gpu_mode = " (unavailable)";
982 if (is_gpu_available()) {
983 gpu_mode = is_gpu_enabled() ? "" : " (disabled)";
984 }
985 std::printf(
986 "GPU device count: %d%s\n",
987 trv::sys::get_gpu_count(), gpu_mode.c_str()
988 );
989 }
990
991 std::printf("\n");
992}
993
994void display_prog_logbars(int endpoint) {
995 if (endpoint == 0) {
996 // std::printf("%s\n", std::string(80, '>').c_str());
997 if (is_colourable()) {
998 std::printf("\033[1mPROGRAM LOG\033[0m >\n\n");
999 } else {
1000 std::printf("PROGRAM LOG >\n\n");
1001 }
1002 } else
1003 if (endpoint == 1) {
1004 // std::printf("%s\n", std::string(80, '<').c_str());
1005 } else {
1007 "Invalid endpoint for log bars: %d.", endpoint
1008 );
1009 }
1010}
1011
1012void expand_envar_in_path(std::string& path_str) {
1013 std::regex envar_pattern(R"(\$\{([^}]+)\})");
1014 std::smatch matches;
1015
1016 auto search_start = path_str.cbegin();
1017 while (
1018 std::regex_search(search_start, path_str.cend(), matches, envar_pattern)
1019 ) {
1020 std::string var_name = matches[1].str();
1021 const char* var_value = std::getenv(var_name.c_str());
1022
1023 if (var_value != nullptr) {
1024 // Calculate offset before replacing.
1025 auto start_pos = matches.prefix().second - path_str.cbegin();
1026 path_str.replace(
1027 matches.prefix().second, matches.suffix().first, var_value
1028 );
1029
1030 // Update `search_start` using offset.
1031 search_start = path_str.cbegin() + start_pos + std::strlen(var_value);
1032 } else {
1033 // If the variable isn't found, skip past this match.
1034 search_start = matches.suffix().first;
1035 }
1036 }
1037}
1038
1039} // namespace trv::sys
1040} // namespace trv
IOError(const char *fmt_string,...)
Construct an trv::sys::IOError exception.
Definition monitor.cpp:701
std::string err_mesg
error message
Definition monitor.hpp:709
virtual const char * what() const noexcept
Exception string representation.
Definition monitor.cpp:714
Exception raised when the data to be operated on are invalid.
Definition monitor.hpp:755
std::string err_mesg
error message
Definition monitor.hpp:757
virtual const char * what() const noexcept
Exception string representation.
Definition monitor.cpp:748
InvalidDataError(const char *fmt_string,...)
Construct an trv::sys::InvalidDataError exception.
Definition monitor.cpp:734
Exception raised when parameters are invalid.
Definition monitor.hpp:731
InvalidParameterError(const char *fmt_string,...)
Construct an trv::sys::InvalidParameterError exception.
Definition monitor.cpp:716
virtual const char * what() const noexcept
Exception string representation.
Definition monitor.cpp:730
std::string err_mesg
error message
Definition monitor.hpp:733
Logger with logging level differentiation.
Definition monitor.hpp:449
Logger(LogLevel level)
Construct the logger with the specified threshold level.
Definition monitor.cpp:336
void info(const char *fmt_string,...)
Emit a information-level message.
Definition monitor.cpp:467
void debug(const char *fmt_string,...)
Emit a debugging-level message.
Definition monitor.cpp:441
void error(const char *fmt_string,...)
Emit a warning-level message.
Definition monitor.cpp:493
void warn(const char *fmt_string,...)
Emit a warning-level message.
Definition monitor.cpp:480
void stat(const char *fmt_string,...)
Emit a status-level message.
Definition monitor.cpp:454
int level_limit
logger threshold level
Definition monitor.hpp:451
void log(LogLevel level_entry, const char *fmt_string,...)
Log a message at the specified level.
Definition monitor.cpp:373
void reset_level(LogLevel level)
Reset the logger threshold level.
Definition monitor.cpp:344
float progress
progress value in [0, 1] interval
Definition monitor.hpp:588
int task_count
total task count
Definition monitor.hpp:586
ProgressBar(int task_count, std::string name="")
Construct a progress bar.
Definition monitor.cpp:524
void set_task_idx(int task_idx)
Set current (or initial) task index.
Definition monitor.cpp:553
void set_nodes(std::vector< float > nodes)
Set progress bar width.
Definition monitor.cpp:544
int task_idx
task index
Definition monitor.hpp:587
void set_bar_width(int bar_width)
Set progress bar width.
Definition monitor.cpp:537
std::string name
progress bar name
Definition monitor.hpp:585
void update(int task_idx_now)
Update the progress bar.
Definition monitor.cpp:580
void set_progress(float progress)
Set current (or initial) progress value.
Definition monitor.cpp:566
virtual const char * what() const noexcept
Exception string representation.
Definition monitor.cpp:697
std::string err_mesg
error message
Definition monitor.hpp:685
UnimplementedError(const char *fmt_string,...)
Construct an trv::sys::UnimplementedError exception.
Definition monitor.cpp:683
Provide tracking of program resources and exceptions.
double gbytesMem
current memory usage in gibibytes
Definition monitor.cpp:94
bool has_extension(const std::string &fname, const std::string &fext)
Check if a file has a given extension.
Definition monitor.cpp:38
void display_help()
Display help message in stdout.
Definition monitor.cpp:856
void update_maxmem(bool gpu=false)
Update the maximum memory usage estimate.
Definition monitor.cpp:165
std::string show_timestamp()
Return the timestamp string including the elapsed time.
Definition monitor.cpp:238
auto clockStart
program starting time
Definition monitor.cpp:113
void expand_envar_in_path(std::string &path_str)
Expand environment variables in a path string.
Definition monitor.cpp:1012
std::vector< int > get_gpu_ids()
Get the indices of GPUs available for use.
Definition monitor.cpp:284
bool fftw_wisdom_b_imported
wisdom import status for backward transform
Definition monitor.cpp:111
bool is_gpu_enabled()
Check if GPU mode is enabled.
Definition monitor.cpp:297
bool is_gpu_available()
Check if GPUs are available in the system.
Definition monitor.cpp:292
void display_prog_logo()
Display program logo in stdout.
Definition monitor.cpp:871
bool fftw_wisdom_f_imported
wisdom import status for forward transform
Definition monitor.cpp:110
float max_count_grid
maximum number of grids
Definition monitor.cpp:105
Logger logger
default logger (at NSET logging level)
int max_count_rgrid
maximum number of 3-d real grids
Definition monitor.cpp:103
std::string show_current_datetime(bool utc=false)
Return the current datetime string.
Definition monitor.cpp:189
float count_grid
number of grids
Definition monitor.cpp:102
void display_prog_licence(bool brief=false)
Display program licence in stdout.
Definition monitor.cpp:890
double gbytesMemGPU
current (GPU) memory usage in gibibytes
Definition monitor.cpp:97
double gbytesMaxMemGPU
maximum (GPU) memory usage in gibibytes
Definition monitor.cpp:98
int max_count_cgrid
maximum number of 3-d complex grids
Definition monitor.cpp:104
int currTask
current task
Definition monitor.cpp:92
void display_prog_logbars(int endpoint)
Display program log bars in stdout.
Definition monitor.cpp:994
std::vector< float > set_nodes_by_str(std::string interval_str)
Set a node list possibly from a string.
Definition monitor.cpp:649
LogLevel
Logging levels.
Definition monitor.hpp:435
@ NSET
0: unset
Definition monitor.hpp:437
@ INFO
30: info
Definition monitor.hpp:440
@ STAT
20: status
Definition monitor.hpp:439
@ WARN
40: warning
Definition monitor.hpp:441
@ ERRO
50: error/critical
Definition monitor.hpp:442
@ DBUG
10: debugging
Definition monitor.hpp:438
int get_gpu_count(bool sys=false)
Get the number of GPUs available.
Definition monitor.cpp:258
bool is_gpu_single()
Check if in single-GPU mode.
Definition monitor.cpp:322
int count_fft
number of FFTs
Definition monitor.cpp:107
int count_cgrid
number of 3-d complex grids
Definition monitor.cpp:101
double gbytesMaxMem
maximum memory usage in gibibytes
Definition monitor.cpp:95
std::vector< std::string > split_string(const std::string &str, const std::string &delimiter)
Split a string into a vector of strings.
Definition monitor.cpp:59
int count_rgrid
number of 3-d real grids
Definition monitor.cpp:100
std::string join_strings(const std::vector< std::string > &strings, const std::string &delimiter)
Join a vector of strings with a delimiter.
Definition monitor.cpp:45
int count_ifft
number of IFFTs
Definition monitor.cpp:108
void update_maxcntgrid()
Update the maximum 3-d grid counts.
Definition monitor.cpp:177
void display_prog_info(bool runtime=false)
Display program information in stdout.
Definition monitor.cpp:930
void exit_fatal(const std::string &msg)
Terminate the program with exit status EXIT_FAILURE.
Definition monitor.cpp:326
bool is_colourable()
Check if the program stdout is colourable.
Definition monitor.cpp:506
std::string show_elapsed_time(double duration_in_seconds)
Return the elapsed-time string in 'HH:MM:SS' format.
Definition monitor.cpp:212
std::string get_build_datetime()
Return the build datetime string in ISO 8601–like format.
Definition monitor.cpp:757