C ++ print progress with minimal impact on runtime

I have a C ++ program with a long stroke. It has about 500,000 iterations. I would like to print progress every 5%.

What I still have is below. The problem is that he will continue to write the same line (0%,% 5, etc.) again and again. This is due to the fact that after truncating the percentage by an integer, it is 1000 iterations, which are multiples of 5. This makes the program noticeably slower.

Conversely, if I do not truncate an integer, then the result of percent % 5.0 unlikely to be exactly 0.

How to print a progress indicator with the least possible impact on runtime?

 // Counters for progress indicator int i = 0; float totalWindows = (float)(win.nX * win.nY); int percent; while (win.next() == 0) { // Read the data // Nicely formatted progress indicator i++; percent = (i / totalWindows) * 100; if (percent % 5 == 0) { std::cout << "\r" << std::string(percent/5, '|') << percent << "%"; std::cout.flush(); } } 

EDIT: Thanks for the answers. I went with the Christians who came to the least amount of instructions. It shaved 25% of the execution time, so it’s pretty significant!

+4
source share
3 answers

Given that totalWindows seems to remain unchanged, and the integer increments / reductions will probably be faster than many double operations with conversion to int, I suggest:

 // Counters for progress indicator int i = 0; float totalWindows = (float)(win.nX * win.nY); int increment5 = 0.05 * totalWindows; // how many iterations does 5% represent ? int countdown = increment5; // decrement countdown instead of modulo int percent5 = 0; // number of elements in the progress bar (1 means 5%) while (win.next() == 0) { // Read the data // Nicely formatted progress indicator i++; if (--countdown == 0) { percent5++; std::cout << "\r" << std::string(percent5, '|') << percent5*5 << "%"; countdown = increment5; std::cout.flush(); } } 

If you fear that cumulative rounding will not be acceptable for displaying progress, you can always select the exact value in the if block: the calculation will be performed only once every 5% instead of each iteration,

+2
source

What about:

 int step = 5; int nextPrint = step; while (win.next() == 0) { // Read the data // Nicely formatted progress indicator i++; percent = (100 * i) / totalWindows; if (percent >= nextPrint) { std::cout << "\r" << std::string(percent/5, '|') << percent << "%"; std::cout.flush(); nextPrint += step; } } 

BTW: Why do you have totalWindows as a float? It also impairs performance. If the number of iterations is 500,000, 32 bits should be sufficient.

Another and better approach, because the percentage is not calculated in each cycle:

 const int percentPrint = 5; int step = totalWindows / (100/percentPrint); int nextPrint = step; while (win.next() == 0) { // Read the data // Nicely formatted progress indicator i++; if (i >= nextPrint) { percent = (100 * i) / totalWindows; std::cout << "\r" << std::string(percent/percentPrint , '|') << percent << "%"; std::cout.flush(); nextPrint += step; } } std::cout << "\r" << std::string(100/percentPrint , '|') << percent << "%"; std::cout.flush(); 
+1
source

Instead of calculating the percentage each time, you can calculate what 5% of the total amount is and use it directly.

Consider this simplified example:

 int main(int argc, char * argv) { int total = 50000; int total_percent_stop = total * 5 / 100; //Set the percentage here. for (int i = 0; i < total; i++) { if (i % total_percent_stop == 0) { printf("%d percent done\n", (i / total_percent_stop) * 5); } } } 

If the performance of this code is very important to you, you can avoid the relatively expensive division operations by doing something like this (due to some readability).

 int main(int argc, char * argv) { int total = 50000; int total_percent_stop = total * 5 / 100; //Set the percentage here for (int i = 0, percent_counter = 0, n_percent = 0; i < total; i++, percent_counter++) { if (percent_counter == total_percent_stop) { percent_counter = 0; n_percent++; printf("%d percent done\n", n_percent * 5); } } } 

On my machine, with sufficiently large values, the second amount is much faster. When I changed everything to unsigned long longs and set the total to 5 billion, the second took 9.336 seconds and the first took 40.159 seconds

0
source

All Articles