/ Forside / Teknologi / Udvikling / Delphi/Pascal / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
Delphi/Pascal
#NavnPoint
oldwiking 603
jrossing 525
rpje 520
EXTERMINA.. 500
gandalf 460
gubi 270
DJ_Puden 250
PARKENSS 230
technet 210
10  jdjespers.. 200
Hurtig tilgang til mange bytes
Fra : Toke Eskildsen


Dato : 20-07-04 19:22

Jeg sidder og arbejder med noget billedbehandling og har brug for at
foretage forskellige beregninger på de enkelte pixels. Jeg er bekendt
med scanline metoden og det er da også udmærket hurtigt til at behandle
Bitmaps.

Jeg har imidlertid behov for at lave nogen midlertidige beregninger,
hvor det er underordnet om værdierne gemmes i form af et Bitmap eller
på anden vis. Der hører en værdi til hver pixel. Jeg ville foretrække
at værdierne var words eller større, men kan klare mig med bytes, hvis
det giver en væsentlig gevinst i form af hastighed.

Jeg har prøvet at lave ca. samme simple operation på fire forskellige
strukturer. Gennemsnitstider for 100 gennemløb er angivet i parantes:

Bitmap med scanline (16,4 ms)
Dynamisk array af bytes (15,3 ms)
Statisk array af bytes (7,6 ms)
Statisk array af words (9,5 ms)

Det kalder jo umiddelbart på brugen at et statisk bytearray, selv om
jeg ikke bryder mig om statisk angivelse af størrelsen. Jeg vil dog
gerne høre om der er er andre muligheder? Måske noget med at allokere
et stykke hukommelse og tilgå det direkte?

RAM forbruget er ikke vigtigt. Hvis der er gevinst ved at benytte 32bit
enheder i stedet for 8bit, er det glimrende.

 
 
Christen Fihl (21-07-2004)
Kommentar
Fra : Christen Fihl


Dato : 21-07-04 11:06

Du skulle nok vise lidt kode her også. Ellers er det ikke til at se hvad
forskellen på byte og word arrayet er.

Der er forskel på om du benytter et array på fast adresse, eller en
allokeret klump af data, som du så skal adressere med en pointer hver
gang.

Følgende er altid adresseret med pointer:
o Bitmap med scanline (16,4 ms)
o Dynamisk array af bytes (15,3 ms)

De næste er som regel ikke, men kan være som forklaret herunder:
o Statisk array af bytes (7,6 ms)
o Statisk array af words (9,5 ms)

Men hvis du laver en array med statisk størrelse, og så allokerer den
senere, så bruger du igen en pointer, altså en ekstra operation.

Type
TStatiskArray1 = Array [0..1000] of Byte;
TStatiskArray2 = Array [0..1000000] of Byte;
Var
Array1:= TStatiskArray1; // Fylder 1000 Bytes
Array2:= ^TStatiskArray2; // Fylder 4 bytes, blot en pointer

begin
GetMem(Array2, 40000);

Brugen af Array1 her vil være hurtig, nok de 7.6 du nævner.
Brugen af Array2^ vil være langsommere.

Hvis det laver meget beregning på de samme data, kunne du fx kopiere en
klump af gangen (fx en hel scanline eller flere) til en statisk
allokeret buffer, og så arbejde deri.
Det spildte arbejde med at kopiere kan måske opvejes flere gange
efterfølgende i behandlingen.

Christen Fihl
http://HSPascal.Fihl.net/



Toke Eskildsen (21-07-2004)
Kommentar
Fra : Toke Eskildsen


Dato : 21-07-04 19:36

Christen Fihl wrote:

> Du skulle nok vise lidt kode her også. Ellers er det ikke til at
> se hvad forskellen på byte og word arrayet er.

Hum... Det er lidt svært, da det meste er pseudokode lige nu. Men jeg
skal gerne prøve at beskrive lidt nøjere:

Jeg skal lave realtime analyse af videobilleder. Små dyr i petriskåle
filmes og jeg skal lokalisere dem og følge deres bevægelser. Dyrene
klassificeres på farve og på form.

Først gennemløbes billedet og alle pixels der opfylder farvekravene
markeres med en værdi.

1) Hvis en kravsopfyldende pixel (KP) befinder sig nedenfor eller til
højre for en anden KP, får den samme værdi som denne.
2) Hvis en KP ikke optræder nedenfor eller til højre for en anden KP,
får den en ny værdi.
3) Hvis der både er en KP ovenfor og til venstre for den aktuelle KP og
disse to pixels har forskellig værdi, huskes der på at disse to værdier
er ækvivalente.
4) Efter første gennemløb laves et nyt gennemløb, hvor ækvivalente KP
slåes sammen.

Ved at benytte bytes, kan der logisk nok kun være 255 forskellige
områder. I praksis går det nok, selvom jeg nok ville foretrække et par
tusinde.

> Men hvis du laver en array med statisk størrelse, og så allokerer
> den senere, så bruger du igen en pointer, altså en ekstra
> operation.

Til min test lavede jeg en simpel form, hvor jeg definerede de
forskellige arrays under public:
public
ar: TMyArray;
ar2: TMyFixedArray;
ar3: TMyWordArray;

De forskellige arrays var så defoneret under type:
TMyArray = array of array of byte;
TMyFixedArray = array[0..767] of array[0..1023] of byte;
TMyWordArray = array[0..767] of array[0..1023] of word;

Det må næsten betyde en dynamisk allokering, da Formen jo er et objekt
der skabes? Burde hastigheden for det dynamiske array og det statiske
så ikke være den samme?

Jeg prøvede at definere et array som var udenfor objektet og det var
ca. et millisekund hurtigere end det statiske array definerer under
Form. Desværre er det ikke umiddelbart brugbart i praksis, da jeg gerne
vil kunne anvende et vilkårligt antal arrays (svarende til et
vilkårligt antal petriskåle).

> Hvis det laver meget beregning på de samme data, kunne du fx
> kopiere en klump af gangen (fx en hel scanline eller flere) til en
> statisk allokeret buffer, og så arbejde deri.

Mnaeh, som det måske fremgår af min beskrivelse er de lokale
beregninger meget simple, men der kræves hastig gennemløb af alle data.

Foreløbig tak for hjælpen. Jeg kunne selvfølgelig overveje en
allokering under var af et (forhåbentligt fornuftigt sat) vist antal af
arrays...
--
Toke Eskildsen - http://ekot.dk/

Christen Fihl (21-07-2004)
Kommentar
Fra : Christen Fihl


Dato : 21-07-04 21:48

Jeg prøvede at forstår

Prøv evt at spørge på borlands newsserver i
borland.public.delphi.language.basm hvor de der går meget op i
optimeringer, dog mest med relevans til assemblerkode. Men scanline
problemer er også oppe der.

PS: Prøv engang at benytte Integer istedetfor Word's, da alle cpu'er
arbejder bedst med byte eller max register længde, dvs 8 eller 32 bits
og ikke 16 bits som et Word er. Hver eneste word reference koster en
extra prefix byte.

--
Christen Fihl
http://HSPascal.Fihl.net/



Nicolai Hansen (22-07-2004)
Kommentar
Fra : Nicolai Hansen


Dato : 22-07-04 16:50


"Toke Eskildsen" <darkwing@daimi.au.dk> skrev i en meddelelse
news:Xns952CCF383F82Ctokeeskildsen@130.133.1.4...

> Jeg har imidlertid behov for at lave nogen midlertidige beregninger,
> hvor det er underordnet om værdierne gemmes i form af et Bitmap eller
> på anden vis. Der hører en værdi til hver pixel. Jeg ville foretrække
> at værdierne var words eller større, men kan klare mig med bytes, hvis
> det giver en væsentlig gevinst i form af hastighed.

Hvad du vinder mest ved kommer meget an på hvordan du bruger dit array.
Springer du meget i det?
Læser du det igennem fra start til slut?

Hvis du bare læser det fra ende til anden er den hurtigste metode at
allokere
et statisk array og tilgå det via en pointer... Men den del klarer din
optimizer
helt sikkert for dig.

Hvis du springer meget i dit array skal du gøre alt for at undgå/optimere
beregningen
af positionen i dit array. Hvis du f.eks. vil sammenligne en "pixel" med
dens fire "naboer"
i et 100x100 billede (bruger et array[0..9999]), kan du med fordel gemme
alle fem
placeringer som pointere
pix:=x;
p1:=x-1;
p2:=x+2;
p3:=x-100;
p4:=x+100;
læse array[pix], array[p1], ... og til sidst inc(pix); inc(p1); inc(p2)...
etc
Det vil du kunne vinde meget ved. Evt. kan du "udvide" dit array så det er
102x102 -
så slipper du helt for at skulle tjekke for om din pixel ligger på kanten.




Søg
Reklame
Statistik
Spørgsmål : 177558
Tips : 31968
Nyheder : 719565
Indlæg : 6408914
Brugere : 218888

Månedens bedste
Årets bedste
Sidste års bedste