原代码是linux下运行,修改后可在window下运行。
- #ifndef TQDM_H
- #define TQDM_H
-
- #include <chrono>
- #include <ctime>
- #include <numeric>
- #include <ios>
- #include <string>
- #include <cstdlib>
- #include <iostream>
- #include <vector>
- #include <math.h>
- #include <algorithm>
- #include <io.h>
- class tqdm {
- private:
- // time, iteration counters and deques for rate calculations
- std::chrono::time_point<std::chrono::system_clock> t_first = std::chrono::system_clock::now();
- std::chrono::time_point<std::chrono::system_clock> t_old = std::chrono::system_clock::now();
- int n_old = 0;
- std::vector<double> deq_t;
- std::vector<int> deq_n;
- int nupdates = 0;
- int total_ = 0;
- int period = 1;
- unsigned int smoothing = 50;
- bool use_ema = true;
- float alpha_ema = 0.1;
-
- std::vector<const char*> bars = { " ", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█" };
-
- bool in_screen = (system("test $STY") == 0);
- bool in_tmux = (system("test $TMUX") == 0);
- bool is_tty = _isatty(1);
- bool use_colors = true;
- bool color_transition = true;
- int width = 40;
-
- std::string right_pad = "▏";
- std::string label = "";
-
- void hsv_to_rgb(float h, float s, float v, int& r, int& g, int& b) {
- if (s < 1e-6) {
- v *= 255.;
- r = v; g = v; b = v;
- }
- int i = (int)(h*6.0);
- float f = (h*6.) - i;
- int p = (int)(255.0*(v*(1. - s)));
- int q = (int)(255.0*(v*(1. - s * f)));
- int t = (int)(255.0*(v*(1. - s * (1. - f))));
- v *= 255;
- i %= 6;
- int vi = (int)v;
- if (i == 0) { r = vi; g = t; b = p; }
- else if (i == 1) { r = q; g = vi; b = p; }
- else if (i == 2) { r = p; g = vi; b = t; }
- else if (i == 3) { r = p; g = q; b = vi; }
- else if (i == 4) { r = t; g = p; b = vi; }
- else if (i == 5) { r = vi; g = p; b = q; }
- }
-
- public:
- tqdm() {
- if (in_screen) {
- set_theme_basic();
- color_transition = false;
- }
- else if (in_tmux) {
- color_transition = false;
- }
- }
-
- void reset() {
- t_first = std::chrono::system_clock::now();
- t_old = std::chrono::system_clock::now();
- n_old = 0;
- deq_t.clear();
- deq_n.clear();
- period = 1;
- nupdates = 0;
- total_ = 0;
- label = "";
- }
-
- void set_theme_line() { bars = { "─", "─", "─", "╾", "╾", "╾", "╾", "━", "═" }; }
- void set_theme_circle() { bars = { " ", "◓", "◑", "◒", "◐", "◓", "◑", "◒", "#" }; }
- void set_theme_braille() { bars = { " ", "⡀", "⡄", "⡆", "⡇", "⡏", "⡟", "⡿", "⣿" }; }
- void set_theme_braille_spin() { bars = { " ", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠇", "⠿" }; }
- void set_theme_vertical() { bars = { "▁", "▂", "▃", "▄", "▅", "▆", "▇", "█", "█" }; }
- void set_theme_basic() {
- bars = { " ", " ", " ", " ", " ", " ", " ", " ", "#" };
- right_pad = "|";
- }
- void set_label(std::string label_) { label = label_; }
- void disable_colors() {
- color_transition = false;
- use_colors = false;
- }
-
- void finish() {
- progress(total_, total_);
- printf("\n");
- fflush(stdout);
- }
- void progress(int curr, int tot) {
- if (is_tty && (curr%period == 0)) {
- total_ = tot;
- nupdates++;
- auto now = std::chrono::system_clock::now();
- double dt = ((std::chrono::duration<double>)(now - t_old)).count();
- double dt_tot = ((std::chrono::duration<double>)(now - t_first)).count();
- int dn = curr - n_old;
- n_old = curr;
- t_old = now;
- if (deq_n.size() >= smoothing) deq_n.erase(deq_n.begin());
- if (deq_t.size() >= smoothing) deq_t.erase(deq_t.begin());
- deq_t.push_back(dt);
- deq_n.push_back(dn);
-
- double avgrate = 0.;
- if (use_ema) {
- avgrate = deq_n[0] / deq_t[0];
- for (unsigned int i = 1; i < deq_t.size(); i++) {
- double r = 1.0*deq_n[i] / deq_t[i];
- avgrate = alpha_ema * r + (1.0 - alpha_ema)*avgrate;
- }
- }
- else {
- double dtsum = std::accumulate(deq_t.begin(), deq_t.end(), 0.);
- int dnsum = std::accumulate(deq_n.begin(), deq_n.end(), 0.);
- avgrate = dnsum / dtsum;
- }
-
- // learn an appropriate period length to avoid spamming stdout
- // and slowing down the loop, shoot for ~25Hz and smooth over 3 seconds
- if (nupdates > 10) {
- period = (int)(std::min(std::max((1.0 / 25)*curr / dt_tot, 1.0), 5e5));
- smoothing = 25 * 3;
- }
- double peta = (tot - curr) / avgrate;
- double pct = (double)curr / (tot*0.01);
- if ((tot - curr) <= period) {
- pct = 100.0;
- avgrate = tot / dt_tot;
- curr = tot;
- peta = 0;
- }
-
- double fills = ((double)curr / tot * width);
- int ifills = (int)fills;
-
- printf("\015 ");
- if (use_colors) {
- if (color_transition) {
- // red (hue=0) to green (hue=1/3)
- int r = 255, g = 255, b = 255;
- hsv_to_rgb(0.0 + 0.01*pct / 3, 0.65, 1.0, r, g, b);
- printf("\033[38;2;%d;%d;%dm ", r, g, b);
- }
- else {
- printf("\033[32m ");
- }
- }
- for (int i = 0; i < ifills; i++) std::cout << bars[8];
- if (!in_screen && (curr != tot)) printf("%s", bars[(int)(8.0*(fills - ifills))]);
- for (int i = 0; i < width - ifills - 1; i++) std::cout << bars[0];
- printf("%s ", right_pad.c_str());
- if (use_colors) printf("\033[1m\033[31m");
- printf("%4.1f%% ", pct);
- if (use_colors) printf("\033[34m");
-
- std::string unit = "Hz";
- double div = 1.;
- if (avgrate > 1e6) {
- unit = "MHz"; div = 1.0e6;
- }
- else if (avgrate > 1e3) {
- unit = "kHz"; div = 1.0e3;
- }
- printf("[%4d/%4d | %3.1f %s | %.0fs<%.0fs] ", curr, tot, avgrate / div, unit.c_str(), dt_tot, peta);
- printf("%s ", label.c_str());
- if (use_colors) printf("\033[0m\033[32m\033[0m\015 ");
-
- if ((tot - curr) > period) fflush(stdout);
-
- }
- }
- };
- #endif
主函数:
- #include "MyClass.h"
- #include <windows.h>
- int main() {
-
- int N = 2000;
- tqdm bar;
-
- std::cout << "Overhead of loop only:" << std::endl;
- for (int i = 0; i < 100000000; i++) {
- bar.progress(i, 100000000);
- }
- bar.finish();
-
-
- std::cout << "Basic:" << std::endl;
- bar.reset();
- bar.set_theme_basic();
- for (int i = 0; i < N; i++) {
- bar.progress(i, N);
- Sleep(1000);
- }
- bar.finish();
-
- std::cout << "Braille:" << std::endl;
- bar.reset();
- bar.set_theme_braille();
- for (int i = 0; i < N; i++) {
- bar.progress(i, N);
- Sleep(300);
- }
- bar.finish();
-
- std::cout << "Line:" << std::endl;
- bar.reset();
- bar.set_theme_line();
- for (int i = 0; i < N; i++) {
- bar.progress(i, N);
- Sleep(300);
- }
- bar.finish();
-
- std::cout << "Circles:" << std::endl;
- bar.reset();
- bar.set_theme_circle();
- for (int i = 0; i < N; i++) {
- bar.progress(i, N);
- Sleep(300);
- }
- bar.finish();
-
- bar.reset();
- std::cout << "Vertical bars:" << std::endl;
- bar.reset();
- bar.set_theme_vertical();
- for (int i = 0; i < N; i++) {
- bar.progress(i, N);
- Sleep(3000);
- }
- bar.finish();
-
- return 0;
- }
