Hi,
as you’ve already know I’ve developed a small library to asset performance of code. The aim of this library is to objectively report how long a function last. It would help you choose an implementation of an algorithm for example.
To illustrate that I will take fibonnaci function as an example. I know at least two implementations of this function, one functional and an another iterative. The strong point of the functional version is that it is easier to implement and to understand as contrary to the iterative. But for large number I suspect the functional version to be very slow but I can not say to what point.
int __inline__ fibonacci(int n) { if (n < 3) return 1; return fibonacci(n - 1) + fibonacci(n - 2); } int __inline__ fibonacciOptim(int n) { int first = 0, second = 1, next, c; for (c = 0; c < n; c++) { if (c <= 1) next = c; else { next = first + second; first = second; second = next; } } return next; }
It is now time to use the Timing Library
First clone the repository
git clone https://github.com/fflayol/timingperf.git cd timingperf
Then create a main to set values of the library and add the different version of your code:
#include "performancetiming.hpp" int __inline__ fibonacci(int n) { if (n < 3) return 1; return fibonacci(n - 1) + fibonacci(n - 2); } int __inline__ fibonacciOptim(int n) { int first = 0, second = 1, next, c; for (c = 0; c < n; c++) { if (c <= 1) next = c; else { next = first + second; first = second; second = next; } } return next; } int main(int argc, char **argv) { timing::addFunction("FIB", fibonacci); timing::addFunction("FIB-OPTIM", fibonacciOptim); timing::setTimingFunction(2); timing::setNumberExecution(1000000); timing::Execute(15); timing::CalcResult(); }
The result gives:
fflayol@local:~/Perso/timingperf$ ./ex1.out Begin [ FIB ] End [ FIB ] Begin [ FIB-OPTIM ] End [ FIB-OPTIM ] Begin [ FIB ] End [ FIB ] Begin [ FIB-OPTIM ] End [ FIB-OPTIM ]
fflayol@local:~/Perso/timingperf$ ./ex1.out Begin [ FIB ] End [ FIB ] Begin [ FIB-OPTIM ] End [ FIB-OPTIM ] Begin [ FIB ] End [ FIB ] Begin [ FIB-OPTIM ] End [ FIB-OPTIM ]
|--------------------------------------------------------------------| |---Name--------Timer-----Duration------Diff-------Min-------Diff----| | | | | | | | | FIB | RDTSC | 6326 | 100 %| 5906| 100 % | |FIB-OPTIM | RDTSC | 158 | 4003.8 %| 137| 4310.95 % | | FIB | RDTSCP | 6354 | 99.5593 %| 5916| 99.831 % | |FIB-OPTIM | RDTSCP | 208 | 3041.35 %| 180| 3281.11 % |
The difference here is very important because our optimization version is 40x faster 🙂
An another nice feature is to check compiler optimization quality. You can change the compiler optimization with -O option followed by a numer (0 to 3, the higher the better).
g++ ex1.cpp -std=c++11 -o ex1.out ; g++ -O3 ex1.cpp -std=c++11 -o ex1-opt.out
|---Name------Timer---Duration------Diff------Min------Diff-
|| FIB | RDTSC | 2253 | 100 % | 2080| 100 % |
|FIB-OPTIM | RDTSC | 31 | 7267.74 % | 24 | 8666.67 % |
| FIB | RDTSCP| 2304 | 97.7865 % | 2108| 98.6717 % |
|FIB-OPTIM | RDTSCP| 51 | 4417.65 % | 45 | 4622.22 % | |------------------------------------------------------------|
As a result both version are faster (3x for the functional version and 5x with the iterative version). As a result the difference of performance is still higher.