Annonces Google
Serveur IRC
Serveur : irc.portlane.se
Canal : #AmigaNG
Activité du Site

Pages vues depuis 25/07/2007 : 25 186 776

  • Nb. de membres 187
  • Nb. d'articles 1 270
  • Nb. de forums 19
  • Nb. de sujets 20
  • Nb. de critiques 24

Top 10  Statistiques

Index du forum »»  Création-Développement »» Langage C : les unions et l'optimisation

Langage C : les unions et l'optimisation#2391

7Contributeur(s)
thelliersadiruxSharynnsinisrusYesCopOlrickcorto
3 Modérateur(s)
K-LElwoodcorto
thellier thelliericon_post
Soir'

Je vais vous parler d'un truc qui peut servir pour des optimisations en langage C ... que ni Crisot ni Hunoppc ne connaissait.

Imaginons que vous voulez lire des pixels ARGB 32 bits puis les manipuler
Donc vous voudriez voir cette donnée "comme" un ULONG 32bits ou comme 4 UBYTE 8 bits
C'est ce que permet un union : c'est comme une double définition d'une structure

union rgba3D {
struct rgba3DL{
ULONG ARGB32;
} L;
struct rgba3DB{
UBYTE ARGB[4];
} B;
};

si vous avez une variable nommée pix
alors pix.L.ARGB32 donnera accès "comme" un ULONG
et pix.B.ARGB[0] pix.B.ARGB[1] pix.B.ARGB[2] pix.B.ARGB[3] donneront accès aux composantes "comme" un UBYTE

On peut aussi créer un pointeur de ce type et accéder aux pixels en mémoire
union rgba3D *pt;

et faire des trucs du genre avec des registres pour faire comme un pseudo assembleur en C

register union rgba3D *pt;
register union rgba3D pix;
register union rgba3D color;

color.B.ARGB[1]=50;
color.B.ARGB[2]=80;
color.B.ARGB[3]=100;

for(n=0;n!=nbre;n++)
{
pix.L.ARGB32=pt[n].L.ARGB32;
pix.B.ARGB[1]=((UWORD)pix.B.ARGB[1]+(UWORD)color.B.ARGB[1])>1;
pix.B.ARGB[2]=((UWORD)pix.B.ARGB[2]+(UWORD)color.B.ARGB[2])>1;
pix.B.ARGB[3]=((UWORD)pix.B.ARGB[3]+(UWORD)color.B.ARGB[3])>1;
pt[n].L.ARGB32=pix.L.ARGB32;
}

PatchCompositeTags fait un usage intensif de ce genre de manip. encapsulée dans des macros

Bonne Nuit 
Message édité par : thellier / 19-01-2017 00:47
sadirux sadiruxicon_post
Je débute en C, du coup j'ai bien lu un passage sur les Union, mais je content d'en voir un exemple concret :) merci pour ce bout de code ! Même si je ne sais pas pourquoi tu additionnes la couleur primaire d'un pixel pour voir si elle est supérieur à 1 (attention, il est fort possible que je ne comprenne pas ta boucle) ;)


thellier thelliericon_post

Ooouuups tu as tout a fait raison c'étais un >> (une division par 2) que je voulais mettre et non pas un >

L'idée c'est additionner les 2 couleurs (de valeur entre 0 et 255) puis diviser par 2 pour retomber sur une valeur entre 0 et 255 qui tienne à nouveau dans un UBYTE

Au final on a juste une lecture 32bits et une écriture 32 bits à la fin et les autres opérations entre ces deux accès se font sur les registres sans accès mémoire

A noter l'utilisation du pointeur "comme un tableau" en faisant pt[n]. dont on peut espérer que la conversion en assembleur (la compilation quoi) donnera un accès 32 bits indexé par un registre 

du genre

pix.L.ARGB32=pt[n].L.ARGB32;

qui donnerait  en 68000

MOVE.L D1, $0(A1, D0.L)  

ou un truc similaire en PPC


Alain



 

Sam440 - Sam460 - X5000 - PowerBookG4 - WinUAE - MiniMig
Sharynn Sharynnicon_post
Super intéressant !!!

Merci pour cette manip !!


Projet AmOS4 - Retour vers l'Amos sous OS4...

SAM440EP - A1200 3.1 de base
sinisrus sinisrusicon_post
@Thellier

Pourquoi faire une division par 2 alors qu'une multiplication par 0.5 c'est plus rapide (les divisions sont à évité le plus possible)
--
Coin coin... amitheme.amiga-ng.org
Sam460 1,15Ghz - OS4.1FE - Radeon Saphir HD7750 R7 250E - 2Go de ram
YesCop YesCopicon_post
Sinirus,
En fait ce n'est pas considéré comme une divsion mais un décalage de bits beaucoup plus rapide qu'une multiplication.
C'est pourquoi tu vois dans les sources des lignes comme a>>4 plutôt que a/16.

Alain,
Ton code me paraissait faux à cause de pt[n], car non déclaré comme pointeur sur un tableau et non initialisé.
D'après ce que tu as écrit, le compilateur compile comme tu le veux mais le fera-t'il à chaque fois indépendamment du compilateur et/ou de sa version?

Sam Flex 800 Mhz Amiga OS4.1 FE
sadirux sadiruxicon_post
Si je ne dit pas de bétise, l'opérateur >> correspond à un décalage de bit, c'est une autre façon de faire une division et il s'agit à ma connaissance de méthode la plus rapide pour faire une division.

merci de me corriger si je me trompe :)
Olrick Olrickicon_post
Citation: YesCop 

Alain,
Ton code me paraissait faux à cause de pt[n], car non déclaré comme pointeur sur un tableau et non initialisé.

Vois [] comme un opérateur d'accès appliqué à un pointeur sur un type et pas comme une notation dédiée à un type tableau.
pt[n] te renvoie le n + 1 ième élément de type (union rgba3D) à partir de l'adresse contenue dans pt.
pt == &pt[0]
#NUL!
corto cortoicon_post
Même si on mettait "/ 2", le compilateur génèrerait un shift de 1 bit.

Sinon, tu peux même aller plus loin avec les unions, et c'est plus lisible :

union rgba3D{
ULONG argb32;
struct {
                UBYTE a;
                UBYTE r;
                UBYTE g;
                UBYTE b;
        };
};

Ainsi tu peux faire : pixel.argb32 = 0xaabbccdd;
Et lire la composante rouge avec : pixel.r

J'utilise ça pour manipuler des registres système (avec en plus des champs de bits dans la struct interne :-D )

Message édité par : corto / 19-01-2017 17:24
thellier thelliericon_post
Soir'
>Et lire la composante rouge avec : pixel.r
Oui tout à fait meme si au final ça changera rien sur l'ASM généré

>une division par 2 alors qu'une multiplication par 0.5 c'est plus rapide
a) le >>1 est plus rapide qu'un (vrai) /2

b) ici c'est des entiers (UBYTE = unsigned byte = entier 8 bits signé) donc pas possible de faire * 0.5 avec un nombre sans virgule
Sauf si on le convertit mais là on perd notre optimisation

>Ton code me paraissait faux à cause [...] tableau non initialisé.

Il est vrai qu'il est pas intialisé mais bon si j'écrivais tout le code pour récupérer un pointeur sur les pixels de l'écran proprement depuis le système .... on serait pas rendu :-P
C'est un exemple abstrait

>car non déclaré comme pointeur sur un tableau.

Je le redis une fois de plus "en C un pointeur et un tableau à une dimension sont fondamentalement la meme chose lors de leur utilisation"
Si vous avez appris qque chose de différent à la fac alors votre prof parlait sans comprendre l'ASM ;-P

Ainsi pt[0].ARGB32 et pt->ARGB32 sont en fait la meme chose une fois compilee
Une fois assimilée ceci n'importe qui peut comprendre ce qu'est un pointeur


Alain





Sam440 - Sam460 - X5000 - PowerBookG4 - WinUAE - MiniMig
Petites Annonces

0 annonce(s) publiée(s)

Consulter

AmigaOS 4.1

Laissez-vous tenter par
AmigaOS 4.1
AmiTheme

AmiTheme