Utrata wydajności. Dlaczego?

0

Mam taki kod:

// (...)
struct i_BMU {
    int x,y, x2,y2;     // współrzędne pierwszego i drugiego BMU
};
typedef list<double>    vec;
list<char>  Decision;   // decyzja kojarzona z każdym neuronem
list<vec> xx;       // lista wektorow wejsciowych (probki uczace)

string getClusterNo(int x, int y) {
    string  out;
    char        txt[5];
    if (clusters[x][y] > 0) {
        sprintf(txt, "%d", clusters[x][y]);
        out.assign(txt);
    }
    else
        out.assign("?");
    return out;
}

i_BMU Run(vec x) {
// "uruchamia" sieć i zwraca nr zwycięzcy
    double  min = 1e10, cur_d;
    int win_x=-1,win_y=-1;      // neuron zwyciezca (BMU = Best Matching Unit)
    int win2_x=-1,win2_y=-1;    // neuron, ktory jest kolejnym BMU
    for (int xp=0; xp<mapsize_x; xp++) {
        for (int yp=0; yp<mapsize_y; yp++) {
            cur_d = neurony[xp][yp].d(x);           // oblicz odleglosc wektora x od wektora W neuronu
            if (min > cur_d)    {
                min = cur_d;
                win_x = xp;     win_y = yp;
            }
        }
    }
    // szukanie 2nd BMU wśród sąsiadów BMU
    min = 1e10;
    for (int xp=-1; xp<=1; xp++)
        for (int yp=-1; yp<=1; yp++) {
            if ((xp==0 && yp==0) || win_x+xp < 0 || win_x+xp >= mapsize_x || win_y+yp < 0 || win_y+yp >= mapsize_y)
                continue;
            cur_d = neurony[win_x+xp][win_y+yp].d(x);   // oblicz odleglosc wektora x od wektora W neuronu
            if (min > cur_d)    {
                min = cur_d;
                win2_x = win_x+xp;      win2_y = win_y+yp;
            }
        }
    return (i_BMU){win_x,win_y, win2_x,win2_y};
}

// (...)
int main(...) {
// (....)
else if (backtest) {
    LoadNet();
    GetInputDataTeach();
    cout << endl << rpad("Generating backtest..."," ",40) << flush;
    plik_out.assign("backtest/");;
    plik_out.append("file.btst");
    FILE *fo = fopen(plik_out.c_str(), "wb");
    sprintf(c_txt,"%d %d ",mainTF, time1st);
    fputs(c_txt, fo);

//--- zapisz odpowiedzi sieci na poszczególne dane wejściowe
    list<vec>::iterator xit=xx.begin();
    char decision[2];
    list<char>::iterator        Dit;
    con_STO();   // zapamiętanie stanu konsoli używając kodów konsoli
    for (no=0; xit!=xx.end(); ++xit, no++) { // **************************
        if (no % 9 == 0) {
            con_RCL();  // odtworzenie stanu konsoli
            sprintf(c_txt, "%.2f%% ", (double)no/P*100);
            cout << progress_signs[no % 4] << "  " << c_txt << flush;       // pokaż, że pracuje
        }
        i_BMU winner = Run(*xit);   // przetworzenie wektora
        sprintf(c_txt, "%s", getClusterNo(winner.x,winner.y).c_str());
        fputs(c_txt, fo);

        Dit = Decision.begin();
        advance(Dit, mapsize_x*winner.y + winner.x);
        sprintf(decision, "%c", *Dit);
        fputs(decision, fo);
        fputs("\n", fo);
    }
    fclose(fo);
    cout << "OK" << endl;
}
} // main

i nie wiem, dlaczego pętla oznaczona gwiazdkami (****) szybko zaczyna zwalniać, aż w końcu wlecze się okropnie.
Lista xx zawiera od 2000 do 4000 elementów. Proszę o jakąś radę.

0

Jak już tak mieszasz C i C++, to mogłeś wypisywać na konsole przez printf.
Ja bym stawiał na tą funkcję con_RCL, ale nie wiem jak wygląda jej kod. Pokaż, albo powiedz co i za pomocą czego tam operujesz ;).

0

To nie ta funkcja :)

void con_RCL() {
    printf("\0338");
}

Nawet, gdy wcześniej jej nie było, to pętla zwalniała.

0

Czy może to być spowodowane tym, że do pliku fo jest cały czas zapisywane i ani razu nie ma flush'a?
Początkowo myślałem, że to wina tych operacji na liście Decision i funkcji advance. Usunąłem to, ale nadal zwalania.


Eeeee :-/ Flush też nie pomógł.

0

Przyjrzyj się operacji modulo 9, szczególnie że no ciągle rośnie.

Reszta operacji wygląda na niezależną od no, tylko od xit - może wartości w tej liście też są rosnące i operacje na nich zajmują więcej czasu im dalej?

0

To też nie to. Nawet, jak wyrzucę cały ten if z modulo, to zwalnia.
Wartości w xx na pewno nie mają znaczenia. Są rozmieszczone w miarę równomiernie.

0

A to jeszcze ten kod jest w pętli :) nie zauważyłem.

cout << progress_signs[no % 4] << " " << c_txt << flush;
To jako pierwsze może trochę zwalniać przy tylu obiektach. Iostream jest wolniejsze, bo dużo rzeczy sprawdza za nim coś zrobi. Co to jest progress_signs ? Tablica obiektów jakieś klasy ?

Operacje dyskowe są najkosztowniejsze. Najlepiej by było zapisać jak najwięcej w jednym wywołaniu funkcji, binarnie.

0

char progress_signs[4] = {'/', '-', '\\', '|'};
Odkryłem, że po jakimś czasie długo trwa wykonaniei_BMU winner = Run(*xit);

0

char progress_signs[4] = {'/', '-', '\', '|'};

To spokojnie tamtą instrukcje możesz zamienić na
printf('%c %s", progress_signs[no % 4], c_txt);
%s jeżeli c_txt to tablica char

Odkryłem, że po jakimś czasie długo trwa wykonanie

Włącz debugger i zobacz jakie wartości przyjmują zmienne kolejnych *xit.

0

W innym miejscu mam kod:

vec get_X(int nr) {
    list<vec>::iterator it = xx.begin();
    advance(it, nr);
    return *it;
}
bool juz_wylosowany(int n) {
    for (list<int>::iterator it=wylosowane_x.begin(); it!=wylosowane_x.end(); ++it) {
        if (*it == n)   return true;
    }
    return false;
}
vec LosujX() {
    int nr;
    if (wylosowane_x.size() == (int)((100-test_perc)*P/100))        wylosowane_x.clear();
    while(true) {
        nr = rand() % (int)((100-test_perc)*P/100);
        if (!juz_wylosowany(nr))    break;
    }
    wylosowane_x.push_back(nr);
    vec x = get_X(nr);
    wylosowany_x = nr;
    return x;
}

// (...)

for (int i=0; i<epok; i++, k++) {
    cout << " Processing epoch " << lpad(i+1," ",(int)ceil(log1p(epok)/log(10.0))) << " of " << epok << "   ";
    con_STO();  // zapamiętaj pozycję kursora (m.in.)
    for (int Pi=0; Pi<P; Pi++) {
        // -- wskaznik pracy
        if (Pi % 9 == 0) {
            con_RCL();
            sprintf(c_txt, "%.1f%% ", (double)(Pi+1)/P*100);
            cout << progress_signs[Pi % 4] << " " << c_txt << flush;
        }
        vec dajx = LosujX();
        i_BMU winner = Run(dajx);

        // podaj wspolrzedne zwyciezcy na mapie
        winner_x = winner.x;
        winner_y = winner.y;
        Change_W();
        Change_P();
    }
    con_RCL(); cout << "            ";      // zamaż wskaźnik pracy

//  CalculateUmatrix(0);
    cout << endl;
}
    cout << "Teaching done.\n\n";

i on nie zwalnia, choć kilka razy przechodzi przed wszystkie wektory z xx, ale w losowej kolejności.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0