Forum » Programiranje » std containers vs. own custom containers
std containers vs. own custom containers
Mmm'Aah ::
Najprej me zanima, če kdo mogoče ve točno kako deluje std::vector. Kako to da lahko hkrati tako hitro briše element, ohranja njihov vrstni red in jih tudi vrača po indeksu ("zaporedna številka"). Kolikor vem, naj bi bil vector v bistvu ArrayList. Ampak array list alocira elemente v enem bloku memorije, torej naenkrat, zato da so lahko elementi v memoriji drug za drugim in je možno hitro vračanje po indeksu (element[x]. Zaradi tega pa je treba pri brisanju vmesnega elementa (če želimo ohraniti vrstni red) premakniti vse sledeče elemente za 1 nazaj, kar pomeni ponovno realokacijo spomina ali pa prekopiranje elementov znotraj trenutno alociranega spomina. Ta postopek ima v naslabšem možen primeru kompleksnost O(n), če je n število elementov seznama, kar vsekakor ni sprejemljivo za hitre algoritme.
Kako lahko std::vector v vseh omenjenih funkcijah ohrani kompleksnost O(1)???
Nadalje me zanima, kakšno je vaše mnenje glede implementiranja lastnih razredov za podatkovne strukture (seznami, množice, hash tables ipd.). Okrog STL knjižnice je spletenih veliko mitov, za katere se ne ve ali zares držijo ali ne. Nekateri pravijo, da je možno z lastnimi specializiranimi razredi doseči tudi 4-5 krat boljši preformans, drugi pravijo da to ni res, oz da ti to lahko uspe le če si "super-duper" programer in uporabljaš ne-vem-kakšne trike. Sam sem spisal LinkedList razred in ArrayList razred, vendar me pri obeh motijo prej omenjene pomanjkljivosti: ArrayList je počasen pri brisanje, LinkedList počasi vrača elemente po indeksu. Rad bi naredil tudi svoj Vector razred, enostavno zato ker mi STL sintaksta ni všeč in mi je bolj komot delat če si lahko naredim svojo. Če ne drugega, pa bi to rad nardil vsaj v izobraževalne namene.
Koliko od vas je že kdaj programiralo razrede podatkovnih struktur? Je kdo uspel sprogramirat vector?
Kako lahko std::vector v vseh omenjenih funkcijah ohrani kompleksnost O(1)???
Nadalje me zanima, kakšno je vaše mnenje glede implementiranja lastnih razredov za podatkovne strukture (seznami, množice, hash tables ipd.). Okrog STL knjižnice je spletenih veliko mitov, za katere se ne ve ali zares držijo ali ne. Nekateri pravijo, da je možno z lastnimi specializiranimi razredi doseči tudi 4-5 krat boljši preformans, drugi pravijo da to ni res, oz da ti to lahko uspe le če si "super-duper" programer in uporabljaš ne-vem-kakšne trike. Sam sem spisal LinkedList razred in ArrayList razred, vendar me pri obeh motijo prej omenjene pomanjkljivosti: ArrayList je počasen pri brisanje, LinkedList počasi vrača elemente po indeksu. Rad bi naredil tudi svoj Vector razred, enostavno zato ker mi STL sintaksta ni všeč in mi je bolj komot delat če si lahko naredim svojo. Če ne drugega, pa bi to rad nardil vsaj v izobraževalne namene.
Koliko od vas je že kdaj programiralo razrede podatkovnih struktur? Je kdo uspel sprogramirat vector?
64202 ::
STL vector mora biti kos rama, ker to pise v standardu (baje, ISO to prodaja za CHF/$$/EU). Do tega kosa pa lahko dostopas tkole &vektor[0], torej naslov od prvega elementa.
Nasploh glede hitrosti pa moras pri STL-ju pazit, ker se zanasas na sposobnosti proizvajalca. Recimo dinkumware (MS compilerji) za razliko od g++/libstdc++ nimajo optimiziran std::string::iterator operacije, recimo:
std::string s, a;
a.assign(s.begin(), s.end());
Koda bi morala narediti memcpy(a, i1, i2-i1), iterator bi pa moral biti char*. No pa koda ne naredi memcpy, ampak POKLICE FUNKCIJO assign ZA VSAK ZNAK. auch. Recimo tole pa deluje normalno:
a.assign(s.c_str(), s.size());
ali pa to:
a.assign(s, 0, s.size());
Torej je treba malo pazit kako delas s stvarmi, pa profiler uporabljat. Na sreco je MS moral pustiti kodo za template, tako da gres lahko z debugerjem cez in vidis kaj se dogaja. Standardni kontejnerji so sicer dobri, ce imas surs iz razlicnih izvorov pa morajo komunicirat z zapletenimi podatkovnimi strukturami. Konverzija iz ene v drugo obliko bi bila jasno draga.
Nasploh glede hitrosti pa moras pri STL-ju pazit, ker se zanasas na sposobnosti proizvajalca. Recimo dinkumware (MS compilerji) za razliko od g++/libstdc++ nimajo optimiziran std::string::iterator operacije, recimo:
std::string s, a;
a.assign(s.begin(), s.end());
Koda bi morala narediti memcpy(a, i1, i2-i1), iterator bi pa moral biti char*. No pa koda ne naredi memcpy, ampak POKLICE FUNKCIJO assign ZA VSAK ZNAK. auch. Recimo tole pa deluje normalno:
a.assign(s.c_str(), s.size());
ali pa to:
a.assign(s, 0, s.size());
Torej je treba malo pazit kako delas s stvarmi, pa profiler uporabljat. Na sreco je MS moral pustiti kodo za template, tako da gres lahko z debugerjem cez in vidis kaj se dogaja. Standardni kontejnerji so sicer dobri, ce imas surs iz razlicnih izvorov pa morajo komunicirat z zapletenimi podatkovnimi strukturami. Konverzija iz ene v drugo obliko bi bila jasno draga.
I am NaN, I am a free man!
Mmm'Aah ::
Hvala 64202, ampak na žalost tvoj odgovor ne ustreza nobenemu od mojh vprašanj. Ne zanima me kako lahko vector uporabljam, ker to znam. Zanima me točno kako deluje, kakšno so kompleksnosti njegovih funkcij itd.
Dobro..če ne drugega, sem zdaj izvedel, da je performans vector-ja močno odvsien tudi od kompajlerja. OK, bom probal z debugerjem trace-at not v kodo od vectorja če mi bo uspelo, pa sam zaštekat kakšne stvari....
Dobro..če ne drugega, sem zdaj izvedel, da je performans vector-ja močno odvsien tudi od kompajlerja. OK, bom probal z debugerjem trace-at not v kodo od vectorja če mi bo uspelo, pa sam zaštekat kakšne stvari....
64202 ::
Sem odgovoril predvsem na to:
> Nadalje me zanima, kakšno je vaše mnenje glede implementiranja lastnih razredov za podatkovne strukture (seznami, množice, hash tables ipd.). Okrog STL knjižnice je spletenih veliko mitov, za katere se ne ve ali zares držijo ali ne.
Tisto gor s stringom je stestirano dejstvo in ni mit :)
Za vektor sem pa mislil da je jasno, ker je kos rama. O(1) so dostopi, inserti v sredini so pa O(n): link
> Nadalje me zanima, kakšno je vaše mnenje glede implementiranja lastnih razredov za podatkovne strukture (seznami, množice, hash tables ipd.). Okrog STL knjižnice je spletenih veliko mitov, za katere se ne ve ali zares držijo ali ne.
Tisto gor s stringom je stestirano dejstvo in ni mit :)
Za vektor sem pa mislil da je jasno, ker je kos rama. O(1) so dostopi, inserti v sredini so pa O(n): link
I am NaN, I am a free man!
Vesoljc ::
kdaj se lotit svojih PS? takrat ko ugotivis, da jih rabis. razlog zakaj pa ponavadi lezi v hitrosti. vcasih array pac ni zadosti :)
Abnormal behavior of abnormal brain makes me normal...
Gundolf ::
Vector je praktično navadna C++ ali C tabela z nekaj funkcijami za enostavnejše delo. Torej brisanje elementa je O(n) in ne O(1). Če pogledaš kakšno dobro STL referenco ti mora tam pisat kompleksnosti za vse glavne operacije vseh glavnih kontejnerjev, se pravi tudi za list, deque, map, set in njihove izvedenke. Mišljeno je pač tako, da glede na potrebe izbereš primeren STL kontejner. Se veda se da za neke zelo dobro definirane specifične probleme napisati boljše kontejnerje a jaz bi rekel takole. Uporabljaj vgrajene, dokler ne ugotoviš da se ti predstavljajo ozko grlo. Potem dobro premisli, če lahko ti s kakšno levo optimizacijo to izboljšaš in to naredi. Ker če v glavnem uporabljaš vektor tako, da ga enkrat alociraš, notri namečeš vse elemente in nato le dostopaš do njih (ter morda vse skupaj resizaš enkrat na 10 minut) potem je vector že maximum v hitrosti, ki ga lahko dosežeš. Nima smisla pisati nekaj svojega. Drugo je, če ti recimo ni všeč način na katerega se resiza vector in bi rad morda da se vsakič ko mu zmanjka prostora poveča za 10x. V takem primeru bi morda razmislil o svoji implementaciji. Pa še tu se verjetno bolj splača le extendat std::vector.
Mmm'Aah ::
>Ker če v glavnem uporabljaš vektor tako, da ga enkrat alociraš, notri namečeš vse elemente >in nato le dostopaš do njih (ter morda vse skupaj resizaš enkrat na 10 minut) potem je vector >že maximum v hitrosti, ki ga lahko dosežeš
Sprobal sem naslednje:
v std::vector in v svojo implementacijo LinkedList sem vstavil dosti elementov (mislim da 100.000). Nato sem meril koliko časa traja da pride skoz vse elemente in pobere njihovo vrednost iz seznama v spremenljivko:
npr.
vs.
Foreach je nek makro ki olajša uporabljanje iteratorjev za LinkedList strukturo. Koda z mojim LinkedList je bila približno 2x hitrejša. A je mogoče operator [] za linked list tolko počasen in nardi še kej, za ta primer, odvečnega?
Sprobal sem naslednje:
v std::vector in v svojo implementacijo LinkedList sem vstavil dosti elementov (mislim da 100.000). Nato sem meril koliko časa traja da pride skoz vse elemente in pobere njihovo vrednost iz seznama v spremenljivko:
npr.
int size=vec.size(); for (int i=0; i<size; i++) { SG_Window *wnd=vec[i]; }
vs.
foreach(SG_Window*, w, ll) { SG_Window *wnd=ll.ElementAt(w); }
Foreach je nek makro ki olajša uporabljanje iteratorjev za LinkedList strukturo. Koda z mojim LinkedList je bila približno 2x hitrejša. A je mogoče operator [] za linked list tolko počasen in nardi še kej, za ta primer, odvečnega?
Zgodovina sprememb…
- spremenil: Mmm'Aah ()
64202 ::
Koda 1:
Koda 2:
Prevedeno z g++ -O3, obakrat izpise 48 232427013. Zalimaj surs/rezultat za svoj linked list pa bomo videli :)
Drugace se verzija g++:
g++ (GCC) 3.3.5 20050117 (prerelease) (SUSE Linux)
Proc:
Intel(R) Pentium(R) M processor 1.80GHz
cache size : 2048 KB
#include <iostream> #include <vector> #include <ctime> int main() { std::vector<int> xx; for(int i=0; i<1000000; ++i) xx.push_back(i); time_t k = time(0); int a = 5; int size = xx.size(); for(int jj=0; jj<10000; ++jj) for(int i=0; i<size; ++i) { a += xx[i]; } std::cout << time(0) - k << ' ' << a << std::endl; return 0; }
Koda 2:
#include <iostream> #include <vector> #include <ctime> int main() { std::vector<int> xx; for(int i=0; i<1000000; ++i) xx.push_back(i); time_t k = time(0); int a = 5; int size = xx.size(); int *xxp = &xx[0]; for(int jj=0; jj<10000; ++jj) for(int i=0; i<size; ++i) { a += xxp[i]; } std::cout << time(0) - k << ' ' << a << std::endl; return 0; }
Prevedeno z g++ -O3, obakrat izpise 48 232427013. Zalimaj surs/rezultat za svoj linked list pa bomo videli :)
Drugace se verzija g++:
g++ (GCC) 3.3.5 20050117 (prerelease) (SUSE Linux)
Proc:
Intel(R) Pentium(R) M processor 1.80GHz
cache size : 2048 KB
I am NaN, I am a free man!
Zgodovina sprememb…
- spremenilo: 64202 ()
Gundolf ::
Ne vem kaj si delal da si dobil tvojo kodo hitrejšo. Logično to ni. Upam da imaš vklopljene optimizacije in pa da ti hkrati kaj preveč ne optimizira. Samo asignanje spremenljivke v zanki stalno čez prejšnjo vrednost bi sicer to znalo zoptimizirati v eno samo prireditev.
Poleg tega vedi da primerjaš vektor, ki je 'identičen' tabeli / polju (int tabela[100];) z linked listo, kar tvoje rezultate naredi še bolj nesmiselne.
Poleg tega vedi da primerjaš vektor, ki je 'identičen' tabeli / polju (int tabela[100];) z linked listo, kar tvoje rezultate naredi še bolj nesmiselne.
Mmm'Aah ::
ok sem sprobal. Verjetno sem kaj zamočil zadnjič pri testiranju, čeprav imam v spominu da je blo vse prav....booh. ok, zdaj bom pa nardil še ArrayList na identičen način kot je vector, pa bom pol sprobal še to. napišem rezultate tukaj;)
Vredno ogleda ...
Tema | Ogledi | Zadnje sporočilo | |
---|---|---|---|
Tema | Ogledi | Zadnje sporočilo | |
» | [C++] Zapis vector<BOOL> v binarno datotekoOddelek: Programiranje | 1056 (860) | mn |
» | [Java] Shranjevanje vrsto razredov v ListOddelek: Programiranje | 1049 (947) | Beezgetz |
» | Java VECTOR?Oddelek: Programiranje | 974 (974) | BlueRunner |
» | [C++] velikost matrikeOddelek: Programiranje | 1695 (1507) | Jean-Paul |
» | [c++] Pomoč pri izdelavi std::vector "wrapperja"Oddelek: Programiranje | 1579 (1480) | zhigatsey |