C++ Program performs better when piped - c++

I haven't done any programming in a decade. I wanted to get back into it, so I made this little pointless program as practice.
The easiest way to describe what it does is with output of my --help codeblock:
./prng_bench --help
./prng_bench: usage: ./prng_bench $N $B [$T]
This program will generate an N digit base(B) random number until
all N digits are the same.
Once a repeating N digit base(B) number is found, the following statistics are displayed:
-Decimal value of all N digits.
-Time & number of tries taken to randomly find.
Optionally, this process is repeated T times.
When running multiple repititions, averages for all N digit base(B)
numbers are displayed at the end, as well as total time and total tries.
My "problem" is that when the problem is "easy", say a 3 digit base 10 number, and I have it do a large number of passes the "total time" is less when piped to grep. ie:
command ; command |grep took :
./prng_bench 3 10 999999 ; ./prng_bench 3 10 999999|grep took
....
Pass# 999999: All 3 base(10) digits = 3 base(10). Time: 0.00005 secs. Tries: 23
It took 191.86701 secs & 99947208 tries to find 999999 repeating 3 digit base(10) numbers.
An average of 0.00019 secs & 99 tries was needed to find each one.
It took 159.32355 secs & 99947208 tries to find 999999 repeating 3 digit base(10) numbers.
If I run the same command many times w/o grep time is always VERY close.
I'm using srand(1234) for now, to test. The code between my calls to clock_gettime() for start and stop do not involve any stream manipulation, which would obviously affect time. I realize this is an exercise in futility, but I'd like to know why it behaves this way.
Below is heart of the program. Here's a link to the full source on DB if anybody wants to compile and test. https://www.dropbox.com/s/bczggar2pqzp9g1/prng_bench.cpp
clock_gettime() requires -lrt.
for (int pass_num=1; pass_num<=passes; pass_num++) { //Executes $passes # of times.
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &temp_time); //get time
start_time = timetodouble(temp_time); //convert time to double, store as start_time
for(i=1, tries=0; i!=0; tries++) { //loops until 'comparison for' fully completes. counts reps as 'tries'. <------------
for (i=0; i<Ndigits; i++) //Move forward through array. |
results[i]=(rand()%base); //assign random num of base to element (digit). |
/*for (i=0; i<Ndigits; i++) //---Debug Lines--------------- |
std::cout<<" "<<results[i]; //---a LOT of output.---------- |
std::cout << "\n"; //---Comment/decoment to disable/enable.*/ // |
for (i=Ndigits-1; i>0 && results[i]==results[0]; i--); //Move through array, != element breaks & i!=0, new digits drawn. -|
} //If all are equal i will be 0, nested for condition satisfied. -|
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &temp_time); //get time
draw_time = (timetodouble(temp_time) - start_time); //convert time to dbl, subtract start_time, set draw_time to diff.
total_time += draw_time; //add time for this pass to total.
total_tries += tries; //add tries for this pass to total.
/*Formated output for each pass:
Pass# ---: All -- base(--) digits = -- base(10) Time: ----.---- secs. Tries: ----- (LINE) */
std::cout<<"Pass# "<<std::setw(width_pass)<<pass_num<<": All "<<Ndigits<<" base("<<base<<") digits = "
<<std::setw(width_base)<<results[0]<<" base(10). Time: "<<std::setw(width_time)<<draw_time
<<" secs. Tries: "<<tries<<"\n";
}
if(passes==1) return 0; //No need for totals and averages of 1 pass.
/* It took ----.---- secs & ------ tries to find --- repeating -- digit base(--) numbers. (LINE)
An average of ---.---- secs & ---- tries was needed to find each one. (LINE)(LINE) */
std::cout<<"It took "<<total_time<<" secs & "<<total_tries<<" tries to find "
<<passes<<" repeating "<<Ndigits<<" digit base("<<base<<") numbers.\n"
<<"An average of "<<total_time/passes<<" secs & "<<total_tries/passes
<<" tries was needed to find each one. \n\n";
return 0;

Printing to the screen is very slow in comparison to a pipe or running without printing. Piping to grep keeps you from doing it.

It is not about printing to the screen; it is about the output being a terminal (tty).
According to the POSIX spec:
When opened, the standard error stream is not fully buffered; the
standard input and standard output streams are fully buffered if and
only if the stream can be determined not to refer to an interactive
device.
Linux interprets this to make the FILE * (i.e. stdio) stdout line-buffered when the output is a tty (e.g. your terminal window), and block-buffered otherwise (e.g. your pipe).
The reason sync_with_stdio makes a difference is that when it is enabled, the C++ cout stream inherits this behavior. When you set it to false, it is no longer bound by that behavior and thus becomes block buffered.
Block buffering is faster because it avoids the overhead of flushing the buffer on every newline.
You can further verify this by piping to cat instead of grep. The difference is the pipe itself, not the screen per se.

Thank you Collin & Nemo. I was certain that because I wasn't calling std::cout between getting start & stop times that it wouldn't have an effect. Not so. I think this is due to optimizations that the compiler performs even with -O0 or 'defaults'.
What I think is happening...? I think that as Collin suggested, the compiler is trying to be clever about when it writes to the TTY. And, as Nemo pointed out, cout inherits the line buffered properties of stdio.
I'm able to reduce the effect, but not eliminate, by using:
std::cout.sync_with_stdio(false);
From my limited reading on this, it should be called before any output operations are done.
Here's source for no_sync version: https://www.dropbox.com/s/wugo7hxvu9ao8i3/prng_bench_no_sync.cpp
./no_sync 3 10 999999;./no_sync 3 10 999999|grep took
Compiled with -O0
999999: All 3 base(10) digits = 3 base(10) Time: 0.00004 secs. Tries: 23
It took 166.30801 secs & 99947208 tries to find 999999 repeating 3 digit base(10) numbers.
An average of 0.00017 secs & 99 tries was needed to find each one.
It took 163.72914 secs & 99947208 tries to find 999999 repeating 3 digit base(10) numbers.
Complied with -O3
999999: All 3 base(10) digits = 3 base(10) Time: 0.00003 secs. Tries: 23
It took 143.23234 secs & 99947208 tries to find 999999 repeating 3 digit base(10) numbers.
An average of 0.00014 secs & 99 tries was needed to find each one.
It took 140.36195 secs & 99947208 tries to find 999999 repeating 3 digit base(10) numbers.
Specifying not to sync with stdio changed my delta between piped and non-piped from over 30 seconds to less than 3. See original question for original delta it was ~191 - ~160
To further test I created another version using a struct to store stats about each pass. This method does all output after all passes are complete. I want to emphasize that this is probably a terrible idea. I'm allowing a command line argument to determine the size of a dynamically allocated array of structs containing an int, double and unsigned long. I can't even run this version with 999,999 passes. I get a segmentation fault. https://www.dropbox.com/s/785ntsm622q9mwd/prng_bench_struct.cpp
./struct_prng 3 10 99999;./struct_prng 3 10 99999|grep took
Pass# 99999: All 3 base(10) digits = 6 base(10) Time: 0.00025 secs. Tries: 193
It took 13.10071 secs & 9970298 tries to find 99999 repeating 3 digit base(10) numbers.
An average of 0.00013 secs & 99 tries was needed to find each one.
It took 13.12466 secs & 9970298 tries to find 99999 repeating 3 digit base(10) numbers.
What I've learned from this is that you can't count on the order you've coded things being the order they're executed in. In future programs I'll probably implement getopt instead of writing my own parse_args function. This would allow me to surpress extraneous output on high repetition loops, by requiring users to use the -v switch if they want to see it.
I hope the further testing proves useful to anybody wondering about piping and output in loops. All of the results I've posted were obtained on a RasPi. All of the source codes linked are GPL, just because that's the first license I could think of... I really have no self-aggrandizing need for the copyleft provisions of the GPL, I just wanted to be clear that it's free, but without warranty or liability.
Note that all of the sources linked have the call to srand(...) commented out, so all of your pseudo-random results will be exactly the same.

Related

C++ not printing to console during while loop, only after loop is finished

Background
I'm currently writing some code for a naughts and crosses machine learning program based on M.E.N.A.C.E, and I have finished the code for the actual machine learning and for playing against the computer, as well as another computer to play games against it to train it. The user can enter that they'd like to let the computer train itself, and then enter the number of games to play.
Problem
I'm trying to make a % completion display that overwrites itself each time it updates. The issue I have is that for some reason the code won't print anything that should be printed during the while loop, instead waiting until the end to print all of it in one go. I am using '\r' (carriage return) to overwrite the last printed text. If I remove the carriage return, the while loop prints the text on each iteration like it should do. I don't have any idea what's causing this problem as I'm quite new to C++.
I am programming in Repl.it since I'm not able to install an IDE on the computer I'm using.
Here is the subroutine for calculating and displaying the % completion (using namespace std).
void calcCompletion(int a, int b)
{
int completion = (static_cast<float>(a)/b) * 100;
cout << '\r';
cout << completion << "%";
}
And here is the start of the while loop where the procedure is called (mode is always 2 when I am testing this).
while(gamesPlayed < gameEnd)
{
//permutations();
if(mode != "1")
{
calcCompletion(gamesPlayed, gameEnd);
}
It's a very long while loop so I won't show the whole thing (hence why the curly brackets do not match up).
And here is the output:
 clang++-7 -pthread -std=c++17 -o main ai.cpp base3.cpp main.cpp otherai.cpp permutations.cpp winCheck.cpp
 ./main
Enter mode.
1 - Play the AI
2 - Train the AI
2
How many games would you like the AI to play?
5
Simulating...
80%
Games complete.
Games played: 5
Games won: 1
Games lost: 0
Games drawn: 4
Win Percentage: 20%
Loss Percentage: 0%
--------------
It just waits until it is done with the while loop and then prints the last number, instead of printing as it goes.
I have tested trying to overwrite something I've written with no time delay in another code, it works fine so clearly being overwritten too quickly isn't the problem.
You have not closed the curly braces of (if clause) under the while loop

Audio manipulation and delete some part of the audio

I'm new in voice codding, now I am succeed to recording microphone in the files and save each 10 seconds in a file with SaveRecordtoFile function(doing this with no problem)
Now I want to delete for example 2 seconds from the recorded data so my output will be 8 seconds instead of 10, in the randomTime array 0 is the number of seconds witch I want to be delete...
In a for-loop I copy the data of waveHeader->lpData in a new buffer if (randomTime[i] == '1')
It seems this is a true algorithm and should works but the problem is the outputs, some of the outputs are good (about 70% or more) but some of them are corrupted
I think I have a mistake in the code but I debug this code for some days and I don't understand what is the problem?
And as my 70% or more of outputs are good I think It's not because of bytes or samples
Your code can break a sample apart, after that the stream is out of sync and you hear a loud noise.
How it happens? Your sample size is 4 bytes. So you must never copy anything that is not a multiple of 4. 10 seconds of audio will take 10x48000×4=1920000 bytes. However Sleep(10000) will always be near 10 seconds but not exactly 10 seconds. So you can get 1920012 bytes. Then you do:
dwSamplePerSec = waveHeader->dwBytesRecorded / 10; // 10 Secs
that returns 192001 (which is not multiple of 4) and the steam gets out of sync. If you're lucky you receive 1920040 bytes for 10 second and that remains multiple of 4 after division on 10 and you're ok.

C++: How to get vector to print user input?

I'm having some trouble figuring out how to print out my vector's user input. I think there's something wrong specifically with my iterator loop, but I'm not sure what. I've been toying around with this and I'm stumped. I'm also having trouble with my sentinel value - my program ceases to continue after entering in my sentinel value. Am I missing something?
Any help you could provide would be greatly appreciated.
Here's my code: (there are some variables here that you might notice that aren't being used in this sample of code. i'm using those variables for another portion of my program).
Any help that you could provide in regards to this would be INCREDIBLY helpful. Thank you.
You're declaring your check_amounts vector a second time, right before your output loop, so you're outputting the contents of an empty vector. Delete the second declaration.
Your code got caught in infinite loop at :
for (i = 0; amount < length; i++) length /= 10;
Because amount = -1, length = 0.
Also do not use != for double values, e.g. (amount != -1). Use < or > . Equality check is not reliable due to inexact bit-pattern
this is what i get when i run your code:
This program inputs a dollar amount and prints it in check-format.
Input up to five check amounts, one at a time. (Enter -1 to quit)
5
Input up to five check amounts, one at a time. (Enter -1 to quit)
10
Input up to five check amounts, one at a time. (Enter -1 to quit)
15
Input up to five check amounts, one at a time. (Enter -1 to quit)
20
Input up to five check amounts, one at a time. (Enter -1 to quit)
25
The check-formated dollar amount for your check(s) are printed as follows: 5 **** 25.00
10 **** 25.00
15 **** 25.00
20 **** 25.00
25 **** 25.00
Can't see a problem with printing out vector's user input. Avik Paul is right for the sentinel case by the way. You should be using the last valid amount maybe.

C++ Program, Console/Terminal Output. How to implement "updating text"

I am writing a C++ program, which runs a long data analysis algorithm. It takes several days to finish running, so it is useful to have a prompt which outputs the "percentage complete" every time a new loop in the program starts so that the user (me) knows the computer isn't sitting in an infinite loop somewhere or has crashed.
At the moment I am doing this the most basic way, by computing the percentage complete as a floating point number and doing:
std::cout << "Percentage complete: " << percentage_complete << " %" << std::endl;
But, when the program has a million loops to run, this is kind of messy. In addition, if the terminal scrollback is only 1000 lines, then I lose the initial debug info printed out at the start once the program is 0.1 % complete.
I would like to copy an idea I have seen in other programs, where instead of writing a new line each time with the percentage complete, I simply replace the last line written to the terminal with the new percentage complete.
How can I do this? Is that possible? And if so, can this be done in a cross platform way? Are there several methods of doing this?
I am unsure how to describe what I am trying to do perfectly clearly, so I hope that this clear enough that you understand what I am trying to do.
To clarify, rather than seeing this:
Running program.
Debug info:
Total number of loops: 1000000
Percentage complete: 0 %
Percentage complete: 0.001 %
Percentage complete: 0.002 %
.
.
.
Percentage complete: 1.835 %
I would like to see this:
Running program.
Debug info:
Total number of loops: 1000000
Percentage complete: 1.835 %
And then on the next loop the terminal should update to this:
Running program.
Debug info:
Total number of loops: 1000000
Percentage complete: 1.836 %
I hope that's enough information.
(Okay, so this output would actually be for 100000 steps, not 1000000.)
Instead of \n or std::endl, use \r. The difference is that the latter returns the cursor to the beginning if the line without a new line.
Disclaimer (as per Lightness' objections): This is not necessarily portable, so YMMV.

C++ calculating time intervals

I want to calculate time intervals (in 1/10th of 1 second) between some events happening in my program. Thus I use clock function for these needs like follows:
clock_t begin;
clock_t now;
clock_t diff;
begin = clock();
while ( 1 )
{
now = clock();
diff = now - begin;
cout << diff / CLOCKS_PER_SEC << "\n";
//usleep ( 1000000 );
};
I expect the program to print 0 for 1 second, then 1 for 1 sec., then 2 for 1 sec. and so on... In fact it prints 0 for about 8 seconds, then 1 for about 8 seconds and so on...
By the way, if I add usleep in order program prints only 1 time per second, it prints only 0 all way long...
Great thanks for help!
The clock() function returns the amount of CPU time charged to your program. When you are blocked inside a usleep() call, no time is being charged to you, making it very clear why your time never seems to increase. As to why you seem to be taking 8 seconds to be charged one second -- there are other things going on within your system, consuming CPU time that you would like to be consuming but you must share the processor. clock() cannot be used to measure the passage of real time.
I bet your printing so much to stdout that old prints are getting buffered. The buffer is growing and the output to the console can't keep up with your tight loop. By adding the sleep you're allowing the buffer some time to flush and catch up. So even though its 8 seconds into your program, your printing stuff from 8 seconds ago.
I'd suggest putting the actual timestamp into the print statement. See if the timestamp is lagging significantly from the actual time.
If you're able to use boost, checkout the Boost Timers library.
Maybe you have to typecast it to double.
cout << (double)(diff / CLOCKS_PER_SEC) << "\n";
Integers get rounded, probably to 0 in your case.
Read about the time() function.