.[ ČeskéHry.cz ].
Sdílená paměť
Jdi na stránku 1, 2  Další
 
odeslat nové téma   Odpovědět na téma    Obsah fóra České-Hry.cz -> C / C++
Zobrazit předchozí téma :: Zobrazit následující téma  
Autor Zpráva
Játro.m



Založen: 01. 02. 2010
Příspěvky: 230

PříspěvekZaslal: 28. červen 2012, 09:48:01    Předmět: Sdílená paměť Odpovědět s citátem

Nazdar,

problém je asi takový, mám jednu třídu, dejme tomu že v mém případě má následující strukturu:
kód:

class Character
{
    public:

        ...

        Sound * deathSound, *hitSound, footSteps;
        Grenades grenades;
        xmAnimation character;
        Shield shield;
        Magnet magnet;
        ...

    private:
        vec3 pos, rot;
};


Většina z těchto instancí má dynamicky alokovanou paměť, kterou potřebuju občas při běhu uvolnit a znova naplnit.
Z této třídy udělám jednodušše pole:
kód:

character = new Character[4];


A konečně se dostávám k problému, tato třída - pole z ní je v hlavní smyčce sdíleno mezi dvěma vlákny - sítě a vykreslování.
Můj postup je takovej, že pole vytvořím v vlákně [sítě], v vlákně [načítání] načtu resource z disku, toto vlákno pozastavím a začnu [vykreslovat].

Do pole zapisuje ze začátku vlákno [načítání], který se pozastaví a převezmou kontrolu [sítě]. V renderingu se z této třídy jenom čte, a data se teda nepoškodí.
Hlavně, obsah zapisovanejch dat z [sítě] jsou obyčejný booleany a pár vektorů, do toho co se kreslí to nešahá, jen se podle příznaků přenastavují animace a podobně.

Toto je všechno v pohodě, jenom jakmile potřebuju tuto paměť uvolnit, tak se to chová jako posunutej pointer nebo špatnej - paměť se neuvolní i když zastavím všechny vlákna, i při vypnutí programu v destruktorech dostanu chyby, že se to nepodařilo uvolnit.

Upřímně, moc toho o multi-threadingu v tomhle směru netuším, jestli musím alokovat a dealokovat ve stejnejch vláknech, nebo je celá tahle navržená struktura na dvě věci?

Takže shrnutí, jak se má zacházet správně s pamětí, která je sdílená mezi vlákny?

Díky za odpovědi.
_________________
Jeden z vývojářů hry Grenade Madness.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Weny Sky



Založen: 28. 07. 2007
Příspěvky: 241

PříspěvekZaslal: 28. červen 2012, 11:33:05    Předmět: Odpovědět s citátem

- V ramci procesu je jedno kde, jak, proc, ... alokujes a uvolnujes pamet.
- S pameti mas zachazet tak, ze spravne synchronizujes pristup do kritickych sekci.

Problem bych videl v tom, ze si nekde poskodis pamet uplne necim jinym. Napriklad zapis mimo rozsah alokovaneho pole.

Jeste me potom napada varianta, ze linkujes proti single-thread standardnim knihovnam, takze pak je mozne, ze napriklad malloc/new poskodi haldu. Nebo nejake jina funkce.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
mar



Založen: 16. 06. 2012
Příspěvky: 610

PříspěvekZaslal: 28. červen 2012, 12:35:09    Předmět: Odpovědět s citátem

No myslím, že by to mělo být jedno. Pokud děláš ve VS, tak tam už myslím statický runtime stejně ani není podporován.

Jde o to, jak se ti to chová. Jestli to padá, tak tam asi bude zápis někam mimo, jak už bylo napsáno.

Jestli se to jenom neuvolňuje, tak se možná ještě jednou ujistit, že se pole dealokují pomocí delete[] místo delete. Může se stát, že to člověk někde přehlédne.

Poslední, co mě napadá, je, jestli se tam neuvolňuje už uvolněný blok. To by taky mohl být problém.
V debug módu by se ty bloky měly vyplňovat např. po uvolnění atd., viz např. tady: http://www.nobugs.org/developer/win32/debug_crt_heap.html
Takže pokud tam někde bude v pointerech něco jako 0xfeeefeee, pak je to ono.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Játro.m



Založen: 01. 02. 2010
Příspěvky: 230

PříspěvekZaslal: 28. červen 2012, 12:47:51    Předmět: Odpovědět s citátem

Pro upřesnění, kompiluju pod minGW, pole mažu určitě delete[], teď jsem to ještě kontroloval a uvolnění nepadá, jenom mi zůstane viset alokovaná paměť. VRAM kterou mažu v destruktorech se taky neuvolní, protože po vypnutí vidím visící shadery v paměti. Dělá to jenom tento kód, ve zbytku enginu je to různě použitý a smaže se to samo.

Na uvolněný bloky se podívám, ono to chování je takový, že se prvně smaže pole a potom se až volají destruktory, místo aby se prvně zavolaly destruktory v modelech a až potom se zničilo pole.
_________________
Jeden z vývojářů hry Grenade Madness.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
pcmaster



Založen: 28. 07. 2007
Příspěvky: 1827

PříspěvekZaslal: 28. červen 2012, 13:27:04    Předmět: Odpovědět s citátem

No tak to chovanie je zle Very Happy

Zvaz pouzivanie std::unique_ptr a std::shared_ptr vsade, kde sa len da -- je to ISO C++, funguje uz aj na predpotopnom VC++ 2010 (na GCC este lepsie) a, ako povedal typek z MS v zaujimavej, tu linkovanej video prezentacii o C++11, "uz nikdy nebudes musiet zavolat delete" Very Happy

Samozrejme, problemov s kritickymi sekciami ta to nezbavi, to si musis doriesit tak, ci tak, presne ako pise Weny.
_________________
Off-topic flame-war addict since the very beginning. Registered since Oct. 2003!
Interproductum fimi omne est.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
mar



Založen: 16. 06. 2012
Příspěvky: 610

PříspěvekZaslal: 28. červen 2012, 13:34:46    Předmět: Odpovědět s citátem

No to je dost divné chování.

Možná ještě zkusit něco z těchhle věcí: http://stackoverflow.com/questions/413477/is-there-a-good-valgrind-substitute-for-windows
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Tringi



Založen: 28. 07. 2007
Příspěvky: 290

PříspěvekZaslal: 28. červen 2012, 13:48:39    Předmět: Odpovědět s citátem

Udělej si kopii a začni program redukovat do úplně nejmenší verze, v níž se problém bude stále projevovat.
Pokud odebráním nějaké části problém zmizí, dá ti to dost dobré vodítko k nalezení chyby, i když ta nemusí být zrovna právě v té odebrané části. Pokračuj pak odebíráním jiných částí.
Pokud se dostaneš pod sto řádků a stále nebudeš vědět čím to, pak postni takto redukovaný kód sem a to by v tom byl čert, aby na to někdo nepřišel.
_________________
WWW | GitHub | TW
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
Játro.m



Založen: 01. 02. 2010
Příspěvky: 230

PříspěvekZaslal: 9. červenec 2012, 17:30:21    Předmět: Odpovědět s citátem

tak po odpoledni debugování jsem na to přišel,

1) vlákno se musí při uvoňování paměti uplně suspendnout funkcí SuspendThread, nestačí aby v smyčce byl return.
2) problém neuvolňování a chování se jako poškozenej pointer způsobovaly interní destruktory třídy, který se mě z naprosto neznámýho důvodu občas samy zavolaly i v renderu ?!? WTF, ale snad ani nechci vědět proč.

Takže řešení bylo, zaházet destruktory rodičovskejch tříd, nechal jsem jenom destruktory tříd ze kterejch se dělaj pole a ostatní destrukty jsem nacpal do vlastní třídy kterou volám při reloadu mapy / zavření okna.

Dík za nápady ;D
_________________
Jeden z vývojářů hry Grenade Madness.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Tringi



Založen: 28. 07. 2007
Příspěvky: 290

PříspěvekZaslal: 9. červenec 2012, 23:47:25    Předmět: Odpovědět s citátem

Chlape ty děláš něco hodně hodně špatně.
Tvé 1 i 2 je totální blbost, někde si přepisuješ paměť nebo něco, a budeš-li postupovat dál, dřív nebo později se zasekneš tak, že budeš moct celý projekt zahodit.
_________________
WWW | GitHub | TW
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
nou



Založen: 28. 07. 2007
Příspěvky: 1050

PříspěvekZaslal: 10. červenec 2012, 07:01:48    Předmět: Odpovědět s citátem

to ze sa ti volaju pravdepodobne pretoze sa ti niekde kopiruju. skus si spravit kopirovaci konstruktor a sprav ho protected. potom ti vyhlasi chybu pri preklade ak sa niekde takyto objekt budes snazit skopirovat.
_________________
Najjednoduchšie chyby sa najtažšie hľadajú.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Játro.m



Založen: 01. 02. 2010
Příspěvky: 230

PříspěvekZaslal: 10. červenec 2012, 07:49:50    Předmět: Odpovědět s citátem

Dík! Měli ste pravdu, ikdyž bych se zapřísáhl, že jsem to kopírování tam neměl, tak fakt na jednom místě bylo, problémy zmizely uplně.

Btw tringi, k tomu pozastavení vlákna. Řekni víc, co je na tom špatně, jsem v MT uplnej zelenáč a tuhle metodu jsem zvolil z důvodu, že když jsem začal mazat data který jsou sdílený mezi dvě/tři vlákna, tak mi to občas naprosto náhodně hodilo nedoledatelnej segfault. Pozastavení ostatních vláken kromě renderu a reloadu tohle vyřešilo.
_________________
Jeden z vývojářů hry Grenade Madness.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Marek



Založen: 28. 07. 2007
Příspěvky: 1782
Bydliště: Velká Morava

PříspěvekZaslal: 10. červenec 2012, 14:19:35    Předmět: Odpovědět s citátem

Přístup ke sdílené struktuře dej do kritické sekce.

SuspendThread je fakt totální blbost.
_________________
AMD Open Source Graphics Driver Developer
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Tringi



Založen: 28. 07. 2007
Příspěvky: 290

PříspěvekZaslal: 10. červenec 2012, 15:25:59    Předmět: Odpovědět s citátem

Játro: Pozastavení vlákna nevyřešilo tvůj problém, pouze zmenšilo pravděpodobnost že se projeví. SuspendThread bez okolků zastaví tvé vlákno klidně uprostřed destruktoru, uprostřed uvolňování paměti (a způsobit poškození heapu), uvnitř kritické sekce nějakého api (a způsobit deadlock jiných vláken) nebo třeba APC což je úplně jiná bestie.

Moje rada by byla: Pokud nemáš bottleneck na procesoru, přestaň používat vlákna, úplně. Pokud nevíš jak to udělat bez nich, použij nějakou vyšší knihovnu, nebo si nejprve alespoň nastuduj k čemu jsou mutexy/kritické sekce.

Když čtu tvoje "mazat data sdílený mezi vlákny" tak dostávám kopřivku. Sice jsem kdysi začínal stejnými pokusy, ale zabil jsem neskutečně času a nervů koukáním do kódu a bojem s neodladitelnými heisen-chybami. A přitom stačilo věnovat trochu času a nejprve si o tom něco přečíst.
_________________
WWW | GitHub | TW
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
Játro.m



Založen: 01. 02. 2010
Příspěvky: 230

PříspěvekZaslal: 10. červenec 2012, 16:27:32    Předmět: Odpovědět s citátem

Tringi, aha, ono jedna věc je studovat dokumentaci a druhá to zkusit prakticky, jakmile jsem viděl, že to funguje tak jsem to dál neřešil, no nevadí, zkusím popsat problém podrobně.

Ono řekněme, že v současné době dodělávám multiplayer pro realtime TPS, proto jsem zvolil použití vláken kvůli blokujícím soketům a možnosti si stavy ze sítě zpracovat v dalším vlákně.

Z toho důvodu, že ty dvě vlákna běží odděleně, není v síťovým vlákně kritická sekce, je jenom mezi renderem a načítáním, protože jsem se kvůli sítím dostával do deadlocku.. Zase, už v tomhle ohledu jedu od boku, protože nikde sepsán nějakej přesnej postup, jak by to mělo přesně vypadat. Proto jsem udělal jak říkáte blbost, že před každým reloadem mapy pozastavím vlákno který zpracovává data ze sítě a zbytek běží dál - načítání a render.

A pokud vím, tak kritickou sekci může v jednom okamžiku vlastnit jenom jedno vlákno, takže když zamknu sítě a render do jedné sekce a nastane náhodou lag, ztratí se paket nebo cokoliv, tak ta smyčka co renderuje se pozastaví přece taky ne?

Pokud v tom mám bordel, tak doufám, že budete tolerantní :D.
Budu rád za každej názor jak by jste to řešili vy.
_________________
Jeden z vývojářů hry Grenade Madness.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
rezna



Založen: 27. 07. 2007
Příspěvky: 2156

PříspěvekZaslal: 10. červenec 2012, 17:00:42    Předmět: Odpovědět s citátem

pouzij neblokujici sockety pomoci windowsich zprav

co se zamykani tyce - zamykaji se pouze kriticka mista, kam se zapisuje a je to sdileno

navic nikdo nerika ze musis zamknout pri cteni ze site

nactes ze site do pomocnych promennych (nehlede na to jakej je lag) - jakmile mas nacteno, zamknes data, prepises, odemknes

zamyka na nezbytne nutnou a nezbytne minimum - jinak samozrejme skoncis v dead-locku a nebo naopak nezamknes a jsi v race conditione

EDIT:
takze hlavni je toto - ty tu ted podrobne popis, co ktere vlakno dela, a ktera jsou ta sdilena data, pripadne proc uvolnujes data z jineho vlakna, nez ktere ho vlastni (to je typicky kamen urazu)
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
Zobrazit příspěvky z předchozích:   
odeslat nové téma   Odpovědět na téma    Obsah fóra České-Hry.cz -> C / C++ Časy uváděny v GMT + 1 hodina
Jdi na stránku 1, 2  Další
Strana 1 z 2

 
Přejdi na:  
Nemůžete odesílat nové téma do tohoto fóra
Nemůžete odpovídat na témata v tomto fóru
Nemůžete upravovat své příspěvky v tomto fóru
Nemůžete mazat své příspěvky v tomto fóru
Nemůžete hlasovat v tomto fóru


Powered by phpBB © 2001, 2005 phpBB Group


Vzhled udelal powermac
Styl "vykraden" z phpBB stylu MonkiDream - upraveno by rezna