0

I was trying to calculate time elapsed during execution of my insertion sort function. So I did as follow. P.S. - function is running correctly and sorting all the numbers. Compiler - GCC Windows

    auto start = chrono::steady_clock::now();
    insertionSort(arr,1000);
    auto end = chrono::steady_clock::now();

    auto diff = start - end; // gives 0 
    auto diff = end - start ; // still zero

    cout << chrono::duration <double, nano> (diff).count() << " ns" << endl;

Firstly I tried with 100 input it gave me 0 ms then I changed it to ns it still gave zero. Then I increased my input to 1000. But sadly output is still zero. Is this correct way to write chrono? Someone suggested to try chrono::high_resolution_clock it still gave me 0ns.

Or any method you guys can suggest to calculate time of a function.

UPDATE - So I was looking for solution so I found that if do something like sometimes it gave result.

    auto start = chrono::high_resolution_clock::now();
    insertionSort(arr,1000);
    auto end = chrono::high_resolution_clock::now();

    auto diff = end - start;

    cout << chrono::duration <double, nano> (diff).count() << " ns" << endl;


    ofstream  write;
    write.open("sort.txt");
    if(write)
    {
        for(int i = 0 ; i < 1000 ; ++i)
        {
            write<<arr[i]<<endl;
        }
    }
    else{
        cout<<"Unable to open file.\n";
    }




I tried to write it in file now it giving me result if I choose nano second. But if I chose mili its still zero.

Does this mean insertion sort fast is exceptionally fast that C++ can't even measure it ?

Here is reproducable code.

#include<iostream>
#include<fstream>
#include<chrono>
using namespace std;

void readData();
void insertionSort(int * , int );
void readData()
{

    int arr[1000];
    ifstream read;
    read.open("sort.txt",ios::binary);
    if(read)
    {
        int i = 0;
        int temp;
        while(read>>temp)
        {
            arr[i] = temp;
            ++i;
        }
        read.close();

    }
    else{
        cout<<"Unable to open file.\n";
    }


    auto start = chrono::high_resolution_clock::now();
    insertionSort(arr,1000);
    auto end = chrono::high_resolution_clock::now();

    auto diff = end - start;

    cout << chrono::duration <double, nano> (diff).count() << " ns" << endl;

    ofstream  write;
    write.open("sort.txt");
    if(write)
    {
        for(int i = 0 ; i < 1000 ; ++i)
        {
            write<<arr[i]<<endl;
        }
    }
    else{
        cout<<"Unable to open file.\n";
    }

}
void insertionSort(int *arr , int size)
{
    for(int i = 1 ; i < size ; ++i)
    {
        int key = arr[i];
        int j = i -1 ;
        while(j>= 0 && arr[j]> key)
        {
            arr[j+1] = arr[j];
            j--;
        }
        arr[++j] = key;
    }

}
int main()
{
    readData();
    return 0;
}

  • 1
    Try `chrono::high_resolution_clock`. – tkausl Nov 28 '19 at 10:38
  • It might be something with optimizations. E.g., gcc at times computes everything at compile time eliminating any run time computations. You ought to use random numbers or something for performance testing. – ALX23z Nov 28 '19 at 10:45
  • @tkausl Tried but stil Zero :-( –  Nov 28 '19 at 10:45
  • 1
    `auto diff = start - end;` maybe `auto diff = end - start;` – Alexander Nov 28 '19 at 10:48
  • @ALX23z Can you explain in detail whatever you write in above comment. –  Nov 28 '19 at 10:49
  • @Alexander Still 0 . –  Nov 28 '19 at 10:50
  • try duration_cast(diff) – Saisai3396 Nov 28 '19 at 10:52
  • @M.M When I made them volatile it says. No operator for `auto diff = end - start;` . operand are volatile. –  Nov 28 '19 at 10:54
  • https://godbolt.org/z/xJwvK8 works. Probably insertionSort was optimized by the compiler. try in godbolt.org to check the assembly – Alexander Nov 28 '19 at 10:57
  • [This might be the issue](https://stackoverflow.com/questions/37786547/enforcing-statement-order-in-c), the sample program in [P0342](https://wg21.link/P0342) is quite similar to your code. The top answer has a workaround of sorts – M.M Nov 28 '19 at 10:58
  • You should be able to confirm by checking the generated assembly as to whether the timer checks have been reordered – M.M Nov 28 '19 at 11:03
  • Please post a minimal source code needed to reproduce the problem, at best include all the `#include`s and `int main()`. What is `arr`? What is `insertionSort`? What compiler are you using? What compiler options are you using? On what architecture are you running the program? Please post an [mcve](https://stackoverflow.com/help/minimal-reproducible-example). – KamilCuk Nov 28 '19 at 11:17
  • @KamilCuk I have updated post. Please check again. –  Nov 28 '19 at 11:20
  • I get: `error: aggregate ‘std::ifstream read’ has incomplete type and cannot be defined` and `error: ‘insertionSort’ was not declared in this scope` errors when compiling your code. Is there `#include #include #include using namespace std; void insertionSort(int *arr , int size); ` missing? `compiler GCC Windows` - Are you using gcc with mingw? – KamilCuk Nov 28 '19 at 11:22
  • @KamilCuk Ofc . they are supposed to be added. This much is obvious thing. >.< But still for your sake I have added everything. –  Nov 28 '19 at 11:24
  • On Windows, you can use `GetSystemTimeAsPreciseFileTime` to get 100 ns resolution. – VLL Nov 28 '19 at 11:25
  • What is the value of `i` after reading the elements from the file? Are you sure you are reading 1000 elements? How much time it takes to sort `srand(time(0)); for (auto& i: arr) { i = rand(); }`? Can you just check if something like (not working, it's a idea) `cout << chrono::high_resolution_clock::now(); std::this_thread::sleep_for(std::chrono::seconds(1)); cout << chrono::high_resolution_clock::now();` returns different values? There is most probably something you are not showing and missing. Are you sure you are running proper binary? Are you sure you are compiling right? – KamilCuk Nov 28 '19 at 11:29
  • Yes everything works fine. I think desktop is exceptionally fast in sorting. –  Nov 28 '19 at 11:37
  • I thought you generate numbers randomly. If you read sorted file then insertionSort will take little to no time. Also, your PC might have a clock with low resolution, and if all 1000 elements happen to be inside the L3 cache at the start and be sorted then the whole sorting will take only a few K cycles which might be below the resolution you have. – ALX23z Nov 28 '19 at 11:55

2 Answers2

2

Use correct template argument to mark that you want milliseconds:

std::chrono::duration<double, std::milli> diff = end - start ; // still zero
cout << diff.count() << " ms" << endl;

If it is still zero, maybe your operation is so fast that it take less than 1 millisecond to finish? Sorting array o 1000 elements is quite fast these days. Make it bigger or repeat several times.

For 10000 elems it is starting to return some values greater than 0. What is your environment? Maybe in your case high_resolution_clock is not available... Time measurements with High_resolution_clock not working as intended

BTW I also have 0 as a result 50% of the time.

bialy
  • 193
  • 2
  • 14
0

As you are on Windows, you can use QueryPerformanceFrequency(). It will give you the number of ticks your system does in one second. So, you can use it to calculate the actual accuracy of your system clock:

#include <Windows.h>

int main() {
    LARGE_INTEGER freq;
    QueryPerformanceFrequency(&freq);
    std::cout << 1.e9 / freq.QuadPart << "ns accuracy" << std::endl;
}

Everything attempt to measure something faster than this, will result in 0. Any attempt to measure something that is roughly in the same magnitude, will be inaccurate.

For example, on my system above code prints 100ns accuracy. If I run your code, it prints 1100ns most of the time, sometimes 1200ns, sometimes 1000ns. Note how this is always a multiple of the accuracy.

One common way to overcome this is to run the code in question multiple times and take the average, like so:

constexpr int runs = 2000;

auto start = std::chrono::steady_clock::now();
for (int i = 0; i < runs; ++i)
    insertionSort(arr,1000);
auto end = std::chrono::steady_clock::now();

auto diff = end - start;

cout << std::chrono::duration <double, std::nano> (diff).count() / runs << " ns" << endl;

On my system this prints 1016.7ns.

sebrockm
  • 5,733
  • 2
  • 16
  • 39