Accueil > Forum > > > > Performances et pointeurs.
Performances et pointeurs.
jeudi 29 mai 2008 à 17:46:12 |
Performances et pointeurs.

Caribensila
|
Bonjour M'sieurs'Dames,
Je suis en train d'essayer de combler une de mes nombreuses lacunes en prog' en tentant de dompter les pointeurs sous Delphi. Pour cela, je fais des tests dans tous les sens. Voici un de ces tests concernant ScanLine. Ca marche, mais mon problème est que je ne comprends pas pourquoi.
Ce test ne fait que transformer une image couleur en niveaux de gris :
{Méthode ScanLine "classique".} procedure TForm1.btnScanLineClick(Sender: TObject); type pRGBArray = ^TRGBArray; TRGBArray = ARRAY[0..0] OF TRGBTriple; var Bmp : TBitMap; Row : pRGBArray; X,Y : Integer; R,G,B,Grey : Byte; StartTime, EndTime : Int64; begin Bmp := TBitMap.Create; try Bmp.LoadFromFile(ChangeFileExt(Application.ExeName,'.bmp')); Image1.Picture.Bitmap.Assign(Bmp); QueryPerformanceCounter(StartTime); for Y := 0 to Bmp.Height-1 do begin Row := Bmp.ScanLine[Y]; for X := 0 to Bmp.Width-1 do begin R := Row[X].rgbtRed; G := Row[X].rgbtGreen; B := Row[X].rgbtBlue; Grey := (R+G+B) div 3; Row[X].rgbtRed := Grey; Row[X].rgbtGreen := Grey; Row[X].rgbtBlue := Grey; end; end; QueryPerformanceCounter(EndTime);//environ 7300 Kticks. Image2.Picture.Bitmap.Assign(Bmp); Label1.Caption := Format('%.0n KCycles',[(EndTime-StartTime)*0.001]); finally Bmp.Free; end; end;
{ScanLine préalable de TOUT le Bitmap dans un tableau de pointeurs.} procedure TForm1.btnTestAClick(Sender: TObject); type pRGBArray = ^TRGBArray; TRGBArray = ARRAY[0..0] OF TRGBTriple; var Bmp : TBitMap; MonTab : Array of pRGBArray;// ça, c'est nouveau! X,Y : Integer; R,G,B,Grey : Byte; StartTime, EndTime : Int64; begin Bmp := TBitMap.Create; try Bmp.LoadFromFile(ChangeFileExt(Application.ExeName,'.bmp')); QueryPerformanceCounter(StartTime);
SetLength(MonTab,Bmp.Height); //On remplit d'abord tout le tableau dynamique. for Y := 0 to Bmp.Height-1 do MonTab[Y] := Bmp.ScanLine[Y];
for Y := 0 to Bmp.Height-1 do begin //..puis on accède à chaque pixel par ce tableau. for X := 0 to Bmp.Width-1 do begin R := MonTab[Y]^[X].rgbtRed; //ou R := MonTab[Y,X].rgbtRed; G := MonTab[Y]^[X].rgbtGreen; B := MonTab[Y]^[X].rgbtBlue; Grey := (R+G+B) div 3; MonTab[Y]^[X].rgbtRed := Grey; MonTab[Y]^[X].rgbtGreen := Grey; MonTab[Y]^[X].rgbtBlue := Grey; end; end; QueryPerformanceCounter(EndTime);//environ 5500 Kticks. Image3.Picture.Bitmap.Assign(Bmp); Label2.Caption := Format('%.0n KCycles',[(EndTime-StartTime)*0.001]); finally Bmp.Free; end; end; Je ne comprends pas pourquoi ma 2ème méthode est environ 25% plus rapide que la méthode ScanLine classique. En effet, dans les 2 méthodes, on parcourt toutes les lignes du Bmp pour les scanner une à une. Pourquoi l'accès à chaque pixel est plus rapide en passant par un tableau? 'doit y avoir une histoire de gestion de la mémoire la-dessous, non?
Si une âme charitable pouvait m'allumer la lampe à Eugène ce serait sympa car je sens confusément que je n'ai encore rien compris à ces foutus pointeurs. 
|
|
jeudi 29 mai 2008 à 18:13:36 |
Re : Performances et pointeurs.

f0xi
|
Réponse acceptée !
normal, l'accés a Scanline du Bitmap est assé long... donc acceder a scanline a chaque boucle est long. en faisant un tableau de ptr avant, permet donc de gagner un peu de temps sinon voici les algo que j'utilise : type pScanLine = ^TScanLine; TScanLine = array[0..32767] of integer; ByteQuad = array[0..3] of byte; ByteTri = array[0..2] of byte; pInt64 = ^Int64;
var BmpBuffer : TBitmap;
{ ------------------------------------------------------------------------ }
procedure Max(const p : pByte; const A,B,C : byte); begin if (A > B) and (A > C) then p^ := A else if (B > C) then p^ := B else p^ := C; end;
procedure Min(const p : pByte; const A,B,C : byte); begin if (A < B) and (A < C) then p^ := A else if (B < C) then p^ := B else p^ := C; end;
procedure Clamp(const p : pByte; const Val,aMin, aMax : integer); begin if Val < aMin then p^ := aMin else if Val > aMax then p^ := aMax else p^ := Val; end;
{ ------------------------------------------------------------------------ }
procedure GrayByMinMax(src, dest : TBitmap; const pCycles: pInt64 = nil); var X,Y : integer; PCS,PCE : int64; pScan : pScanLine; Pix : ByteQuad; Bo,Bm,Bx : byte; begin QueryPerformanceCounter(PCS); Src.PixelFormat := pf32Bit; Dest.PixelFormat := pf32Bit; Dest.Assign(Src); for Y := 0 to Dest.Height-1 do begin pScan := Dest.ScanLine[Y]; for X := 0 to Dest.Width-1 do begin Pix := ByteQuad(pScan[X]); Max(@Bx,Pix[0],Pix[1],Pix[2]); Min(@Bm,Pix[0],Pix[1],Pix[2]); Bo := (Bx + Bm) shr 1; pScan[X] := (Bo shl 16) or (Bo shl 8) or (Bo); end; end; QueryPerformanceCounter(PCE); if pCycles <> nil then pCycles^ := PCE-PCS; end;
{ ------- }
procedure GrayByRGBAverage(src, dest : TBitmap; const pCycles: pInt64 = nil); var X,Y : integer; PCS,PCE : int64; pScan : pScanLine; Pix : ByteQuad; Bo : byte; begin QueryPerformanceCounter(PCS); Src.PixelFormat := pf32Bit; Dest.PixelFormat := pf32Bit; Dest.Assign(Src); for Y := 0 to Dest.Height-1 do begin pScan := Dest.ScanLine[Y]; for X := 0 to Dest.Width-1 do begin Pix := ByteQuad(pScan[X]); Bo := (Pix[0] + Pix[1] + Pix[2]) div 3; pScan[X] := (Bo shl 16) or (Bo shl 8) or (Bo); end; end; QueryPerformanceCounter(PCE); if pCycles <> nil then pCycles^ := PCE-PCS; end;
{ ------- }
const LumRed = 0.2125; LumGreen = 0.7154; LumBlue = 0.0721;
function Lum(const color : integer) : integer; var LC : integer; begin LC := round( (byte(Color)*LumRed) + (byte(Color shr 8)*LumGreen) + (byte(Color shr 16)*LumBlue) ); if LC > 255 then LC := 255 else if LC < 0 then LC := 0; result := integer(LC or (LC shl 8) or (LC shl 16)); end;
{ ------- }
procedure TrueGrayScale(Src : TBitmap; Dest : TBitmap; const pCycles: pInt64 = nil); var PCS,PCE : int64; X,Y : integer; pScan : pScanLine; begin QueryPerformanceCounter(PCS); Src.PixelFormat := pf32bit; Dest.Assign(Src); for Y := 0 to Dest.Height-1 do begin pScan := Dest.ScanLine[Y]; for X := 0 to Dest.Width-1 do pScan[X] := Lum(pScan[X]); end; QueryPerformanceCounter(PCE); if pCycles <> nil then pCycles^ := PCE-PCS; end;
|
|
jeudi 29 mai 2008 à 19:22:47 |
Re : Performances et pointeurs.

f0xi
|
Réponse acceptée !
en fait, voila le code que l'on appel avec ScanLine : -> Scanline[Y] -> GetScanline -> Changing -> condition de verification des limites -> DibNeeded -> GDIFlush -> Retour du pointeur
|
|
jeudi 29 mai 2008 à 19:23:18 |
Re : Performances et pointeurs.

Caribensila
|
Merci pour les algo, f0xi. Ca va me donner du grain à moudre...  Cependant, je crois qu'il y a quand même un truc qui nous échappe, là... Tu dis : « Normal, l'accès a Scanline du Bitmap est assez long... donc acceder a scanline a chaque boucle est long. » Mais si je fais : NB: l'image fait 320x240 pixels pour éviter les ajustements de fin de ligne !!!
Row := Bmp.ScanLine[239]; // 1 seul appel à ScanLine au début du Bmp (coin inf. gauche). for X := 0 to 76799 do begin // 76799 = 320 x 240 - 1 R := Row[X].rgbtRed; G := Row[X].rgbtGreen; B := Row[X].rgbtBlue; Grey := (R+G+B) div 3; Row[X].rgbtRed := Grey; Row[X].rgbtGreen := Grey; Row[X].rgbtBlue := Grey; end;
Ca donne les perfs les plus décevantes! Il n'y a qu'1 seul appel à ScanLine[] et c'est la plus lente de toutes les méthodes ! ! !
J'suis tj dans le brouillard, quoi... 
|
|
jeudi 29 mai 2008 à 21:02:03 |
Re : Performances et pointeurs.

florenth
|
Réponse acceptée !
Salut !
As-tu vu mon code source sur le traitement archi-extra-giga-bref-rapide des bitmaps via scanline ?
Le problème du Row[2X], c'est que chaque emploi demande au CPU de faire l'addition (@Row + X * SizeOf(TRGBTriple)) et de renvoyer le résultat. Et tu l'emploie 6 fois par pixel !
Alors qu'en faisant :
var
Pix: PRGBTriple;
begin
Pix := Bmp.ScanLine[239];
for X := 0 to 76799 do
begin
Grey := (Pix^.rgbtRed + Pix^.rgbtGreen + Pix^.rgbtBlue) div 3;
Pix^.rgbtRed := Grey;
Pix^.rgbtGreen := Grey;
Pix^.rgbtBlue := Grey;
Inc(Pix);
end;
end;
Là, tu as une addition par pixel, au lieu de 6, puisque l'usage d'un pointeur direct sur la mémoire à changer permet d'économiser le temps d'accès que Delphi génère avec ses foutus pseudos-pointeurs-de-tableaux infinis (le array[0..0] est supra lent).
|
|
jeudi 29 mai 2008 à 21:05:05 |
Re : Performances et pointeurs.

florenth
|
Réponse acceptée !
Enfin, pour l'exemple complet, voir ici : http://www.delphifr.com/codes/BON-USAGE-SCANLINE_43222.aspx
Pourvu que ça serve !
|
|
jeudi 29 mai 2008 à 21:54:55 |
Re : Performances et pointeurs.

Caribensila
|
Salut Flo, « http://www.delphifr.com/codes/BON-USAGE-SCANLINE_43222.aspx Pourvu que ça serve ! » Ton exemple... je l'ai imprimé et, de plus, il trône sur ma table de nuit ! Mais il semble que mon niveau ne me l'a pas fait apprécier à 100%. J'aurais eu besoin d'un " vrai" tuto sur les pointeurs en même temps je crois. Désolé.  En tout cas, merci à toi et à f0xi pour mes nouvelles connexions neuronales. J'ai eu un brusque éclair de compréhension grâce à vous! Y'a plus qu'à attendre la pousse des axones... 
|
|
vendredi 30 mai 2008 à 11:40:40 |
Re : Performances et pointeurs.

ThWilliam
|
Réponse acceptée !
Salut.
Tests faits sur gros bitmaps avec le code de Florent en n'appelant qu'1 x Scanline et en incrémentant Pix. C'est environ 2x plus rapide que la méthode classique (appel à Scanline pour chaque ligne du bitmap). De plus, pour peindre un bitmap dans une couleur uniforme, c'est tout aussi rapide que Bmp.Canvas.FillRect ! Dès lors, n'a-ton pas atteint l'optimisation maximale sous Delphi ?
|
|
vendredi 30 mai 2008 à 13:52:39 |
Re : Performances et pointeurs.

Caribensila
|
Salut, « Dès lors, n'a-ton pas atteint l'optimisation maximale sous Delphi ? » Oui, si on considère que Bmp.Canvas.FillRect est le nec plus ultra en matière d'optimisation. J'entrevois cependant une posibilité d'encore diminuer le temps de traitement par deux (au moins théoriquement) : A la condition de disposer d'un Multi Core, c'est de faire une moitié du traitement dans un Thread et l'autre moitié dans un autre Thread. La difficulté étant de partager un Bmp entre 2 Threads. Mais ça doit être jouable. En tout cas, ça vaut le coup d'explorer cette voie car cette technique du multi-threading dans un environnement MultiCore est applicable à tout traitement long. Mais tout cela m'éloigne de ma préoccupation actuelle que sont les pointeurs et ça ne répond toujours pas à ma première question : « Pourquoi l'accès à chaque pixel est plus rapide en passant par un tableau? ». 
|
|
vendredi 30 mai 2008 à 13:55:07 |
Re : Performances et pointeurs.

Kenavo
|
Réponse acceptée !
Le pointer est assez performant à la chasse, mais ses longues périodes d'arrêt font qu'il n'est pas si rapide que ça ! Finalement ! Tout bien pesé !
Ken@vo Code, Code, Codec !
|
|
Cette discussion est classée dans : end, bmp, row, montab, grey
Répondre à ce message
Sujets en rapport avec ce message
Problème de procedure [ par lapucedu88 ]
Voilà je crée une procedure de cette forme : Procedure initordi( chiffre : integer; ordi : TImage; chaine : String );Begin Case chiffre Of 0 :
Message de sauvegarde [ par cincap ]
Bonjour à tous,Est t'il possible de mettre un message d'avertissement au cas ou le fichier bmp ou jpg existerait avant de sauvegarder le nouveau fichi
Utiliser un TopenPictureDialog [ par cincap ]
Bonjour,Je cale sur une application qui charge des images au format Bmp en créant une liste avec un Tcombobox, avant de pouvoir appliquer un effet, se
Envoye d'un BMP par les composants Indy sur un serveur [ par Francky23012301 ]
Salut à tous, J'ai un bmp que je souhaite transferer sur un serveur par les composants Indy. Je vous copie ma source : procedure TForm1.sendstr; var
Pb de conversion emf vers jpg de grandes images [ par macpc ]
Bonsoir à tous,Je suis confronté au problème suivant lors de la conversion de grandes images emf vers jpg, j'obtiens une erreur endofressources:Po
[Erreur Composant] [ par Bacterius ]
Bonsoir, voici un cas fort interessant ... et bizarre. Je prépare un composant graphique descendant de TGraphicControl, une sorte de progressbar pour
Thread [ par barbichette ]
Bonjour lecteurs de ce poste J'ai un petit souci avec les threads... J'ai un thread plus que classique avec un traitement d'une image assez long. D'où
probleme de skin [ par thone08 ]
Bonjour voila j'aimerai realiser un programme ki kand on passe sur le coter gauche sa ouvre un panneau . Pour cela j'ai tester la fonction suivant mai
Besoin d'aide sur un pb de débutant. Trouvez les max et le min de 7 entiers [ par patou248 ]
Voici mon pb.Parmi 7 entiers: A,B,C,D,E,F,GTrouvez les 6 premiers maximums et le min ou si vous préférez les 7 maximums.J'ai le bout de code suivant p
utilisation threads [ par milomax91 ]
Bonjour a tous [^^clinoeil1], J'ai un petit problème, je suis sur la création d'un jeux assez simple. Animaux qui ce promène sur un fond d'écran et o
Livres en rapport
|
Derniers Blogs
UNE JOLIE-HORLOGE ET PAS QU'UN PEU !UNE JOLIE-HORLOGE ET PAS QU'UN PEU ! par neodante
Pour les possesseurs d'iPhone, ça y est Bijin Tokei - qui se traduit littéralement en Français par " Jolie Horloge " - est arrivé et GRATUITEMENT s'il vous plaît ! Après la version Tokyo, Hokkaido, night club, racing, Gal, "pour les mademoiselles'", . voi...
Cliquez pour lire la suite de l'article par neodante TECHDAYS PARIS 2010 : CONNECTEZ VOS DONNéES à SHAREPOINT 2010 AVEC LES BUSINESS CONNECTIVITY SERVICESTECHDAYS PARIS 2010 : CONNECTEZ VOS DONNéES à SHAREPOINT 2010 AVEC LES BUSINESS CONNECTIVITY SERVICES par ROMELARD Fabrice
Animé par: Gaetan Bouveret et Julien Chomarat Business Connectivity Services (BCS) est dans SharePoint 2010 la version 2 de Business Data Catalog (BDC dans SharePoint 2007). Il s'agit de la solution permettant de visualiser des données provenan...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice [DIVERS] SUIVRE VOS SéRIES PRéFéRéS SUR LA TOILE[DIVERS] SUIVRE VOS SéRIES PRéFéRéS SUR LA TOILE par orion
Comme de nombreux geek, je suis un grand amateur de série TV et je rate régulièrement des épisodes de mes séries préférés. Une solution s'offre à vous avec ce merveilleux site : Tv Gorge - www.tvgorge.com Moteur de recherche à l'appui, vous pouvez ...
Cliquez pour lire la suite de l'article par orion TECHDAYS PARIS 2010 : LA BI DANS SHAREPOINT 2010TECHDAYS PARIS 2010 : LA BI DANS SHAREPOINT 2010 par ROMELARD Fabrice
Animé par: Vincent Bellet et Baptiste Giraudier La BI dans SharePoint 2010, Les nouveaux services d'application dans SP2010 et SQL Server Reporting services 2008 R2. La BI dans SharePoint est généralisée pour tous afin de permettre à tous les coll...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice
Logiciels
DB-MAIN (9.1.0)DB-MAIN (9.1.0)DB-MAIN is a data-modeling and data-architecture tool. It is designed to help developers and anal... Cliquez pour télécharger DB-MAIN Xilisoft DPG Convertisseur (5.1.37.0120)XILISOFT DPG CONVERTISSEUR (5.1.37.0120)Xilisoft DPG Convertisseur offre aux fans de Nintendo DS une bonne solution leur permettant de dé... Cliquez pour télécharger Xilisoft DPG Convertisseur GraphicsGale (2.01.01)GRAPHICSGALE (2.01.01)GraphicsGale est un logiciel de PixelArt avec de nombreuse fonctionnalités permettant de réalisé ... Cliquez pour télécharger GraphicsGale Architecte 3D (Platinum 2010)ARCHITECTE 3D (PLATINUM 2010)Architecte 3D Platinium vous permet de concevoir facilement les plans votre future maison, de l'é... Cliquez pour télécharger Architecte 3D TeamViewer 5 (TeamViewer 5)TEAMVIEWER 5 (TEAMVIEWER 5)Dépanner un ami,expliquer une manipulation devient un jeu d'enfant.
Prise en main d'un autre ord... Cliquez pour télécharger TeamViewer 5
|