onsdag 21 november 2018

Prestandatest på morgonen (C++)

Jag tenderar att fundera vilken typ av loopar som man ska använda, och om optimeringar gör någon nytta. Här har vi några exempel på hur loopar, och olika optimeringar kan fungera.

I det här exemplet så funderade jag dels på hur effektiva for-each-loopar är jämfört med vanliga loopar, och dels så funderade jag på hur effektivt min kompilator optimerade i kombination med hur min processor optimerar i sig.

Jag har någon slags stationär dator som är rätt snabb (bra specifikationer va?).

Här är koden.




#include <iostream>
#include <chrono>
#include <string>
#include <random>



using namespace std;

chrono::high_resolution_clock::time_point start;

void tic() {
    start = std::chrono::high_resolution_clock::now();
}

double toc() {
    auto finish = std::chrono::high_resolution_clock::now();
    std::chrono::duration duration(finish- start);
    return duration.count();
}

int main(int argc, char **argv) {
    vector a(100000000);
    vector b;
    b.reserve(a.size());

    cout << endl;
    cout << "generating numbers " << endl;

    for (auto &f: a) {
        f = (float)(rand()%10000) / 10000. - .5;
    }

    cout << "random generation finished... numbers like:" << endl;

    for (int i = 0 ;i < 10; ++i) {
        cout << a[i] << " ";
    }
    cout << endl;

    tic();
    for (auto f: a) {
        b.push_back(f * (f>0.));
    }
    cout << "multiplications for each " << toc() << endl;


    b.clear();
    b.reserve(a.size());

    tic();
    for (int i = 0; i < a.size(); ++i) {
        auto f = a[i];
        b.push_back(f*(f > 0));
    }
    cout << "multiplications regular-for: " << toc() << endl;

    b.clear();

    b.resize(a.size());

    tic();
    for (int i = 0; i < a.size(); ++i) {
        auto f = a[i];
        b[i] = f * (f > 0);
    }
    cout << "indexes multiplications regular-for: " << toc() << endl;

    

    b.clear();
    b.resize(a.size());

    tic();
    for (int i = 0; i < a.size(); ++i) {
        b[i] = ReLu(a[i]);
    }
    cout << "indexes inline function regular-for: " << toc() << endl;


    b.clear();
    b.reserve(a.size());

    tic();
    for (auto f: a) {
        if (f > 0) {
            b.push_back(f);
        }
        else {
            b.push_back(0);
        }
    }

    cout << "if statements for each " << toc() << endl;

    b.clear();
    b.reserve(a.size());

    tic();
    for (int i = 0; i < a.size(); ++i) {
        auto f = a[i];
        if (f > 0) {
            b.push_back(f);
        }
        else {
            b.push_back(0);
        }
    }

    cout << "if-statements regular for " << toc() << endl;


    b.clear();
    b.resize(a.size());

    tic();
    for (int i = 0; i < a.size(); ++i) {
        auto f = a[i];
        if (f > 0) {
            b[i] = f;
        }
        else {
            b[i] = 0;
        }
    }

    cout << "indexes if-statements regular for " << toc() << endl;
}



Resultatet blev som följande: Utan några optimeringar givna till g++ får jag följande resultat.
generating numbers 
random generation finished... numbers like:
0.4383 -0.4114 -0.2223 0.1915 0.2793 0.3335 0.0386 -0.4508 0.1649 -0.3579 
multiplications for each 4.21264
multiplications regular-for: 2.96703
indexes multiplications regular-for: 1.37391
indexes inline function regular-for: 1.43445

if statements for each 3.5061
if-statements regular for 3.10215
indexes if-statements regular for 1.64089



Med optimeringar (-O3) får jag följande resultat
generating numbers 
random generation finished... numbers like:
0.4383 -0.4114 -0.2223 0.1915 0.2793 0.3335 0.0386 -0.4508 0.1649 -0.3579 
multiplications for each 0.27903
multiplications regular-for: 0.158509
indexes multiplications regular-for: 0.15735
indexes inline function regular-for: 0.161381


if statements for each 0.572224
if-statements regular for 0.587925
indexes if-statements regular for 0.150071


Så vad kan man dra för slutsatser? Jag tar med mig följande tumregler.
1: Ska det gå snabbt: Se till att använda kompilatorns inbyggda optimeringar. (Det går ungefär tio gånger snabbare i det här exemplet).
2: Det går oftast snabbare att använda en vanlig indexerad for-loop än att använda en for-each-loop (om prestanda är väldigt väldigt viktigt)
3: Egna optimeringar kan fungera, som exempelvis när man som ovan multiplicerar med en siffra för att undvika en if-sats, men inte alls i samma grad som den inbyggda kompilatorn. Ska man mikrooptimera så är det viktigt att testa koden för att hitta det som fungerar snabbast på den datorn där koden ska köras.
4: Inline-funktioner drar ner prestandan lite (i det här fallet runt 5%)


Not: Kom alltid ihåg att det finns saker som gör att det inte blir som man tror att det är som: Kompilatorn optimerar på ett sätt som man inte vet om, cache-missar och branch-prediction (varje grej förtjänar några googlingar på internettet.)





tisdag 24 november 2015

Fix audacity startup bug - on ubuntu 15.10

For a while ago audacity stopped working. It hung on startup, and i tried to fix the problem in a lot of different ways.

I searched for the problem online and realised that there was some problem with the version that was distributed with ubuntu, that it was built to the wrong version of wx-widgets.

One obvious solution (for a linux user) was to try to compile the application from source. But for some reason i ended up with strange compilation errors. I tried for the code for version 2.0.6, 2.1.1 or 2.1.2 but all ended with some dependencies missing that was not possible to install from the ubuntu repositories.

The final solution that i found thas this repository that i found online. This is a newer compiled version than the one that i tried

sudo add-apt-repository ppa:ubuntuhandbook1/audacity
sudo apt-get update
sudo apt-get install audacity

...



Then audacity finaly started...