I have a C++ program with a long running loop. It has about 500000 iterations. I'd like to print the progress every 5%.
What I have so far is below. Problem with this is that it will keep writing the same line (0%, %5 etc) over and over. This is because after truncating the percent to an integer there are 1000's of iterations that will hit upon a multiple of 5. This makes the program noticeably slower.
Conversely, if I don't truncate to an integer, then the result of percent % 5.0
is unlikely to be precisely 0.
How can I print a progress indicator with the minimum 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 have gone with christophes' which just came to the least number of instructions. It shaved 25% of runtime, so pretty significant!
Considering that totalWindows
seems to remain unchanged, and integer
increments/decrements will probably be faster than a lot of double
operations with conversion to int, I propose:
// 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 the cumulative roundings would not be acceptable for displaying the progress, you could always opt to calculate the exact value in the if
-block: the calculation would be performedonly once every 5% instead of at each iteration.
How 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? That also hurts performance. If the number of iterations are 500000 an 32 bit int should be sufficient.
Another and better approach because percent isn't calculated in every loop:
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();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With