Optimisations diverses : besoin d'astuces [C/C++] - C - Programmation
Marsh Posté le 29-11-2007 à 12:57:27
oui mais non
paske si cR = 256 soit 0x100, ca donne une fois le masque appliqué 0x00, or moi je voudrais que "cale" sur 0xFF (j'ai pas été super là dessus en fait )
c le même principe que cR %= 256 en fait
Marsh Posté le 29-11-2007 à 13:00:22
Bien sûr. Désolé je me suis trompé. Excusez-moi. Il faut un ou binaire au lieu du et binaire, donc
cR |= 255.
EDIT : NazzTazz a raison le ou binaire ne va pas non plus. Je n'avais pas compris que pour 256, 257, ... l'infini, il fallait avoir 255.
Marsh Posté le 29-11-2007 à 13:17:29
Pour le OU logique oui en effet, les OU "forcent" les bits, mais merci quand meme
Pour ton expression NazzTazz, ca reste un test conditionnel, mais je vais voir quand même comment réagi le compilateur (dans mon j'utilise dev-C++)
EDIT:
testé... et ca revient au même sorry
Pour la petite histoire, je me suis mis en tête de faire une petite routine de bumpmapping 2D avec SDL (demomaking toussa ), et j'affiche le nombre de FPS en temps réel. Si un ou deux FPS en + ou - ne changent rien, si j'en perds ou gagne 10 par ci par là, c bien
Pour info, ma routine tournait à 140-150 FPS sur ma machine du taf (640x480x32 software), et en optimisant des trucs un peu partout, ca devient super spécifique, mais ca tourne maintenant à 210 environ. Et je veux voir jusqu'où on peut aller juste en "grattant" un peu partout
Marsh Posté le 29-11-2007 à 13:45:00
ben oui mais ca "reboucle", si la val passe à 0x100, on se retrouve de nouveau avec 0x00, et moi je voudrais limiter la val à 0xFF au max.
Je me demande si c'est possible en fait de faire en se passant d'un test conditionnel ou d'une re-analyse générale
Marsh Posté le 29-11-2007 à 13:54:02
SICKofitALL a écrit : |
la val passe jamais à 0x100. un char quoi
Marsh Posté le 29-11-2007 à 14:01:39
je suis d'accord, mais en interne il fera un cast et prendra les bits de point faible pour obtenir son char
Marsh Posté le 29-11-2007 à 14:20:05
le coup est lié au branchement potentiel.
regarde le code asm généré, peut-être que le compilo a utilisé un cmov, ce qui fait que l'expression initiale que tu as est efficace.
de toutes manières il faut connaitre l'archi que tu cibles, et ce que le compilo génére.
Marsh Posté le 29-11-2007 à 14:29:43
SICKofitALL a écrit : je suis d'accord, mais en interne il fera un cast et prendra les bits de point faible pour obtenir son char |
nan hein. J'ai un peu de mal à avoir en quoi quelques mov*b* serait plus lent que toutes tes branches ?
Marsh Posté le 29-11-2007 à 14:36:14
ok ok
jvais zieuter le code généré de plus près
Ceci dit, le compilo qui va avec dev-C++ (gcc.exe/g++.exe) ne me semble pas être superbissime, ou alors je m'y prends mal je sais pas, jvais creuser...
Marsh Posté le 29-11-2007 à 14:38:32
on va dire que ton compilateur, si t'as des registres 32bits, il va travailler avec ses registres sans limites. mais chaque fois que nécessaire, il fera la troncature. Genre si tu fais une somme de char, t'auras un registre général de la partie, il n'y aura aucune différence avec une somme d'int, sauf l'instruction finale qui fera le casage correct.
Marsh Posté le 29-11-2007 à 14:50:21
Taz a écrit : |
les mov ne clampent pas
Marsh Posté le 29-11-2007 à 15:21:05
>Taz
Oui mais là je baigne dans le flou
Ca voudrait dire que si je fais :
Code :
|
donc r va être égal à 255 ou alors au "reste", càd 1 ?
Marsh Posté le 29-11-2007 à 15:23:15
bjone a écrit : |
si tu copies que 8 bits, t'as pas l'impression que ça fait la même chose ?
Marsh Posté le 29-11-2007 à 22:04:56
Si le temps est vraiment une question de vie ou de mort, si vous vous moquez de la portabilité comme de l'an quarante, si vous n'etes pas allérgique à l'assembleur et enfin si vous avez du temps à perdre, bah y'a un groupe d'instructions pour 86/amd récent (2003 au moins) qui fait exactement ce que vous voulez en SIMD et tout et tout. Ca s'appelle la saturation. Y'a 3 types d'opérations différentes et elles s'effectuent soit sur les régistres MMX, soit sur les SSE (ces derniers étant toujours plus pratiques à utiliser):
packsswb/dw : juste une simple saturation 8 mots -> 8 octets en même temps (wb), ou 4 double -> 4 mots (dw). Le tout en 2 cyles processeurs.
packuswb : idem en unsigned.
Mais là ou c'est intéressant, c'est une addition en saturation:
paddsb/paddsw : addition + saturation, 8 x 16bits -> 8 x 8bits (wb) ou 4 x 32bits -> 4 x 16 bits (dw). Pas plus couteuse, en 2 cycles aussi.
paddusb/paddusw: idem en unsigned
psubsb/psubsw : soustraction + saturation
psubusb/psubusw: idem en unsigned
Je ne crois pas que l'équivalent avec la mutiplication existe, de toute façon, ça serait inutile. Sinon, en restant en C pur, le plus performant restera de toute façon l'opérateur ternaire (en tous cas pour nos supers processeurs spéculatifs modernes).
cr = (cr > 255)? 255 : cr;
Par contre, je sais pas si j'ai bien compris, mais le fait passer votre cr en unsigned ne permettra pas de récupérer 0 à la place d'un nombre négatif, hein ?
Marsh Posté le 29-11-2007 à 22:09:44
dave_tetehi a écrit : Si le temps est vraiment une question de vie ou de mort, si vous vous moquez de la portabilité comme de l'an quarante, si vous n'etes pas allérgique à l'assembleur et enfin si vous avez du temps à perdre, bah y'a un groupe d'instructions pour 86/amd récent (2003 au moins) qui fait exactement ce que vous voulez en SIMD et tout et tout. Ca s'appelle la saturation. Y'a 3 types d'opérations différentes et elles s'effectuent soit sur les régistres MMX, soit sur les SSE (ces derniers étant toujours plus pratiques à utiliser): |
merci pour ces infos
jme disais bien que ce genre de manips devaient d'une facon ou d'une autre être traité en interne genre TRES interne
sinon oui pour le unsigned on est bien daccord
Marsh Posté le 30-11-2007 à 00:47:50
Taz a écrit : |
bin non, c'est pas un clamp.
Marsh Posté le 30-11-2007 à 00:53:43
dave_tetehi a écrit : Si le temps est vraiment une question de vie ou de mort, si vous vous moquez de la portabilité comme de l'an quarante, si vous n'etes pas allérgique à l'assembleur et enfin si vous avez du temps à perdre, bah y'a un groupe d'instructions pour 86/amd récent (2003 au moins) qui fait exactement ce que vous voulez en SIMD et tout et tout. Ca s'appelle la saturation. Y'a 3 types d'opérations différentes et elles s'effectuent soit sur les régistres MMX, soit sur les SSE (ces derniers étant toujours plus pratiques à utiliser): |
tout à fait, mais j'ai peur qu'un
cr = (cr > 255)? 255 : cr;
soit moins trivial à traduire par un mov conditionnel (dans le cas d'un x86, et peut-être d'autres archi qui peuvent avoir des prédicats sur certaines instructions) de la part du compilo que le bête
if( cr > 255 ) cr = 255;
dans tous les cas, il faut regarder le code produit, et choisir les options de compilation offrant le plus de possibilitées au compilateur.
le mov conditionnel date du ppro, le sse du p3, maintenant si il travaille sur 3 canaux rgb (ou 4 - argb), faire tout l'innerloop en sse, forcément ça le fera mieux.
Marsh Posté le 30-11-2007 à 00:55:46
SICKofitALL a écrit : >Taz
|
pour moi et ma machine 1.
maintenant je sais pas du tout si dans la norme du C y'a un spécification pour les overflows. (et si y'a des archis qui ont un comportement différent en overflow entier)
Marsh Posté le 30-11-2007 à 01:11:46
J'ai trouvé ca sur un site, jvais tester :
Code :
|
c censé limiter les valeurs à la fourchette 0 -> 255, et sans branching donc
Marsh Posté le 30-11-2007 à 01:44:01
Un article là-dessus : http://kristahl.design.free.fr/ind [...] dFRcc46stf
Marsh Posté le 30-11-2007 à 10:23:55
SICKofitALL a écrit : J'ai trouvé ca sur un site, jvais tester :
|
tout à fait
mais dump la sortie assembleur de l'expression classique.
Marsh Posté le 30-11-2007 à 11:12:16
Bon d'un point de vue vitesse de traitement, on y gagne c clair
Par contre ca "reboucle"
Comparez ca à l'image plus haut :
Mais bref c un bon début !
Voila l'asm correspondant tel que VC++ Express me le sort :
Code :
|
Working on it !
Marsh Posté le 30-11-2007 à 11:37:13
ARGHHH damned !
J'ai activé les optimisations dans les props du compilo de VC++, juste pour voir, et :
Donc mon clamp à la one again plus haut est sympa pour l'ego, mais moins rapide en fait
pénible ca
Marsh Posté le 30-11-2007 à 15:24:50
normalement il devrait y avoir moyen de faire un:
mov ebx,255
cmp eax,ebx
cmova eax,ebx
http://www.sesp.cse.clrc.ac.uk/htm [...] h/vc35.htm
a priori y'a pas de de variantes avec un immédiat.
Marsh Posté le 30-11-2007 à 15:26:08
SICKofitALL a écrit : Bon d'un point de vue vitesse de traitement, on y gagne c clair
|
ça reboucle quand la valeur deviens négative (au lieu d'être clampée à 0, elle l'est à 255).
Marsh Posté le 30-11-2007 à 18:42:13
tout à fait, dave_tetehi a proposé une solution sse.
mais quitte à faire du sse, autant retoucher toute la routine de bump.
de toutes manières, dans l'ordre (d'efficacité et d'incompatibilité, enfin d'un point de vue x86):
- hacks binaires
- cmp/cmov
- sse
enfin après faut bencher, yakafaucon
Marsh Posté le 30-11-2007 à 19:30:36
perso, c'ets C à la main -> SSE2 direct. Les hacks à deux balles, c'etait fun en 1880. Maintenant c'est bon
Pareil c'est SSE2 voir SSE3+. MMX c'ets pour le jardin d'enfants.
Marsh Posté le 30-11-2007 à 20:21:07
Petite précision sur le clamp(), si vous voulez vraiment borner entre 0 et 255 (et pas juste 255), il faudra faire:
Code :
|
Mais ce genre de chose, c'est un peu quand même de la prog de grand-père.
Marsh Posté le 30-11-2007 à 21:04:53
calculer en short puis faire un ?: c'ets pas genre 10x ce qu'il faut ? ou j'ai loupé un wagon ?
@dave_tetehi : ca fait bien des années que SSE2 ca se programme plus en assembleur
Marsh Posté le 19-12-2007 à 19:01:43
Joel F a écrit : ca fait bien des années que SSE2 ca se programme plus en assembleur |
Ca se programme avec quoi ?
Marsh Posté le 19-12-2007 à 19:10:28
he, les intrinsics INTEL supportés par Visual Studio, gcc post-3.4 et ICC sont pas fait pour les chiens
sinon y a des outils qui masquent tt ça anyway ( @ sig)
Marsh Posté le 19-12-2007 à 19:31:18
Joel F a écrit : he, les intrinsics INTEL supportés par Visual Studio, gcc post-3.4 et ICC sont pas fait pour les chiens |
Pour les outils Intel, je suis d'accord les intrinsics ça peut etre interressant, pour GCC le code généré est parfois mal optimisé par rapport à du vrai code écrit à la main. Visual Studio... jamais essayé.
Et puis de toute façon écrire avec les intrinsics demande de connaître le jeux d'instruction qu'il y a derrière.
Donc ça demande autant de compétence que d'écrire directement en assembleur.
Ca dépend de l'algorithme à optimiser, mais s'il est crucial pour le programme il vaut peut être mieux coder directement en asm.
Sinon les outils qui masquent tout, soit ils sont pas trés bon, soit ils sont professionnels et coûtent cher ($$$).
Marsh Posté le 19-12-2007 à 20:13:35
sligor a écrit : |
blablabla, ca date de quand ta dernière tentative
sligor a écrit : |
Non, c'ets comme si tu disais que utilisé cos et sin pr faire de la trigo c'etait naze.
Vois le sintrinsic comme des fonctiosn et ca rulez
sligor a écrit : |
Tu dis du caca
Marsh Posté le 19-12-2007 à 20:22:43
Il y a quoi comme outils bien et gratuits pour vectoriser automatiquement du code C standard?
Marsh Posté le 19-12-2007 à 20:44:30
bn c'est fou ce qu'on peut etre largué en quelques mois sur les nouvelles technos, je viens de faire des tests gcc c'est grandement amélioré en vectorisation, mea culpa.
Sinon s'il y a d'autre outils mieux que gcc et gratuits/libres je suis preneur
Marsh Posté le 29-11-2007 à 12:45:58
Salut à tous !
j'ai une question toute bête mais bon
j'ai des variables cR, cG et cB de type int que je veux conserver entre 0 et 255 (pour choper une correspondance de couleur dans une LUT).
Pour n'avoir pas à tester si elles sont inférieurs à 0, j'ai passé le type en unsigned int, c déjà ca de gagner comme cycle machine.
Mais il ya t'il un truc, une astuce (masque binaire ?) pour éviter d'avoir à faire des
Je sais pas c pas super clair, mais bon si vous avez des astuces d'optimisations diverses dans le genre, je suis preneur
---------------
We deserve everything that's coming...