2024. április 19., péntek

Gyorskeresés

[SVS_8] Augusztus 26-31.

Írta: | Kulcsszavak: SRV . surveyor . SVS

[ ÚJ BEJEGYZÉS ]

Kicsit egyszerűsítem a dolgokat, mert sajnos kezdődik hamarosan az iskola :O. Például csak a munkával telt napokat jegyzem fel és a címbe se írok le minden napot, csak az időszakot.

Augusztus 27., még 104 nap

A sobel feldolgozás ötletemhez ismét elővettem a thread linkjeimet, és megoldást kerestem arra, hogyan adhatok adatot a threadnek, és hogyan szerezhetek onnan vissza, globális változók nélkül. Amire "vágytam", azt tesztkódban sikeresen megcsináltam.

Gondoltam először az SVS képlehívását írom át 2db threadbe (a dll-ben), kíváncsiságból, hogy mennyit gyorsul. Olyan szép hibaüzeneteket kaptam, hogy csak lestem :B. Itt egy [link] nekem is ez volt a bajom, és Napalm megoldása lett jó nálam is, így nem kellett az egész dll-t átalakítani, a másik megoldás amit találtam, az sokkal nagyobb átalakítást igényelt volna.

Izgatottan vártam, na mennyit gyorsul az SVS ettől és az eredmény: semmi gyorsulás :O. (Fekete kupakos teszt, régi kód 9-10 FPS, új kód 9-10 FPS 320x240Q8). Kicsit letörtem, mert nem értettem mi a baj, a thread hívás jól lett megírva, mert a tesztkódon szépen egyszerre csinálnak mindent.

Egyetlen ötletem, hogy olyan gyorsan átjön az adat, és olyan gyorsan dekódolják, hogy nem érezhető gyorsulás attól, hogy párhuzamos threadben vannak. Meg fogom ismételni a tesztet úgy, hogy kirakom az ablakba a robotot (részletesebb kép -> nagyobb és bonyolultabb jpeg) és úgy mérem le. Ezt csak holnap, mert éjszaka van már, és az SVS fogta magát és csendben lemerült.

Mivel nem tudtam tovább tesztelgetni, így újra elővettem az SRV-t, hogy a képlehívást egy kamerára is megpróbáljam még gyorsítani. Itt tesztelgettem már, memcpy() kihagyását próbáltam meg ismét. Megint parse error, stepbystep megint jó, stb.
Beraktam egy Sleep()-t, és tényleg az volt a hiba, hogy túl gyors. Alapesetben 160x120Q8 kupakos teszten 33-36 FPS, szépen tízesével növelve a Sleep() értéket találtam egy stabil várakozást, ott 20-25 FPS volt.
Úgy néz ki memcpy() vagy memmove() nélkül nem úszom meg, mert a két buffert el kell választani egymástól.

AForge.NET-nek is megtaláltam a határát, 160x120Q8 fekete kupaknál kiakad a program :).

Augusztus 28., még 103 nap

Release build

Kíváncsiságból csinálni akartam a programomból egy rendes futtatható állományt, és a "natív" oprendszeremen (win7x64) megnézni, hogy az eddig mért adatok stimmelnek-e.

Beállítottam mindent, bemásoltam mindent, és mégis hibaüzenet kaptam a program indításakor. Notin is megnéztem, nem-e win7-tel lehet-e a baja, de nem, ott is elszáll, ugyanazzal a hibaüzenettel.

Nem mentettem el a hibaüzenetet, így nem tudom megmutatni, de az rá a megoldás, hogy release linker beállításoknál az opencv "d" nélküli libjeit kell berakni, és a "d" nélküli dlljeit kell bemásolni. Aki belenéz az opencv lib és bin könyvtárába, az érteni fogja :).

320x240Q8 és 640x480Q8 esetén kb. +1 FPS összejött, CPU terhelés gyakorlatilag semmi, viszont 160x120Q8 esetén csak 32 FPS volt (36 helyett).

Párhuzamos thread

Kiraktam a robotot az ablakba, és az történt, amit (nem) vártam. Egyedül 320x240Q1-nél gyorsult 1 FPS-t (1-2-ről 2-3-ra), többi maradt. :O
Annyi pozitívum történt, hogy felfedeztem egy elég nagy hibát, ami a thread miatt jön elő, és összeomláshoz vezet. A hiba akkor jön elő, ha az egyik kamera timeoutol, a másik nem, ilyenkor megint memóriafelszabadításos hiba jön elő (de könnyen javítható).

Egy kamera gyorsítás

Még kipróbáltam ezt azt, de nem sikerült gyorsítani. Ha csak nem üt be valami zseniális ötlet, felhagyok a tesztelésekkel, és haladok tovább.

Augusztus 31., még 100 nap

A napot már megint SVS gyorsítással kezdtem. A pár nappal előbb említett kód a dll-ben csinál két thread-t, most megnéztem, mi van ha az ablakos programban csinálok két thread-t, és a dll-be egy jobb és bal képlehívást.
Ott se gyorsult semmi. Egyedül 640x480-nél növekszik 1 fps-sel. Maradok a dll-ben megvalósítottnál.

A tesztelt, majd elvetett ablakos képlehívás threadje (működött!):
DWORD WINAPI getimgThread_L(LPVOID iValue)
{
IplImage **image = (IplImage**)iValue;
if(svs->getimg_L(&*image)<0)
ExitThread(1);
else
ExitThread(0);
}

Egyszer a pointerek fognak a sírba vinni :D.

Már elfogytak az ötleteim. Valószínűleg a robot úgy csinálja, hogy mivel 1 csatorna van, szépen sorba rendezi a válaszokat. Az az elméletem, hogy mire teljesen elküldi a 2. kamera képét, addigra a pc feldolgozza az 1. kamera képét (mert a képtovábbítás a leglassabb), így tűnik úgy, hogy nem gyorsult semmit az egy szálashoz képest.

28-n írtam, hogy SVS képlehívő threadjében találtam egy nagy hibát, be is írtam a kigondolt megoldást. Teszt, és ismét, timeoutnál, parser errornál teljesen elhasalt a program. Persze mire ezt kidebbugoltam, aaaaaaah :W (alattomos, rejtett hibák rulz).

Első hiba tünete: ablakos program mindig cvReleaseImage()-nél halt le, de csak akkor, ha a robot timeoutolt. Kellett némi idő, míg rájöttem, hogy a hiba oka a robotvezérlő dll-ben van, azon belül, ahol elindítom a két thread-t.
Hiba oka: a threadek változóját "elengedtem" (CloseHandle()), aztán kérdeztem le, hogy milyen kóddal értek véget (GetExitCodeThread()), így persze mindig 0-t adtak, és szépen kihagyták a hibás esetre írt kódomat. Miután felcseréltem a kettőt, minden a helyére került. Ez történik, ha nem figyelem, hogy hova rakok dolgokat :D. Viszont ekkor jött a következő hiba.

Második hiba tünete: Szintén timeout esetén, svs->GetImages() hívásánál, ez a hiba is ugyanott volt, ahol az előző.
Hiba oka: ha egyik kamera kap képet (thread végzett), míg a másik valahol kilép (thread kilépett a vége előtt) akkor fel kell szabadítanom a képeket, mert következő futásnál hibával leállna. Nehéz körülírni mi történt, de ha felszabadítottam az egyik képet, akkor a másik kép struktúrájába (IplImage) random hülyeségek lettek (én is néztem nagyot). A feltétel képnek nézte, a cvReleaseImage() szerint meg nem volt az, így ott szállt el. Sokat tesztelgettem, végül az lett a megoldás, hogy minden GetImages() hívás elején a két képet nullával kell egyenlővé tenni. Van egy sejtésem, hogy mi történhetett, de inkább nem részletezem, mert lehet, hogy nagy hülyeség :D.

Második hiba hatására visszatértem egy régi probléma forrásához (SVS csatlakozása), és ott is ez jelentette a megoldást.
Ablakos programba is átalakítottam ezt azt, mert kicsit szúrta a szemem. Készültem feltölteni SVN-be a napi munkámat, ilyenkor törlöm a Debug és Release könyvtárakat, mert csak a helyet foglalják. Nagy igyekezetemben kitöröltem az ablakos programom forrását :W. Még szerencse, hogy nem a dll-t, bár ablakosban is mindent helyreállítani kb. 1,5 órába tellett.

Másik nagy szívás, hogy a hibákhoz timeoutot kellett előidézni. Persze most sehogy se akart, végül leszedtem az antennát. Emberi test jobban fogja a jeleket mint a betonfal :).

Copyright © 2000-2024 PROHARDVER Informatikai Kft.