Autor Wątek: pętla vs manual  (Przeczytany 4740 razy)

Offline Kosai_

  • Użytkownik
    • devlog

# Lipiec 16, 2008, 16:15:10
tak się zastanawiałem ostatnio...
bardzo często widzę kod w stylu

float v[3], p[3];
// jakieś tam działania...
v[0] = p[0];
v[1] = p[1];
v[2] = p[2];

czym on się różni, pod względem wydajności z takim:

float v[3], p[3];
// jakieś tam działania...
for(int i = 0; i < 3; i++) v[i] = p[i];

? takiej konstrukcji nie zaobserwowałem jeszcze w różnych projektach... jeśli nie różni się pod względem wydajności to dlaczego koderzy wybierają dłuższy sposób do napisania? czytelniejszy może jest?...

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline SiMet

  • Użytkownik

# Lipiec 16, 2008, 16:21:23
Jak to nie widzisz roznicy :D
Jak zmienisz liczbe elementow na 100 (albo nawet na 5), bo trzeba rozszerzyc projekt to widac roznice nie?
Zreszta kod ktory wg Ciebie jest krotszy ma wiecej znakow niz ten z petla
Raczej jest to rozwniez bardziej czytlene, ze przechodzimy po wszystkich elementach od 0 do 2

Offline Kosai_

  • Użytkownik
    • devlog

# Lipiec 16, 2008, 16:24:57
właśnie ja stosuję pętlę i się dziwię pierwszemu sposobowi...
poza tym pytam się czy wydajność jest różna

Offline yarpen

  • Użytkownik

# Lipiec 16, 2008, 16:25:37
Petla bedzie wolniejsza.

Offline benethorpl

  • Użytkownik

# Lipiec 16, 2008, 16:32:13
pętla musi być nieco wolniesza bo oprócz samych przypisań zawiera kontrolę warunku pętli i skok. Narzut pętli jest liniowy, a koderzy którym bardzo zależy na wydajności wybierają sposób pierwszy, bo od minimalnego narzutu liniowego wolą narzut zerowy kosztem tego, że się naklepią zanim wykonają tą ppętlę ręcznie:P

Offline counterClockWise

  • Użytkownik

# Lipiec 16, 2008, 16:34:37
pętla musi być nieco wolniesza bo oprócz samych przypisań zawiera kontrolę warunku pętli i skok. Narzut pętli jest liniowy, a koderzy którym bardzo zależy na wydajności wybierają sposób pierwszy, bo od minimalnego narzutu liniowego wolą narzut zerowy kosztem tego, że się naklepią zanim wykonają tą ppętlę ręcznie:P

A niektórzy napiszą krótką pętle, dobry kompilator mu ją rozwinie i też nie będą mieli narzutu ;)

Offline Kosz85

  • Użytkownik

# Lipiec 16, 2008, 16:35:13
Jak nie widzisz różnicy, to jeszcze trochę nauki przed tobą :)
Po drugie swojej wersji pętli też nie uświadczysz u lepszych koderów.
++i jest szybsze od i++, więc pętla według lepszych koderów będzie wyglądać tak:
Kod: (c) [Zaznacz]
float v[3], p[3];
for(int i = 0; i < 3; ++i) v[i] = p[i];
Niby zerowa różnica, ale przy wyłączonej optymalizacji jednak jest. Bo oczywiście można się kłócić, że kompilator to zoptymalizuje, ale tak naprawdę, nigdy nie wiadomo.

Po trzecie wersja bez pętli będzie szybsza bo:
- nie ma dodatkowej zmiennej i, którą trzeba położyć na stosie, inkrementować itd.
- nie ma porównania, które trochę cykli zjada :)
- nie ma skoków warunkowych, procesor może lepiej zoptymalizować swoją pracę gdy widzi jaki kod będzie musiał wykonać - nie musi przewidywać skoków.

Niby to są oszczędności małe, ale jeśli byłoby to w treści jakiejś funkcji wykorzystywanej przez 90% czasu wykonywania, to przez takie optymalizacje mógłbyś zauważyć wzrost wydajności. Chociaż tak jak mówiłem, należałoby się zastanowić, czy kompilator sam tego nie zoptymalizuje do pierwszej przedstawionej formy :) GCC, prawdopodobnie rozwija takie pętelki domyślnie, chyba że ustawisz optymalizację uwzględniającą jak najmniejszy rozmiar kodu. Sprawdź i po testuj ;)

Ps. Dla mnie dodatkowo pierwsza forma jest czytelniejsza :) Ale dla wektora  z większą ilością pól pewnie wolałbym pętle, powierzając optymalizacje kompilatorowi :)

Offline Kosai_

  • Użytkownik
    • devlog

# Lipiec 16, 2008, 16:35:46
czyli przy takich zadaniach jak mnożenie macierzy etc lepiej robić to ręcznie, bo takich obliczeń jest bardzo dużo..? czy mimo wszystko różnice będą niezauważalne?

Jak nie widzisz różnicy, to jeszcze trochę nauki przed tobą :)
Po drugie swojej wersji pętli też nie uświadczysz u lepszych koderów.
++i jest szybsze od i++, więc pętla według lepszych koderów będzie wyglądać tak:
Kod: (c) [Zaznacz]
float v[3], p[3];
for(int i = 0; i < 3; ++i) v[i] = p[i];
trochę nauki przed tobą bo wartość początkowa i powinna wynosić -1 :P...

ale tak tylko żartuję.. :P ale z tym ++ to przydatna informacja, dzięki
« Ostatnia zmiana: Lipiec 16, 2008, 16:37:48 wysłana przez kosiak »

Offline yarpen

  • Użytkownik

# Lipiec 16, 2008, 16:40:42
Jak nie widzisz różnicy, to jeszcze trochę nauki przed tobą :)
Po drugie swojej wersji pętli też nie uświadczysz u lepszych koderów.
++i jest szybsze od i++, więc pętla według lepszych koderów będzie wyglądać tak:
Bzdura.

Offline vinc999

  • Użytkownik

# Lipiec 16, 2008, 16:44:57
trochę nauki przed tobą bo wartość początkowa i powinna wynosić -1 :P...
to jest zart??? jesli nie... to troche nauki przed Toba...;];];]

Offline Kosz85

  • Użytkownik

# Lipiec 16, 2008, 16:50:44
czyli przy takich zadaniach jak mnożenie macierzy etc lepiej robić to ręcznie, bo takich obliczeń jest bardzo dużo..? czy mimo wszystko różnice będą niezauważalne?
trochę nauki przed tobą bo wartość początkowa i powinna wynosić -1 :P...

Tak jak mówiłem, przy włączonej optymalizacji dobrego kompilatora, efekt prawdopodobnie będzie taki sam. Chociaż ja już kilka razy udowodniłem, że pisząc ten sam algorytm z optymalizacją i używając "zakazanych" technik typu goto, inteligentnie zastosowane if'y zamiast switch itp. Można osiągnąć 1/2 do 1/3 prędkości oryginalnego algorytmu :) W ten sposób na zajęciach implementowaliśmy jakiś algorytm chyba do specyficznych zadań SAT, i położyłem wykładowce, który stwierdził, że nie zejdę z czasem wykonywania niżej niż w jego algorytmie (nie stosując wstawek asm). Zszedłem o prawie połowę :) Ale kod był zupełnie nieczytelny.

Poszukaj, w necie jest sporo o optymalizacji, zarówno C, jak i skryptów. Chociaż, część rzeczy jest typowo do przetestowania samemu, użyj jakiś profilerów :)

PS. jasne może jeszcze -2 ? i Segmentation Fault gratis ;)


++i jest szybsze od i++, więc pętla według lepszych koderów będzie wyglądać tak:
Bzdura.
Kompilator prawdopodobnie w wypadku pętli zoptymalizuje, ale wcale nie bzdura ++i zwiększa wartość, a i++ kopiuje wartość! Bo najpierw używa do działań (wartoś i zostaje utracona), a dopiero potem zwiększa o 1.

st3tc

  • Gość
# Lipiec 16, 2008, 16:52:12
Kompilator prawdopodobnie w wypadku pętli zoptymalizuje, ale wcale nie bzdura ++i zwiększa wartość, a i++ kopiuje wartość! Bo najpierw używa do działań (wartoś i zostaje utracona), a dopiero potem zwiększa o 1.
A popatrz słońce na jakim typie danych pracujesz ??

Offline yarpen

  • Użytkownik

# Lipiec 16, 2008, 16:53:00
Kompilator prawdopodobnie w wypadku pętli zoptymalizuje, ale wcale nie bzdura ++i zwiększa wartość, a i++ kopiuje wartość! Bo najpierw używa do działań (wartoś i zostaje utracona), a dopiero potem zwiększa o 1.
inc eax w obu przypadkach.

Offline Kosai_

  • Użytkownik
    • devlog

# Lipiec 16, 2008, 16:54:47
kurcze to nie wiem jak ja się uczyłem  ::)  ukamieniujcie mnie :P (w takim razie dobrze że jednak używałem i++ :P)
yarpen i beneth k++

Offline SiMet

  • Użytkownik

# Lipiec 16, 2008, 16:56:57
przeciez ten for ktory ma ++i mozesz sobie rozwinac tak:

for(int i=0;i<3;){
 /* */
 ++i;
}

ten warunek ZAWSZE wykonuje sie na koncu