Tööl olid vahepeal karmid ajad, olime graafikust maas ja töötasime 10h päevas. Rootsis asjad ilmselt käivadki nii - ühel hommikusel miitingul lihtsalt öeldi, et koodivabrik hakkab täispööretel tööle.. ja nii ongi :D Ja see kestis üle kahe nädala järjest ning oli isegi päris fun, aga lõputöö ja botmasteriga tegelemiseks ei jäänud eriti aega. Nüüd on kiired ajad jälle möödas :)
Seoses lõputöö administratiivse poolega.
- Lõputöö deklareerisin ÕISis ära (Ei maganudki maha).
- Juhendaja andis ametliku kinnituse, et nõustub juhendama mu diplomitööd. Juhendajaks Valdur Kaldvee!
VisionTime.cpp & VisionTime.h in Botmasters NOW!
Olemus ja Ehitus
Sain valmis oma fancy tööriista, mille disainisin antud olukorras spetsiaalselt videotöötluse jõudluse mõõtmiseks. Samas saab seda kasutada kõikjal, kus protsesside täidesaatmine toimub tsükliliselt. Panin sellele nimeks VisionTime.Olemus ja Ehitus
Tool ise on singleton disainimustriga, mis sarnaste lahenduste puhul üldlevinud:
- Klassi kuuluva(te) objekti(de) arv on alati rangelt piiratud ühele & alati ainult üks ligipääsupunkt
- "Global point of access" - globaalselt ligipääsetav
- “Just-in-time initialization”
Ja selle saavutamiseks on kasutusel privaatne konstruktor ning privaatne pointer staatilisele objekti instantsile. (Java kutina on mul C++'is pidev peavalu nende pointeritega, no ei oska kunagi otsustada, kas kasutada või mitte :P) Instantsi "getter" on avalik ning esimasel väljakutsumisel algul loob objekti ja siis tagastab, järgnevatel kordadel lihtsalt tagastab olemasoleva.
Paljud loggerid on taolise ülesehitusega. Väga lihtne ja basic ning teatud funktsionaalsuse puhul ka päris vajalik. Näiteks andmebaasisessioonide puhul, kui on vaja vältida paralleelseid ühendusi. Mul on olnud kokkupuuteid singletoniga küll, javas ka levinud, kuid üldiselt reeglina ei soovitata andmeid ja objekte kasutada globaalse kehtivusega. Aga hetkel see vastas nõudmistele ideaalselt.
Alustasin tegelikult sellega, et mõtlesin täiustada Timer.cpp klassi, mille Silver oli kirjutanud 2010 aastal oma lõputöö arvutuste jaoks. Mingi hetk sain aru, et minu tool-i funktsionaalsus hakkab vanast timer.cpp skoobist väga kaugele eemalduma. Otsustasingi teha eraldiseisvaks. Vanast timerist on kasutusel vaid samasugune ajahetke "püüdmise" printsiip.
Kuidas töötab
Koodis pannakse lipukesed enne ja pärast mõõdetavaid protsesse. Samuti seadistatakse paika, mitmendast kaadrist alates algab mõõtmine ning, mitu järjestikust kaadrit arvestatakse.
Sel hetkel kui toimub videotöötlus, VisionTime ise mingeid kalkulatsioone ei tee, vaid salvestab Time Stamp Counter väärtusi eraldi csv faili - (edit: järgmises versioonis loobusin csv faili kirjutamisest ning hakkasin salvestama otse RAMi, sest see on muidugi veelgi kiirem) üritab olla botmasteri videotöötlemise ajal nii lightweight kui võimalik. Väärtuste hankimiseks kasutatakse POSIX programmiliidese funktsiooni clock_gettime määrates ära parameetrina monotoonse kella (CLOCK_MONOTONIC). See loendur on nanosekundilise täpsusega ja üliväikese üldkuluga - võtab mõned protsessori taktid, et loenduri väärtus lugeda.
1 nanosekund on 1/1000000000 sekundit ehk äärmiselt väike sekundi murdosa.
Näiteks 3.3 nanosekundiga liigub valgus vaakumis kõigest ühe meetri. (vees ja atmosfääris veel aeglasemalt)
Kaks VisionTime Tool'i ajasalvestust (sündmuse algus ja lõpp) võtavad aega umbes~50000ns(edit: 2000ns), ehk on võimelised salvestama 20 000 (edit: 500000) korda sekundis.
Kogu tulemuste arvutamine toimub alles lõpufaasis, kui on kogutud ajasalvestused soovitud arvu kaadrite kohta. Põhimõtteliselt tehakse ära "tagantjärgi arvutamine". VisionTime teeb tuhandeid arvutusi, rehkendab iga mõõdetava protsessi keskmised ja lisatab muud statistikat, mida saadud numbrite alusel saab kokku panna.
Pärast seda läheb automaatselt käima Open-Office Calc, mis kuvab tabeli koos tulemustega. (Mu lemmik featuur :D)
1 nanosekund on 1/1000000000 sekundit ehk äärmiselt väike sekundi murdosa.
Näiteks 3.3 nanosekundiga liigub valgus vaakumis kõigest ühe meetri. (vees ja atmosfääris veel aeglasemalt)
Kaks VisionTime Tool'i ajasalvestust (sündmuse algus ja lõpp) võtavad aega umbes
Kogu tulemuste arvutamine toimub alles lõpufaasis, kui on kogutud ajasalvestused soovitud arvu kaadrite kohta. Põhimõtteliselt tehakse ära "tagantjärgi arvutamine". VisionTime teeb tuhandeid arvutusi, rehkendab iga mõõdetava protsessi keskmised ja lisatab muud statistikat, mida saadud numbrite alusel saab kokku panna.
Pärast seda läheb automaatselt käima Open-Office Calc, mis kuvab tabeli koos tulemustega. (Mu lemmik featuur :D)
Umbes sellise tabeli annab välja:
(hetkel mõõdetud suht suvalised protsessid)
(hetkel mõõdetud suht suvalised protsessid)
| <... umbes 600 sarnast rida nagu järgmised kolm> | |||
| procfunc_goalB | e | 183564720 | |
| procfunc | e | 183707475 | |
| frame | e | 193506229 | |
| ------------------------------------------- | |||
| MEASUREMENT OVERVIEW | |||
| Started_measuring_from_frame: | 90 | ||
| Measured_nr_of_frames: | 30 | ||
| ----- | |||
| RESULTS | |||
| Process | Total_Nanoseconds | Occurrences | Avg_nanoseconds |
| fps_calc | 4345991 | 30 | 144866 |
| Gauss | 227982470 | 30 | 7599415 |
| Lut | 368607550 | 30 | 12286918 |
| procfunct_cvline | 1410093 | 30 | 47003 |
| procfunc_goalB | 185440320 | 30 | 6181344 |
| frame | 1705898552 | 30 | 56863285 |
| procfunct_stor_crt | 1106627 | 30 | 36887 |
| procfunc_goalY | 116735493 | 30 | 3891183 |
| procfunc_ball | 70547238 | 30 | 2351574 |
| procfunc | 389610809 | 30 | 12987026 |
| ----- | |||
| ACCORDING_TO_CALCULATIONS | |||
| Average_FPS: | 17 | ||
| Slowest_process:(procfunc) | 12987026 | ns (Avg.) | |
| Fastest_process:(fps_calc) | 144866 | ns (Avg.) |
DEMO!
Väikeses aknas captionid ei tööta päris nii nagu vaja :P
Kuidas saab panna tööle
Iseenesest mõistetav, et..
#include "visiontime.h"VisionTime liidese juhtimine käib kujul VisionTime::DO()->funktsiooniNimi(Parameeter);
Kokku on 6 avalikku juhtimisfunktsiooni.
Esimesed kolm on mõistlik käivitada testitava programmi(nt Botmasteri) main() funktsioonis.
1. turnOn() funktsioon lülitab sisse VisionTime'i. Kui see välja kommenteerida, siis ülejäänud VisionTime'i funktsioonid ei tee mitte midagi (pole lõplikult valmis):
VisionTime::DO()->turnOn();2. setMeasureNumberOfFrames() - määrab mitme kaadri kohta tulemused arvutatakse. Nimelt ei ole pilditöötluse kiirus konstantne, see muutub ajas pidevalt. Ühe ainsa kaadri mõõtmine on mõttetu, sest tegu võib olla kaadriga, tegelikust keskmisest parem/halvem. VisionTime kogub info etteantud arvu kaadrite kohta ning arvutab keskmised.
VisionTime::DO()->setMeasureNumberOfFrames(30);3. setMeasutingFromFrame() - määrab mitmendast kaadrist alates alustatakse mõõtmist. Jällegi pilditöötluse kiirus pole konstante ja kaamera videovoo edastamise alguses on jõudlus mõnevõrra kehvem ning paari sekundi pärast stabiliseerub.
VisionTime::DO()->setStartMeasuringFromFrame(90);
4. newFrame() - lipuke, mis määrab momendi, mil algab uus kaader. Ehk siis selline rida tuleb panna koodis uue kaadri funktsiooni vahetusse lähedusse.
VisionTime::DO()->newFrame();5. markBegin() - lipuke, mis määrab momendi, mil algab üks mõõdetavatest protsessidest. Funktsiooni argumendiks on protsessi nimetus või lühend - seda kasutatakse lõpus tulemuste kokkuvõttes.
VisionTime::DO()->markBegin("Lut");6. markEnd() - lipuke, mis määrab momendi, mil lõpeb üks mõõdetavatest protsessidest. Argument on sama nagu oli protsessi alguse lipukese puhul.
// Mõõdetav protsess nt 'Lut' vms
VisionTime::DO()->markEnd("Lut");
VisionTime aktsepteerib ka "alamprotsesse":
VisionTime::DO()->markBegin("Process");
VisionTime::DO()->markBegin("Sub-process1");
//alamprotsess1
VisionTime::DO()->markEnd("Sub-process1");
VisionTime::DO()->markBegin("Sub-process2");
//alamprotsess2
VisionTime::DO()->markEnd("Sub-process2");
//miskit muud
VisionTime::DO()->markEnd("Process");
Kuid alamprotsess ei tohi olla sama nimega:VisionTime::DO()->markBegin("Nimi");
//mingi protsess
VisionTime::DO()->markBegin("Nimi");
//mõõdetav protsess
VisionTime::DO()->markEnd("Nimi"); //Kumb lõpeb?
VisionTime::DO()->markEnd("Nimi"); //Kumb lõpeb?
Samuti ei pea mõõdetavad protsessid esinema sama arv kordi. Iga protsessi keskmine arvutatakse täpselt selle järgi kui tihti selle käivitamiseni programm jõudis. Ainus nõue on see, et viimase mõõdetava kaadri lõpuks ei tohi olla ühtegi pooleliolevat protsessi. Videotöötluse puhul on see loomulik, sest uue kaadri alguses peab olema kogu eelmise kaadri töötlemine juba "kauge minevik" :)
Mõned issued veel on (seoses turnOn() funktsionaalsuse ja käskude kujuga), mida tahaks muuta, aga põhiline funktsionaalsus on sellel tükil valmis. Hea mini-projektike c++'ga harjumiseks enne suuremaid vägitegusid ning lähitulevikus see jupp kannab ka vilja kuna säästab kindlasti palju aega. Igasuguse koodimuudatuse peale saab asja lihtsalt käima lükata ning vähem kui minuti pärast on ees kena tabel väljaarvutatud tulemustega. Ning kohe saab võrrelda, kuidas muudatused mõjutasid jõudlust. Elu on päris lill, kui keegi teeb alati sinu eest tülika mõõtmistöö :)
Source v1.0:
visiontime.cpp
Nüüd saan keskenduda mõõtmiste analüüsile ning alustan suurte Botmasteri uuendustöödega.


normps update timerile, sa võid vana asendada :P respection :)
ReplyDeleteAitäh :) Aga ei maksa vana arvelt võtta.
ReplyDeleteEks neil on erinev ampluaa :P
Vana timer sobib paremini ühekordseteks mõõtmisteks vms.