2012-06-13 13 views
5

Mam dwa powiązane pytania, jeden ogólny i jeden dotyczący projektu, nad którym pracuję.pętle, projektowanie i wydajność funkcji: dwa pytania

  1. Generalnie jeśli mam pętlę z dużą ilością powtórzeń (mln) z niektórymi częściami kodu są realizowane pod pewnymi warunkami, to jest lepsze (bardziej wydajne) mieć jedną pętlę z wielu instrukcji warunkowych lub wieloma pętlami bez im. Na przykład.

Przykład 1:

while (something()) 
{ 
    // some common code 
    if (condition_a) 
     // some code 
    if (condition_b) 
     // some code 
    // some more common code 
} 

Przykład 2:

if (condition_a && condition_b) 
{ 
    while (something()) 
    { 
     // some common and specific code 
    } 
} 
else if (condition_a) 
    while (something()) //.. 
else if (condition_b) 
    // Another loop 
else //... 

Wydaje się, że w przykładzie 2 skutkowałoby bardziej wydajnego kodu kosztem redundancji, ponieważ warunki są sprawdzane tylko raz zamiast milion razy. Jeśli wspólny kod jest ogromny lub istnieje wiele możliwych warunków, wydaje się to bardzo zbędne.

  1. Teraz mój konkretny problem. Mam funkcję, która odczytuje punkty z pliku i wstawia je do struktury danych. Wygląda to mniej więcej tak:

    while (reader-> read_point) { // robić pewne rzeczy // punkt wstawienia }

Problemem jest to, że istnieje kilka funkcji do czytania punkt, który powinien być stosowany na podstawie kryteriów podanych przez użytkownika. Na przykład read_point_inside_circle(), read_point_inside_rectangle() itp.

Idealnie chciałbym użyć wskaźnika funkcji do decydowania o poprawnej funkcji wcześniej, jednak nie sądzę, że jest to możliwe, ponieważ czytnik jest instancją klasy Reader (jeśli to możliwe, to rozwiąże wszystkie moje problemy).

W tej sytuacji jest lepiej, jeśli mam wiele pętli, które różnią się tylko warunkiem lub powinienem użyć wielu instrukcji if, aby uniknąć nadmiarowego kodu, np.

for(;;) 
{ 
    if (read_every_point) 
     if(!reader->read_point()) 
      break; 
    else if (read_inside_circle) 
     if(!reader->read_inside_circle()) 
      break; 
    else if // ... 
} 
+2

Wątpię, aby pierwsze miało jakikolwiek wpływ na każdy współczesny kompilator. Poszedłbym z tym, co jest bardziej czytelne i pozwoliłbym, aby kompilator zoptymalizował to dla mnie. – amit

Odpowiedz

2

Idealnie chciałbym użyć wskaźnika funkcji decyduje o prawidłowej funkcji uprzednich, jednak nie sądzę, że to możliwe, ponieważ czytelnik jest instancją klasy Reader (jeśli jest to możliwe w jakiś sposób, że rozwiąże wszystkie moje problemy).

Można użyć wskaźników funkcji członek na to, zakładając, że wszystkie swoje czytać funkcje mają ten sam podpis:

typedef void (Reader::*read_fun_t)(); 
read_fun_t read_fun = &Reader::read_point; 
// or 
read_fun_t read_fun = &Reader::read_inside_circle; 

... 

(reader->*read_fun)(); 

lub jeśli nie czujesz się przytulne z nimi, po prostu stworzyć swój własne bezpłatne funkcje, które zawijają wywołania metody:

void read_point(Reader* reader){ reader->read_point(); } 
void read_inside_circle(Reader* reader){ reader->read_inside_circle(); } 

i zamiast tego użyj zwykłych wskaźników funkcyjnych.

+0

To rzeczywiście działało, ale niestety moje funkcje przyjmują różne parametry: read_point(), inside_circle (F64 center_x, F64 center_y, F64 radius), inside_rectangle (F64 min_x, F64 max_x, ...). Jakikolwiek sposób obejścia tego? – jaho

+0

@Marian: Jeśli parametry są _loop niezmiennicze_, to będą działać obiekty i bindery wyższego poziomu. Poszukaj 'std | boost :: function' i' std | boost :: bind'. –

3

Aby odpowiedzieć na konkretne pytanie: czas potrzebny na odczytanie pliku będzie przytłoczyć czas spędzony w urządzeniu if/else. Napisz, co jest bardziej czytelne. Zwykle jest to bardziej efektywne i nie optymalizuj go, dopóki nie udowodnisz, że jest to wąskie gardło.

Aby odpowiedzieć na ogólne pytanie: zależy od wielu rzeczy, a nowoczesne kompilatory doskonale radzą sobie z robieniem rzeczy w sposób niezależny od intuicji. Więc jest to dyskusja teoretyczna, dopóki nie będziesz pracował na kodzie określonego kompilatora i architektury.