We are studying the performance of various sorting algorithms and implemented our version of mergesort. We are trying to measure the running time with different input, but when we run the main() program shown below, we are getting different time results.
For example, clock() function output below can show 30 seconds with large input, but when we use the actual timer using our phones, the main program takes about 2 minutes.
What are we missing here? Are we not using the clock() function in a right way? Why is there such a big difference (1.5 minutes)?
Thank you
int n;
cout << "Enter n - lenght of array" << endl;
cin >> n;
vector<int> v(n);
for(int i = 0; i < n; ++i)
{
v[i] = i;
}
auto rng = default_random_engine {};
std::shuffle(std::begin(v), std::end(v), rng);
clock_t begin = clock();
sort(v);
cout << "done";
clock_t end = clock();
cout <<"total time : " << (double)(end-begin) / CLOCKS_PER_SEC<<endl;
return 0;
I ran your code by replacing the sort function with the std::sort, for n=5000000 it showed 11.744s then I moved the line clock_t begin = clock(); before the declaration of vector v and the time was 13.818s
So it seems memory allocation, O(N) initialization and shuffling can take a good amount of time and if you choose a much bigger number for n, depending on the efficiency of your sort function for a random inputset, initialization can take more time than the sort.
Related
I'm trying to create a program using Merge Sort for an assignment, using rand and srand to place random numbers in the array. The goal is to sort a large number of values entered manually by the user and count how long it takes the program in seconds to process it.
Everything works so far, but the one problem I'm getting is that a random value is only being assigned to the first position and the rest are given 0
This is the body of my merge function (main program) where I suspect the issue might be:
//Function that begins the Merge Sort option and acts as int main()
void mergeSortAlg(){
srand(time(NULL));
int n= 0;
cout << "\n\nPlease make a selection by typing one of the following:\n";
cout << "1000 \n10000 \n50000 \n\n";
cin >> n;
cout << "You have selected: " << n << "\n";
cout << "Stopwatch has started...\n\n";
//statement that begins counting the execution time for the program
auto start = chrono::steady_clock::now();
int arr[n]= {rand() % 100}; //generating random values between 1-99 in the array
int arr_size= sizeof(arr) / sizeof(arr[0]);
cout << "The array list before sorting is: \n";
displayMergeArray(arr, arr_size);
mergeSorting(arr, 0, arr_size-1);
cout << "\n\n\nThe array list after sorting is: \n";
displayMergeArray(arr, arr_size);
auto end = chrono::steady_clock::now(); //stopping the timer at the end of the merge sort
//printing the amount of time (in seconds) the program took to sort the values
cout << "\n\n\nTotal processing time elapsed:\n" << chrono::duration_cast<chrono::seconds>(end - start).count() << " seconds\n\n\n";
}
Note that the mergeSortAlg() function just acts as int main() since the main program currently is being used to call a menu function for 3 sorting options
Still kind of new to merging and C++ in general, so I'm not sure how to use rand to assign the number of random values needed based on how many positions are entered by the user.
You expect array initialization to work in a way it does not work. This
int arr[n]= {rand() % 100};
Initializes the first element with rand()%100 and the remaining elements are zero-initialized.
Moreover int arr[n] is not valid c++. See here: Why aren't variable-length arrays part of the C++ standard?.
You can use a std::vector when the size is only known at runtime and you can use a loop to roll n random numbers instead of just one:
std::vector<int> arr(n);
for (auto& e : arr) e = rand() % 100;
PS: Note that rand() is not the best way to generate random numbers. rand() is only loosely specificed and implementations are known to have issues. And on top of that rand() % N is not uniformly distributed (only if RAND_MAX % N == 0). You can find better random generators in <random>.
I'm trying to create a programm that makes sudoku's. But when I try to let the programm place numbers at random spots it doesnt use every position.
I tried to use rand(); with srand(time(0));
and random number generators from <random>.
In the Constructor i use this:
mt19937_64 randomGeneratorTmp(time(0));
randomGenerator = randomGeneratorTmp;
uniform_int_distribution<int> numGetterTmp(0, 8);
numGetter = numGetterTmp;
While I have randomGenerator and numGetter variable so i can use them in another function of the sudoku object.
And this is the function where i use the random numbers:
bool fillInNumber(int n){
int placedNums = 0, tries=0;
int failedTries[9][9];
for(int dim1=0;dim1<9;dim1++){
for(int dim2=0;dim2<9;dim2++){
failedTries[dim1][dim2] = 0;
}
}
while(placedNums<9){
int dim1 = numGetter(randomGenerator);
int dim2 = numGetter(randomGenerator);
if(nums[dim1][dim2]==0){
if(allowedLocation(n,dim1,dim2)){
nums[dim1][dim2] = n;
placedNums++;
} else {
failedTries[dim1][dim2]++;
tries++;
}
}
if(tries>100000000){
if(placedNums == 8){
cout<< "Number: " << n << endl;
cout<< "Placing number: " << placedNums << endl;
cout<< "Dim1: " << dim1 << endl;
cout<< "Dim2: " << dim2 << endl;
printArray(failedTries);
}
return false;
}
}
return true;
}
(The array failedTries just shows me which positions the program tried.
and most of the fields have been tried millions of times, while others not once)
I think that the random generation just repeats itself before it used every number combination, but i don't know what i'm doing wrong.
Don't expect random numbers to have an even distribution over your matrix - there's no guarantee they will. That would be like having a routine to randomly generate cards from a deck, and waiting until you see all 52 values - you may wait a very very long time to get every single card.
That's especially true since "random" numbers are actually generated by pseudorandom number generators, which, generally utilize multiplying a very large number and adding an arbitrary constant. Depending on the algorithm, this might cluster in unanticipated ways.
If I may make a suggestion: create an array of all of the possible matrix positions, and then shuffle that array. That's how deck shuffling algorithms are able to guarantee you have all the cards in the deck covered, and it's the same problem you're having.
For a shuffle, generate two random positions in the array and exchange the values - repeat as many times as it takes to get a suitably random result. (Since your array is limited to 9x9, I might shuffle an array of ints 0..80: extract the columns and rows with a /9 and a % 9 for each int).
I wrote a simple program that should be equivalent to your code, and it works without issues:
#include <iostream>
#include <random>
#include <vector>
using namespace std;
int main()
{
std::default_random_engine engine;
std::uniform_int_distribution<int> distr(0,80);
std::vector<bool> vals(81,false);
int attempts = 0;
int trueCount = 0;
while(trueCount < 81)
{
int newNum = distr(engine);
if(!vals[newNum])
{
vals[newNum] = true;
trueCount++;
}
attempts++;
}
std::cout << "attempts: " << attempts;
return 0;
}
Usually it prints around 400 attempts which is the statistical average.
You most likely have a bug in your code. I am not sure where though, as you don't show all of your code.
I am trying to time a code I've got in C++. I have an inner and an outer loop that I want to time separately, but at the same time. For some reason when I do this one of the instances returns 1.84467e+13 and always this exact number.
Why is this happening?
Here is a minimum working example that replicates the effect on my machine:
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
int main()
{
long int i, j;
clock_t start, finish, tick, tock;
double a = 0.0;
double adding_time, runtime;
start = clock();
for(i=0; i<10; i++)
{
a=0.0;
tick =clock();
for(j=0; j<10000000; j++)
{
a+=1;
}
tock= clock();
adding_time = (double)(tick - tock)/CLOCKS_PER_SEC;
cout << "Computation time:" << adding_time << endl;
}
finish = clock();
runtime = (double)(finish - start)/CLOCKS_PER_SEC;
cout << "Total computation time:" << runtime << endl;
}
Your clock_t is apparently an unsigned 64-bit type.
You're taking tick - tock, where tock was measured after tick, so if there's any difference between the two at all, it's going to try to produce a negative number--but since it's an unsigned type, that's wrapping around to become something close to the largest number that can be represented in that type.
Obviously, you really want to use tock-tick instead.
let say tic = 2ms and tac is 4ms; so when you do tic-tac(2-4) that will generate a negative number obviously.. even if it given a positive number it wont be the real time. and also, the number it generate (which doesnt appear on my computer) is a big number, so, try to use the manipulator;
#include"iomanip"
cout << fixed << showpoint;
cout << setprecision(2);
it might work..
Here's a simple program I wrote to find all the non-decreasing-digit numbers of length <=L whose digits sum upto N. The code works fine, but when I try to clock the run time using clock() from ctime it shows a weird behaviour.
#include<iostream>
#include<vector>
#include<ctime>
using namespace std;
typedef long long int LL;
int Sum(LL S){
int sum=0;
for(;S;S/=10)
sum+=S%10;
return sum;
}
void Generate(LL S, int len, int N, int L, vector<LL> &V){
if(len<L)
for(int i=0;i<=9;++i)
if(i>=S%10)
Generate(S*10+i, len+1, N, L, V);
int sum = Sum(S);
if(sum!=N)
return;
else if(sum == N && len == L){
V.push_back(S);
cout << S << endl; //Line 4
return;
}
}
int main(){
int N,L;
vector<LL> V;
LL S;
cin >> N >> L;
clock_t start=clock(); //Line 1
Generate(S, 0, N, L, V);
//clock_t start=clock(); //Line 2
clock_t end = clock();
for(int i=0;i<V.size();++i)
cout << V[i] << " ";
cout << endl;
cout << "Run time: " << (double)(end-start)/CLOCKS_PER_SEC;
return 0;
}
I record the no. of clock ticks elapsed before calling the "Generate" function at //Line 1 and I do the same afterwards at //Line 2, the difference of which I believe should give me the no. of clock ticks elapsed in generating the required numbers.
But if I do so my function "Generate"'s processing somehow gets affected! It won't output the numbers to stdout(from //Line 4) and even if I pass a vector to store up the generated numbers, it won't store any!
However, if I use clock() at //Line 2 my output on stdout is fine and the referenced vector V gets filled up with the desired result. but clock() on //Line 2 is of no use.
What I fail to understand is How can a call to clock() affect some processing in 'Generate' function, unless of course I've some obscure Bug! or the clock() is not supposed to be used in this kind of recursive setup?
Please help me Debug this.
I get variable S is being used without being initialized in your code. Really you need to initialize it to 0 in the very beginning. From then on the behavior is quite unpredictable - thus from time to time you might get the correct answers, but I doubt it. It does not depend on the calls of clock().
I was trying to program a Timer class (unaware that boost had one), then when that wasn't working, I tried to just output the value of clock(), using this code:
#include <ctime>
#include <iostream>
int main()
{
for(int i = 0; i < 50; ++i)
{
std::cout << std::clock() << " ";
}
return 0;
}
When I run the program, I get a series of 0s. I have a similar experience when using boost thread sleep functions to spread out timing a little longer (although after a few seconds, it jumps from 0 to 10,000 and keeps outputting 10,000).
I'm running Gentoo Linux. Is this a platform thing? A C++ thing? What's going on?
Edit: Strangely the jump to 10000 comes after a number of seconds, not milliseconds. When I was sleeping my thread for a second at a time, it took five or six seconds to get to 10000. However, if I'm understanding correctly. The time the thread spends sleeping doesn't contribute towards the clock() count? (Which would make sense; why would it be executing clock cycles if it's sleeping?)
The clock() return value is specified in microseconds. But typical granularity of whatever low-level system call the clock() implementation uses is much lower. So it seems that on your system the granularity is 10ms. Also note that clock() does NOT measure real time - it measures CPU time used by the program. So the time flows when your program controls the CPU, and it freezes when your program is suspended - sleeping, for example.
std::clock's resolution is unspecified. In most cases, it's resolution is going to be about 10ms. Hence the jump.
Try the following:
#include <ctime>
#include <iostream>
int main()
{
for(int i = 0; i < 50; ++i)
{
for (int j = 0; j < 500; ++j )
{
std::cout << j << " ";
}
std::cout << std::endl;
std::cout << std::clock() << std::endl;
}
std::cout << std::endl;
return 0;
}
On my system, I see the return value of clock() staying at 0 until at some point it jumps to 10000. It stays at 10000 till the end. If I remove the std::cout in the inner loop, the return value of clock() stays at 0 all the way through. Looks like clock() returns values in increments of 10000 only.
If I change the inner loop to compute the square root of j and print the return value of sqrt(), the return value of clock() goes up to 50000, but is still increases in increments of 10000.
on my 64 bit operating system the CLOCKS_PER_SEC speed is 1000.and the values of clock comes in milliseconds. perfect timing will be extracted from the code below.
int main(){
clock_t a,b;
int c,d,e,f;
c=clock();
scanf("%d",&e);
d=clock();
f=(d-c)/CLOCKS_PER_SECOND;
printf("timing is %d seconds",f);/*for 64 bit operating system
CLOCKS_PER_SECOND is 1000*/
}