1

I have implemented a C++ code on a Zedboard. It compiles and runs perfectly, but now i would like to check the performances in order to optimize some functions. I have checked some threads here (Testing the performance of a C++ app) and here (Timer function to provide time in nano seconds using C++), but i don't really understand how to apply it mon code ...

To make things clear : I'm not good at C++, I have never really learned the language formally but only used it several times with specific libraries. I am not even the author of the code I'm using (given to me by the professors).

My goal here is to check the time spent on each functions and globally when I execute the program on the Zedboard. The code is on Linux image on an SD card, the board booting on this image. It is using the opencv library for anImage processing application. I'm using g++ 4.6.3 as a compiler.

Thanks in advance for your answer !

  • 1
    You need to define a timer, then get the time before and after you execute your function. The difference is your elapsed function time. – turoni Jun 08 '17 at 10:44
  • Valentin, are you still on the ARM side (PS) of Zedboard's Zynq SoC? It should work as any other ARM Cortex-A9 or other ARM Cortex-A of the epoch of ARMv7. Please, tell us what is your compiler and its version (version of Xilinx tools you use to cross-compile the code; how did you compile the code). – osgx Jun 08 '17 at 16:19
  • @osgx I made the Zedboard boot on Linaro Ubuntu installed on a SD card, so I guess I'm working on the ARM and not the FPGA part. I compile in Terminal using `g++ -4.6` in my Makefile. – Valentin Dubois Jun 12 '17 at 16:15

2 Answers2

0

You can create a simple timer class using the <chrono> header. Something like this:

class Timer
{
public:
    using clock = std::chrono::steady_clock;

    void clear() { start(); tse = tsb; }
    void start() { tsb = clock::now(); }
    void stop()  { tse = clock::now(); }

    auto nsecs() const
    {
        using namespace std::chrono;
        return duration_cast<nanoseconds>(tse - tsb).count();
    }

    double usecs() const { return double(nsecs()) / 1000.0; }
    double msecs() const { return double(nsecs()) / 1000000.0; }
    double  secs() const { return double(nsecs()) / 1000000000.0; }

    friend std::ostream& operator<<(std::ostream& o, Timer const& timer)
    {
        return o << timer.secs();
    }

private:
    clock::time_point tsb;
    clock::time_point tse;
};

You can use it simply like this:

Timer timer;

timer.start();

// do some stuff
std::this_thread::sleep_for(std::chrono::milliseconds(600));

timer.stop();

std::cout << timer << " seconds" << '\n';

EDIT: On POSIX systems you can use clock_gettime() if <chrono> is not available:

class Timer
{
public:
    void clear() { start(); tse = tsb; }
    void start() { clock_gettime(CLOCK_MONOTONIC, &tsb); }
    void stop() { clock_gettime(CLOCK_MONOTONIC, &tse); }

    long nsecs() const
    {
        long b = (tsb.tv_sec * 1000000000) + tsb.tv_nsec;
        long e = (tse.tv_sec * 1000000000) + tse.tv_nsec;
        return e - b;
    }

    double usecs() const { return double(nsecs()) / 1000.0; }
    double msecs() const { return double(nsecs()) / 1000000.0; }
    double  secs() const { return double(nsecs()) / 1000000000.0; }

    friend std::ostream& operator<<(std::ostream& o, Timer const& timer)
    {
        return o << timer.secs();
    }

private:
    timespec tsb;
    timespec tse;
};
Galik
  • 42,526
  • 3
  • 76
  • 100
  • Thank you for your answer, i will try this and post the result. I suppose i must download this header somewhere for it to work ? – Valentin Dubois Jun 08 '17 at 13:34
  • @ValentinDubois No `` is part of standard `C++`. – Galik Jun 08 '17 at 13:44
  • Unfortunately the header is not included in my version. I'm thinking about using clock_gettime() from . – Valentin Dubois Jun 08 '17 at 15:26
  • @ValentinDubois Sure, I use that too with `CLOCK_MONOTONIC`. – Galik Jun 08 '17 at 15:37
  • @ValentinDubois I added another example to my answer using `clock_gettime()`. – Galik Jun 08 '17 at 15:41
  • Guess in my main I should also replace the `std::chrono::milliseconds(600)` ? – Valentin Dubois Jun 08 '17 at 16:11
  • Unfortunately apart from the point i mentionned above I got a lot of errors from your struct definition. More specifically I got `ISO C++ forbids declaration of "nsecs" with no type [-fpermissive]` and other errors related to `int Timer::nesecs() const`. – Valentin Dubois Jun 08 '17 at 16:14
  • @ValentinDubois Ah you seem to not have `C++11`. I changes the `auto` return types to `long` but you may be able to enable `c++11` on your compiler by adding `-std=c++11` to the compiler command. – Galik Jun 08 '17 at 17:03
  • To test the timer in the main thread you could use `usleep()` http://man7.org/linux/man-pages/man3/usleep.3.html – Galik Jun 08 '17 at 17:08
  • One of my teachers told me to do a simple check with `gettimeofday()` and it works, but i guess there are also many processes from Ubuntu which are part of this timer, so the value is not exactly equal to the time spent on my functions. – Valentin Dubois Jun 12 '17 at 13:13
  • I'll try again what you suggest, and you said that I could use `usleep` instead of `std::this_thread::sleep_for(std::chrono::milliseconds(600))` ? Cause I still can't use the `` – Valentin Dubois Jun 12 '17 at 13:14
  • @ValentinDubois You don't need the `std::this_thread::sleep_for()` I just put that in to prove the timer keeps proper time. Substitute the code you want to time instead of the `std::this_thread::sleep_for()`. – Galik Jun 12 '17 at 13:50
  • Oh yeah my bad i just missed the point entirely ! I still can't figure out how to enable C++11 on my compiler tho. In my Makefile i call `g++-4.6` to compile, and if i try to add or replace anything with what you said it still can't find it. – Valentin Dubois Jun 12 '17 at 15:48
  • @ValentinDubois That version is quite old and doesn't have full `c++11` support. You ca try with `g++-4.6 -std=c++0x`. – Galik Jun 12 '17 at 16:00
  • Still doesn't work sadly. Is there any way to change the code, or even to install the components the compiler needs ? The thing is that I'm working directly on the ZedBoard which is booting on an SD card with Linaro Ubuntu. The g++ compiler included may be quite outdated. – Valentin Dubois Jun 12 '17 at 16:11
  • @ValentinDubois Just use the second version I posted. Forget about ``. Does the second version work for you? – Galik Jun 12 '17 at 16:19
  • I'm talking about the second version from the beginning, the one without `` ^^ – Valentin Dubois Jun 12 '17 at 16:29
  • I changed the `auto` types for `long` and it worked. I don't think I could have more precise results so I will keep this solution. Thank you a lot for your help ! – Valentin Dubois Jun 15 '17 at 13:55
0

I have found an unsatisfying solution, but I thought I could still post it if it can be of any help.

I made use of the gettimeofday() function defined in <time.h>. It's pretty simple to use but has flaws which i may explain later :

timeval t1, t2;
gettimeofday(&t1, NULL);
/* some function */
gettimeofday(&t2, NULL);
double time;
time = (t2.tv_sec - t1.tv_sec)*1000.0 + (t2.tv_usec - t1.tv_usec)/1000.0; 
cout << time << "ms" << "\n";

This way I measure a time in milliseconds and display it on screen. However gettimeofday is not based on the computer clock but on the actual time. To be clear, the time elapsed between 2 calls contains indeed my function, but also all the processes running in the background on Ubuntu. In other terms, this does not give me the precise time taken by my function to execute, but a value slightly higher.

EDIT : I found another solution again, using the clock() function from <time.h> and the result seems correct in comparison of the ones i get with the previous method. Unfortunately, the precision is not enough since it gives a number in seconds with only 3 digits.

  • There is also timer for CPU time in Unix/Linux/POSIX world (not ["wall time"](https://en.wikipedia.org/wiki/Wall-clock_time) as with `gettimeofday`, or clock hanging on the wall of your room), measured by kernel and reported with several syscalls like [getrusage](http://man7.org/linux/man-pages/man2/getrusage.2.html) with RUSAGE_SELF and `ru_utime` field. But this clock is often measured in large steps like 1 ms or 10 ms, and it can't be used to measure sub-ms function timing. – osgx Jun 12 '17 at 17:02
  • @osgx Thanks for your answer ! Would it be possible for you to give me a quick example of how I'm supposed to use it ? – Valentin Dubois Jun 13 '17 at 13:47
  • Valentin, like in stackoverflow.com/questions/10509660/ but with ru_utime. This also will give you low-resolution result, 2 or 3 digits after point (10 ms - 1 ms). Use longer parts of program to measure, or use gettimeofday and do several measurements. When your program have no external I/O or waiting syscalls, gettimeofday will return correct and precise value most times. – osgx Jun 13 '17 at 14:11