dev.gamez.lv Forum Index dev.gamez.lv
Latvian Game Developers Community
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups 

identifikatori
Goto page Previous  1, 2
 
dev.gamez.lv Forum Index -> Programmēšana
View previous topic :: View next topic  
Author Message
elvman
Indago Uzvarētājs
Indago Uzvarētājs


Joined: 09 Apr 2003
Posts: 1278
Location: Kuldiga

PostPosted: Sat Aug 04, 2007 10:17 am    Post subject:

Ok, izveidoju hash table (izrādās, ka tas tomēr neprasija tika daudzlaika, pāris minūšu darbs) ar visiem iteratoriem un string atbalstu.

Vienīgie jautājumi ir saistībā ar iteratoriem, man viņi darbojas tā:

Ir klase CIterator, kurā glabājas pointeri uz iepriekšējo un nākošo iteratoru (un pašu objektu, kam ir šis iterators). Kad pievienoju listei jaunu elementu, dabūju tā Indexu tabulā, un tad braucu pa tabulu uz atpakaļu, līdz dabūju iepriekšējo elementu, un tieši to pašu daru uz priekšu, lai dabūtu nākošo elementu.

Kad elements tiek izdzēsts, tad iepriekšējā iteratora nākošais iterators ir izdzēstā iteratora nākošais iterators,un nākošā iteratora iepriekšējais iterators ir izdzēstā iteratora iepriekšējais iterators.
Pseidokods:
Dzēst(Iterators)
{
IepriekšējaisIterators=Iterators->prev;
NākošaisIterators=Iterators->next;

IepriekšējaisIterators->next=NākošaisIterators;
NākošaisIterators->prev=IepriekšējaisIterators;

IdzēšamIteratoru(index);
}

Šo metodi dabūju pats izdomāt, jo literatūru netā ir diezgan grūti atrast. Varbūt ir kāda labāka metode, kā to visu darīt?
_________________
long time; /* know C */
Back to top
View user's profile Visit poster's website
bubu
Indago Uzvarētājs
Indago Uzvarētājs


Joined: 23 Mar 2004
Posts: 3223
Location: Riga

PostPosted: Sat Aug 04, 2007 11:43 am    Post subject:

Literatūru ir atrast viegli, vajag tikai pareizos keywordus zinā - doubly linked list: http://en.wikipedia.org/wiki/Linked_list#Doubly-linked_lists
Vispārīgā variantā iesaku pamācīties par datu struktūrām, daudz labu lietu sapratīsi:
http://en.wikipedia.org/wiki/Data_structure (rindas, steki, koki, grafi, un tml).
http://en.wikipedia.org/wiki/Category:Data_structures

Par to kā labāk darīt - tad jautājums, kam tev šāds CIterator ir vajadzīgs?
Back to top
View user's profile Send e-mail
elvman
Indago Uzvarētājs
Indago Uzvarētājs


Joined: 09 Apr 2003
Posts: 1278
Location: Kuldiga

PostPosted: Sat Aug 04, 2007 12:54 pm    Post subject:

Pastudēju tavus linkus, mans variants bija identisks tavam dotajam Doubly-linked list (biju pieļāvis nelielas loģikas kļūdas). Tagad visi iteratori strādā ideāli un nemaz neprasīja tik daudz laika. Atkal atsvešinos no STL...
_________________
long time; /* know C */
Back to top
View user's profile Visit poster's website
bubu
Indago Uzvarētājs
Indago Uzvarētājs


Joined: 23 Mar 2004
Posts: 3223
Location: Riga

PostPosted: Sat Aug 04, 2007 1:57 pm    Post subject:

Vispār, ko es personīgi būtu darījis tavā gadījumā - lietojis std::map. Pirmkārt - tas strādā, ir pārbaudīts un ir maz ticam, ka STLā ir kāda kļūda (ko galīgi nevaru teikt ne par tavu implementāciju, no offence, ne arī par savu, ja tādu rakstītu). Otrkārt - vai tiešām šī id lookapošanā mapā būtu performances bottleneks? Es ceru, ka tu zini, 90/10 likumu - ka gandrīz jebkurā softā, tai skaitā spēlēs, 90% CPU laika tiek pavadīts 10% koda. Tas nozīmē, ka kods ir jāoptimizē tikai tajos 10% koda, kas parasti ir vienā konkrētā vietā. Mūsu Squares3D mēs lietojam map'u visur, kur vien vajag asociatīvo konteineru neuztraucoties par performances zudumiem (hash_map vs map), jo es zinu, ka tā nu noteikti nav vieta, kas rada bremzi. Zinu daudz citas vietas savā kodā, kas rada bremzi.

Jo redzi, kāda jēga optimizēt std::map šim tavam gadījumam, ja performancē iegūsi tikai labi ja 1% ? Es nesaku, ka nevar iegūt vairāk, iespējams var - tas atkarīgs no koda. Bet veltīt tik daudz laika optimizējot šo 1%... vai ir jēga? Manuprāt labāk veltīt laika optimizējot patiešām performances kritiskas lietas tādējādi iegūstot 10%, 20% vai pat vairāk procentu ātrdarbības.

Kā gudri vīri saka - "premature optimization is the root of all evil".
http://www.flounder.com/optimization.htm
http://en.wikipedia.org/wiki/Optimization_(computer_science)


Ak jā, ja runā konkrēti par std::map implementāciju, tad tā vispārīgi rēķinot, pieņemsim, ka tev ir n=1000 objekti salikti kādā mapā. Un ja tu gribēsi noskaidrot vai kaut kāds identifikators ir šajā mapā vai nav (find metode), tad nepieciešamo darbību skaita kārta (aptuveni) ir log2(n), kas nozīmē to, ka būs nepieciešamas ap 10 salīdzināšanas (tb if konstrukcijas) un 10 pointeru dereferencēšanas (a = a->left). Man tas nemaz nešķiet tik ļoti "dārgi".
Back to top
View user's profile Send e-mail
elvman
Indago Uzvarētājs
Indago Uzvarētājs


Joined: 09 Apr 2003
Posts: 1278
Location: Kuldiga

PostPosted: Sat Aug 04, 2007 2:12 pm    Post subject:

Nu man daļa no šiem 10% arī būtu tā identifikatoru padarīšana, jo spēlē viss tiek balstīts uz šiem identifikatoriem (burvestības, radījumi, objekti, spēlētāji, pat charakteru skini) un katrā loopā ir n-tās reizes ir jārakņājas pa šīm listēm.
Un neprasīja tas nemaz tik daudz laika izveidot šo hash listi, bet ieguvumam vajadzētu būt milzīgam (vēl neesmu testējis uz lieliem datu apjomiem). Kļūdām arī nevajadzētu būt (notestēju au visos variantos, tomēr 100% pārliecināts nekad nevar būt).
_________________
long time; /* know C */
Back to top
View user's profile Visit poster's website
bubu
Indago Uzvarētājs
Indago Uzvarētājs


Joined: 23 Mar 2004
Posts: 3223
Location: Riga

PostPosted: Sat Aug 04, 2007 2:23 pm    Post subject:

elvman wrote:
Nu man daļa no šiem 10% arī būtu tā identifikatoru padarīšana, jo spēlē viss tiek balstīts uz šiem identifikatoriem (burvestības, radījumi, objekti, spēlētāji, pat charakteru skini) un katrā loopā ir n-tās reizes ir jārakņājas pa šīm listēm.

Nē, šāda lieta nenozīmē tos 10%. Tie 10% nozīmē to, ko profileris tev uzrādīs. Ka tiešām 10% no programmas laika tiek pavadīts find metodes izsaukumā. No zila gaisa izrauti spriedumi praktiski nekad neizrādās patiesi. Pats esmu uz to vairākkārt uzrāvies. Likās, ka kāda funkcija ir performances bottleneks, bet izrādās, ka tā ir pavisam tālu no tā.

Quote:
Un neprasīja tas nemaz tik daudz laika izveidot šo hash listi, bet ieguvumam vajadzētu būt milzīgam

Kāpēc milzīgam? Tikmēr kamēr tu neuzlaidīsi profileri savam kodam, tikmēr tu nevari būt pārliecināts par ieguvuma rezultātu.

Pie tam STL spēks jau ir ne tikai gatavos konteineros, bet gan gatavos algoritmos operācijām ar tiem. STL augstā līmenī skatoties sastāv no konteineriem, algoritmiem, iteratoriem, funktoriem un strīmiem. Lai pilnībā izmantotu STL iespējas, vairākiem no šiem ir jāsadarbojās savā starpā. Tikai tad var saprast, kāpēc STL ir izdevīgi lietot un kāpēc tas ir uzbūvēts tā kā ir uzbūvēts.

Citreiz skatoties vai lietojot kautkādas open-source bibliotēkas mani tracina tas, ka tās katra gandrīz vai implementē savu std::string, savu std::vector, utt. Tas tikai man liedz efektīvi izmantot šos konteinerus ar STL algoritmiem.

Ar to visu es gribu pateikt - nevajag no zila gaisa izraut minējumus, vajag izmērīt ar atbilstošiem rīkiem, kas tieši kodā strādā lēni un tikai tad optimizēt. Bez šaubām - pliks std::map::find būs lēnāks par stdext::hash_map::find. Taču vai visā programmā tā būs lēnākā daļa - tas ir īstais jautājums!
Back to top
View user's profile Send e-mail
elvman
Indago Uzvarētājs
Indago Uzvarētājs


Joined: 09 Apr 2003
Posts: 1278
Location: Kuldiga

PostPosted: Sat Aug 04, 2007 2:31 pm    Post subject:

Ok, paskatīšos kādi rezultāti būs profilera testam.
_________________
long time; /* know C */
Back to top
View user's profile Visit poster's website
elvman
Indago Uzvarētājs
Indago Uzvarētājs


Joined: 09 Apr 2003
Posts: 1278
Location: Kuldiga

PostPosted: Sun Aug 05, 2007 5:24 pm    Post subject:

Man tagad viena neliela problēma. Gribētu, lai lietotāji varētu no klases ārpuses definēt hash un salīdzināšanas funkcijas.
Klases sākums izskatās tā:
Code:
template <typename IndexType,typename ValueType>class CList
{
public:
   typedef UDWORD(*HASHFUNCTION)(ValueType);
   typedef bool(*EQUALFUNCTION)(IndexType,IndexType);

   void SetHashFunction(HASHFUNCTION HashFunction)
   {
      if (HashFunction)
         m_HashFunction=HashFunction;
      else
         m_HashFunction=Hash; //uzliekam default
   }

   void SetEqualFunction(EQUALFUNCTION EqualFunc)
   {
      if (EqualFunc)
         m_EqualFunc=EqualFunc;
      else
         m_EqualFunc=Equal; //uzliekam default
   }
private:
   HASHFUNCTION            m_HashFunction;
   EQUALFUNCTION            m_EqualFunction;
...

Un klasē pašā ir definēts:
Code:
   bool Equal(IndexType Index1,IndexType Index2)
   {
      return Index1==Index2;
   }

Loģiski, ka m_EqualFunction=Equal nestrādā, bet kā īsti to definēt, ai strādātu? Funkciju ārpus klases nevar definēt, jo klase ir templeits. Ja tiešām nav nekāda variantu, tad vien būs jātaisa struktūra ar šo funkciju, kā memberu, kā tas ir std::map.
_________________
long time; /* know C */
Back to top
View user's profile Visit poster's website
bubu
Indago Uzvarētājs
Indago Uzvarētājs


Joined: 23 Mar 2004
Posts: 3223
Location: Riga

PostPosted: Sun Aug 05, 2007 5:51 pm    Post subject:

Nesapratu tavu problēmu no tava koda piemēra.

Cik saprotu gribi customizētus datu tipus likt savā konteinerī? Un tāpēc ir jābūt hešfunkcijai pieejamai, kuru nezini kā definēt? Tad ir divi varianti - taisi memberfunkcijas savām klasēm (cik saprotu šo tu negribi), vai arī izmanto funkciju overloadingu (līdzīgi kā STLā tiek realizēts operator << outstreamam):
Code:
class MyCoolDataType
{
    // ...
};

unsigned int hash(const MyCoolDataType& x)
{
    unsigned int hash = 0;
    hash ^= x.getX();
    hash ^= x.getY();
    return hash;
}

template <typename IndexType, typename DataType>
class HashTable
{
public:
   DataType& find(const IndexType& x)
   {
       return m_allData[hash(x)];
   }

private:
   std::vector<DataType> m_allData;
}

HashTable<MyCoolDataType, int> table;
int x = table.find(MyCoolDataType(..));


Funkciju pointeri ar nav īsti laba lieta C++'ā. Neaizraujies ar tiem. To vietā var tīri labi lietot citas lietas.

elvman wrote:
Funkciju ārpus klases nevar definēt, jo klase ir templeits.

Un kāpēc gan nevar? Mierīgi var:
Code:
template <class X>
class KLASE
{
    void funkcija(X& x);
};

template <class X>
void KLASE<X>::funkcija(X& x)
{
  ...
}

Tikai nezinu, ko tev tas dod..


Edit:
Ah sapratu - tu gribi funkcijas pointerim piešķirt member funkcijas pointeri. To, protams, ka nevar. Tie ir divi dažādi tipi. Member funkcija ar headeri void f(int x) klasei C īstenībā ir kā parasta funkcija void f(C* this, int x) - acīmredzami, ka tipi atšķirās.
Ja grib abus apvienot vienā mainīgajā, tad ir jālieto boost::bind analogs. Vai arī šis te: http://www.codeproject.com/cpp/FastDelegate.asp

Edit2:
Bet patiešām - šādi tu hešfunkcijas/salīdzināšanas funkcijas izsaukumu padari par vienu pointeri tālāk - uz rantaimu, nevis uzreiz kompilēšanas laikā izmantojot C++ dotās iespējas ar templeitiem un polimorfismu (funkciju overloadingu). Tādējādi tu padari savu heškonteineri lēnāku uz katru haš/salīdzināšanas funkcijas izsaukumu - tam vajag no atmiņas izlasīt funkcijas adresi pirms izsaukt to, nevis pa tiešo izsaukt (kā manā piemērā).

btw - kāpēc nelieto const funkciju argumentiem? Tā ir ļoti svarīga lieta priekš kompilatora, lai tas efektīvāk spēj optimizēt kodu!
Kā arī šeit - typedef bool(*EQUALFUNCTION)(IndexType,IndexType); nelieto references!
typedef bool(*EQUALFUNCTION)(const IndexType&, const IndexType&);
Gribēji uzrakstīt ātrāku std::map, bet man aizdomas, ka tev tavs CList sanāks vēl lēnāks :)


Last edited by bubu on Sun Aug 05, 2007 6:15 pm; edited 1 time in total
Back to top
View user's profile Send e-mail
elvman
Indago Uzvarētājs
Indago Uzvarētājs


Joined: 09 Apr 2003
Posts: 1278
Location: Kuldiga

PostPosted: Sun Aug 05, 2007 6:15 pm    Post subject:

Ui, neiedomājos padarīt šīs member funkcijas par statiskām (static). Viss OK, lietotājs, gan no klases ārpuses var padod savas funkcijas ar SetEqualFunction(funkcija), gan arī CList klase var izmantot savējās (statiskās) funkcijas, ja lietotājs tās nav uzstādījis pats.
_________________
long time; /* know C */
Back to top
View user's profile Visit poster's website
bubu
Indago Uzvarētājs
Indago Uzvarētājs


Joined: 23 Mar 2004
Posts: 3223
Location: Riga

PostPosted: Sun Aug 05, 2007 6:17 pm    Post subject:

Kāpēc tam CList'am vispār vajag kautkādas savējās statiskās funkcijas izmantot?
Es iepriekšējā postiņā pie Edit2 pierakstīju kāpēc tavs risinājums nav labs no ātrdarbības viedokļa.
Back to top
View user's profile Send e-mail
bubu
Indago Uzvarētājs
Indago Uzvarētājs


Joined: 23 Mar 2004
Posts: 3223
Location: Riga

PostPosted: Tue Aug 07, 2007 12:30 am    Post subject:

Pēc garām diskusijām IRC dimensijā tika viennozīmīgi nolemts, ka "premature optimization is the root of all evil", jo realizētais CList nemaz nestrādāja pareizi. Rezultātā kods tika atgriezts pie "sentēvu" metodēm - std::map<A,B>. Pie reizes tika iznīdēts "Hungarian notation" un funkciju argumentos tika ieteikts ieviest const & ātrdarbības uzlabošanai.

Labs darbiņš, kas padarīts - kārtējais neticīgais pievērsts "pareizajai" ticībai ;)
Back to top
View user's profile Send e-mail
Display posts from previous:   
dev.gamez.lv Forum Index -> Programmēšana All times are GMT + 2 Hours
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group