Zobrazit předchozí téma :: Zobrazit následující téma |
Autor |
Zpráva |
perry

Založen: 28. 07. 2009 Příspěvky: 879
|
Zaslal: 9. únor 2011, 19:10:02 Předmět: Matrix class - spravnost kodu |
|
|
Zdravím,
začal jsem s C++ (přechod od C#, dříve jsem něco málo kutil v ANSI C). Začal jsem psát malou matematickou "knihovnu" pro použití v mých projektech (přeci jenom, je to základ).
Zajímalo by mě, zda je to dobře napsané a není-li to totální "prasečina", popř. co byste změnili
Matrix4x4.h
Děkuji za názory _________________ Perry.cz |
|
Návrat nahoru |
|
 |
if.then
Založen: 13. 04. 2008 Příspěvky: 579
|
Zaslal: 9. únor 2011, 19:28:46 Předmět: |
|
|
Pár rychlých postřehů neodborníka (i když jsem si taky už třídu pro matici napsal):
- inline se už tuším nemusí používat, moderní kompilery ho ignorují a inlinují dle libosti
- proč neděláš identity už v konstruktoru?
- kde máš operator[]?
- proč nemáš matici v poli?
- zdá se mi, že do téhle třídy chceš nacpat všechno - ale správný program není hotový tehdy, když není co přidat, ale když není co odebrat
- osobně preferuji mít class a externy v .h a všechny funkce a proměnné v .cpp, které neincluduješ. Tak se vyhneš vícenásobnému nalinkování (což je hrůza ). A taky je asi vhodnější #pragma once místo #ifndef...#define...#endif (je to jednodušší napsat ) - pokud tedy nepotřebuješ např. kontrolovat, zda je dodrženo pořadí includování apod. _________________ For guns and glory, go to www.ceske-hry.cz.
For work and worry, execute VC++. |
|
Návrat nahoru |
|
 |
perry

Založen: 28. 07. 2009 Příspěvky: 879
|
Zaslal: 9. únor 2011, 19:44:19 Předmět: |
|
|
- Ty inline jsou tam kvůli template... s nimi mi to nejde rozdělit do *.h a *.cpp.. viděl jsem sice řešení s extren keywordem, ale údajně to nepodporuje každý překladač.
- no, ne každou matici potřebuju jako identity ... ale stojí za zvážení, díky
- diky, na ten jsem jaksi zapomnel
- v poli to nemám, protože mi někdo říkal, že použít proměnné je rychlejší pro jednotkový přístup, než sapisovat v random pořadí do pole.. ale težko říct co je na tom pravdy
- nacpat všechno ? Zatím tam není nic, co bych nepotřeboval (kromě možná pár operátorů, ale ty radši píšu předem všechny)
- zvyk z ANSI C, kde #pragma nebylo
Jinak díky za postřehy _________________ Perry.cz |
|
Návrat nahoru |
|
 |
frca

Založen: 28. 07. 2007 Příspěvky: 1561
|
Zaslal: 9. únor 2011, 19:57:46 Předmět: |
|
|
perry napsal: |
- v poli to nemám, protože mi někdo říkal, že použít proměnné je rychlejší pro jednotkový přístup, než sapisovat v random pořadí do pole.. ale težko říct co je na tom pravdy |
Toto je nějaká blbost. V paměti to bude uložené stejně, jako by to bylo statické pole, takže tam neurychlíš nic. _________________ www.FRANTICWARE.com |
|
Návrat nahoru |
|
 |
perry

Založen: 28. 07. 2009 Příspěvky: 879
|
Zaslal: 9. únor 2011, 20:14:54 Předmět: |
|
|
Dobře.. přehodím to na pole... _________________ Perry.cz |
|
Návrat nahoru |
|
 |
nou

Založen: 28. 07. 2007 Příspěvky: 1050
|
Zaslal: 9. únor 2011, 20:33:40 Předmět: |
|
|
perry napsal: |
viděl jsem sice řešení s extren keywordem, ale údajně to nepodporuje každý překladač.
- v poli to nemám, protože mi někdo říkal, že použít proměnné je rychlejší pro jednotkový přístup, než sapisovat v random pořadí do pole.. ale težko říct co je na tom pravdy
|
ja som toto googlil. (template v cpp) a nasiel som ze extern template podporuju asi dva uplne exoticke prekladace. ale nie su to ICC, gcc ani ten vo Visual. implementovat to je vraj strasny opruz.
na 99% to prekladac prelozi cez LEA
a naco tam mas to #pragma region. _________________ Najjednoduchšie chyby sa najtažšie hľadajú. |
|
Návrat nahoru |
|
 |
if.then
Založen: 13. 04. 2008 Příspěvky: 579
|
Zaslal: 9. únor 2011, 20:35:53 Předmět: |
|
|
Pole si vlastně v C můžeš představit jako x elementů přesně po sobě. x[i] je vlastně "*(x+i)". Takže rychlost je asi fakt dost podobná jako u prvků uložených bez pole...
BTW: A není to trošku blbost, dělat si template matici? Vždyť v hrách budeš na 99% používat jen float nebo jen double, proč si přidělávat práci? _________________ For guns and glory, go to www.ceske-hry.cz.
For work and worry, execute VC++. |
|
Návrat nahoru |
|
 |
rezna
Založen: 27. 07. 2007 Příspěvky: 2156
|
Zaslal: 9. únor 2011, 20:46:44 Předmět: |
|
|
ja bych varoval pred #pragma once - je to M$ specific AFAIK ikdyz dneska i GCC to prelozi s nejakym prepinacem - a navic to ma taky sva uskali |
|
Návrat nahoru |
|
 |
perry

Založen: 28. 07. 2009 Příspěvky: 879
|
Zaslal: 9. únor 2011, 20:54:51 Předmět: |
|
|
#pragma region tam je na uzavirani bloku (obdoba #region ze C#), má význam jen ve VC++
Ad templates: ve hrách je to jasný float (možná double), ale raději píšu věci co nejvíc univerzální, než abych je psal pořád dokola . Mohl bych to sice řešit přes #define, ale takhle mi to přijde nějak lepší
citace: |
ja bych varoval pred #pragma once - je to M$ specific AFAIK ikdyz dneska i GCC to prelozi s nejakym prepinacem - a navic to ma taky sva uskali
|
Aha, možná proto nám to bylo v C řečeno kdysi #pragma once nepoužívat
Add pole: Mám použít definici T data[16] nebo T data[4][4] ? [/code] _________________ Perry.cz |
|
Návrat nahoru |
|
 |
Fila
Založen: 31. 07. 2007 Příspěvky: 853
|
Zaslal: 9. únor 2011, 21:14:30 Předmět: |
|
|
frca napsal: |
perry napsal: |
- v poli to nemám, protože mi někdo říkal, že použít proměnné je rychlejší pro jednotkový přístup, než sapisovat v random pořadí do pole.. ale težko říct co je na tom pravdy |
Toto je nějaká blbost. V paměti to bude uložené stejně, jako by to bylo statické pole, takže tam neurychlíš nic. |
Pokud s tim polem nedelas nejake skopiciny a ma pevnou velikost, pak by si s nim kompilator mel poradit stejne efektivne, jako se samostatnyma promennyma. Obecne to ale platit nemusi, v pameti to totiz vubec nemusi byt v prubehu vypoctu ulozene po celou dobu stejne (floatovou promennou muzes drzet nejakou dobu v registru, zatimco u pole si pri prasactejsim kodu napr. nemusi byt kompilator jisty, jestli muze nejaky udaj drzet v registru, nebo mu jej meni jina cast vypoctu, pak se musi valet nejlip v L1 a to rozhodne pomalejsi je). |
|
Návrat nahoru |
|
 |
rezna
Založen: 27. 07. 2007 Příspěvky: 2156
|
Zaslal: 9. únor 2011, 21:16:02 Předmět: |
|
|
a hlavne bych se vyprnul na sabloni - psat nejuniverzalnejsi kod co to jde je super - ale az to opravdu potrebujes - takto si zbytecne do zacatku pridavas tuny balastu, ktery treba ani nikdy nebudes potrebovat |
|
Návrat nahoru |
|
 |
VladR
Založen: 30. 07. 2007 Příspěvky: 1322 Bydliště: Greater New York City Area
|
Zaslal: 9. únor 2011, 22:04:43 Předmět: |
|
|
pragma #once je prasacina, to nepouzivaj. Raz by si to omylom mohol pouzit v robote a vyrobis si pruser.
citace: |
v poli to nemám, protože mi někdo říkal, že použít proměnné je rychlejší pro jednotkový přístup, než sapisovat v random pořadí do pole.. ale težko říct co je na tom pravdy |
No ale to je hodne vytrhnute z kontextu. Tuna mas predsa pole o 16 konsekutivnych hodnotach. De facto cele to bude cely cas v L1ke (za predpokladu spravneho zarovnania - hod si tam align ()).
To, ze ty pouzijes premennu, ktoru zadeklarujes v metode, a teda bude na stacku vobec nezarucuje, ze kompiler ju hodi do registru. A aj ked obvykle lokalne premenne skoncia v L1ke, zarucene to uplne nemas, pokial fakt nevies co presne robis.
Ak chces takuto kontrolu, tak potom rovno chod do SSE, a tam to mas na par instrukcii.
Za dalsie - skontroluj, ci nahodou niekde nemas preklepom typecast double->float
Tiez uvedom si, ze execution units vedia paralelne zratat viac vysledkov, takze ak vies zreorganizovat dependencies manualne (a pomoct tak kompileru), tak nevahaj a sprav to.
Napr. add zaberie 3 clocky, ale pipeline vie efektivne zacat novu floatingpoint operaciu kazdy clock, pokial nezavisi na vysledku predoslej. Inak, dostanes vysledok len kazdy treti clock (namiesto kazdeho za predpokladu nulovej dependency na predoslom vysledku).
Tento paralelizmus totalne zabijes tym, ak zadeklarujes lokalne parametre, ktore si bude CPU cucat zo stacku - lebo tym implicitne zavedies dependency (aj ked z L1 cache, ale to uz execution units zily netrha).
Samozrejme, paralelizmus sa najlepsie kontroluje na urovni assembleru, kde si vies rucne prehodit priamo nesuvisiaci integer kod medzi floatingpoint kod, cim zarucis paralelizmus na urovni jak integer execution CPU units, tak floatingpoint execution CPU units bez akychkolvek stalls. To je ale uz cisty assembler a pokial rychlost nie je kriticka, tak sa tym ani zaoberat nemusis.
Cache funguje najefektivnejsie, ak pristupujes k datam sekvencne, menej efektivne ak ides spatne a uplne najhorsie pri random pristupe.
Ak by si robil s SSE, tak si vies priamo poziadat o cache line prefetch.
Tuna pozor este na uncached write - pretoze cela cache line musi byt precitana a zapisana.
Este by som podotkol, ze sa netreba bat pripadneho prepnutia z L1 do L2.Na Core2Duo je latency pri L1ke 3 clocks, a pri L2ke 14 clocks, co je stale obrovsky rozdiel oproti ~185 clocks z RAMky.
Kod teraz nemam cas pozerat, takze pisem len take bezne, vseobecne rady. |
|
Návrat nahoru |
|
 |
perry

Založen: 28. 07. 2009 Příspěvky: 879
|
Zaslal: 9. únor 2011, 22:08:21 Předmět: |
|
|
Tak tuny balastu mi nevadi (jediné co mi vadí, je ta matlanina, kdy nejde nějak čistě držet *.h a *.cpp strukturu)...
a co jsem četl, tak výkon šablonama netrpí... hlavni cil byl spis je vyzkoušel, protože jsem je pak chtěl aplikovat až budu psát stromy, kde mi přijdou jako podstatná a užitečná věc
Ad pole vs proměnné:
Když bych nechal proměnné a chtěl bych případně poslat matici do shaderu jako raw data, tak tam už výkon ztratím při konverzi na pole ? Nebo můžu vzít matici a poslat její obsah v proměnných do shaderu ve stylu
kód: |
Matrix4x4<float> mojeMatice = Matrix4x4<float>::Identity();
send_raw_data(mojeMatice) |
Zase... možná je to nějaká prasečina, ale C# tohle interpretuje a funguje to OK  _________________ Perry.cz |
|
Návrat nahoru |
|
 |
VladR
Založen: 30. 07. 2007 Příspěvky: 1322 Bydliště: Greater New York City Area
|
Zaslal: 9. únor 2011, 22:12:47 Předmět: |
|
|
perry napsal: |
Add pole: Mám použít definici T data[16] nebo T data[4][4] ? |
Kludne pouzi aj [4][4], len si potom daj pozor, aby si pri pripadnom traversovani vo vnorenom cykle mal ten druhy index meneny v tom vnorenom cykle - nech to zodpoveda poradiu, ako je to aj skutocne v RAMke - kvoli cache.
iste, pri 16 hodnotach je to sumafuck, ale je dobre na to mysliet.
Traversovat maticu tak, ze druhy index menis v prvom cykle je proste fuuuuuj a taky clovek by mal radsej ist "kodit" databazy  |
|
Návrat nahoru |
|
 |
VladR
Založen: 30. 07. 2007 Příspěvky: 1322 Bydliště: Greater New York City Area
|
Zaslal: 9. únor 2011, 22:18:00 Předmět: |
|
|
perry napsal: |
Ad pole vs proměnné:
Když bych nechal proměnné a chtěl bych případně poslat matici do shaderu jako raw data, tak tam už výkon ztratím při konverzi na pole ? Nebo můžu vzít matici a poslat její obsah v proměnných do shaderu ve stylu
kód: |
Matrix4x4<float> mojeMatice = Matrix4x4<float>::Identity();
send_raw_data(mojeMatice) |
Zase... možná je to nějaká prasečina, ale C# tohle interpretuje a funguje to OK  |
Netusim ako to C# runtime interpretuje, nevidel som ten kod.
Ale ak posielas maticu do shaderu, tak predsa davas adresu pola a velkost.
Toto s premennymi nespravis.
Druha vec je, ze ten shader tak casto volat nebudes, takze ten overhead nebude tak strasny.
No ale prasacina to bude v kazdom pripade  |
|
Návrat nahoru |
|
 |
|