begin process at 2010 02 10 12:44:53
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Maths & Algorithmes

 > PUISSANCE DE 2, VITESSE ALGO, CONCOURS (WIN32)

PUISSANCE DE 2, VITESSE ALGO, CONCOURS (WIN32)


 Information sur la source

Note :
Aucune note
Catégorie :Maths & Algorithmes Niveau :Débutant Date de création :01/03/2005 Date de mise à jour :02/03/2005 15:20:27 Vu / téléchargé :4 216 / 160

Auteur : BruNews

Ecrire un message privé
Site perso
Ce membre participe au partage de revenus publicitaires
Commentaire sur cette source (75)
Ajouter un commentaire et/ou une note


 Description

Cette fonction retourne la plus proche puissance de 2 >= au param.
Si param == 0 doit retourner 0.
Si param > (2 puiss 31) doit retourner (DWORD) -1;

Prog de test complet dans le zip, suffira de modifier fonctions pour voir les écarts.
Comparatif C et ASM dans le prog, si vous trouvez + rapide sans modifier la boucle de test, prière de publier la fonction dans les comments.

SEULE CONTRAINTE: Pas de table précalculée ni série de 32 'if' ou chose de ce genre pour cause de taille de code.

Le sujet a déjà été étudié sur forum:
http://www.cppfrance.com/forum.v2.aspx?ID=4 02227

A vos claviers et merci de votre participation.



 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !
  •   release
    • PowTwo.exeTélécharger ce fichier [Réservé aux membres club]24 064 octets
  • PowTwo.apsTélécharger ce fichier [Réservé aux membres club]18 264 octets
  • PowTwo.cppTélécharger ce fichier [Réservé aux membres club]Voir ce fichier2 676 octets
  • PowTwo.ncbTélécharger ce fichier [Réservé aux membres club]35 840 octets
  • PowTwo.rcTélécharger ce fichier [Réservé aux membres club]Voir ce fichier2 352 octets
  • PowTwo.slnTélécharger ce fichier [Réservé aux membres club]Voir ce fichier901 octets
  • PowTwo.suoTélécharger ce fichier [Réservé aux membres club]9 216 octets
  • PowTwo.vcprojTélécharger ce fichier [Réservé aux membres club]3 871 octets
  • resource.hTélécharger ce fichier [Réservé aux membres club]Voir ce fichier633 octets

Télécharger le zip


 Historique

02 mars 2005 15:20:28 :
Ajout du test: if(d > 0x80000000) en entrée dans la version C. D'ores et déjà il faut lui préférer la version de JCDjcd ou Matt67.

 Sources du même auteur

Source avec Zip Source avec une capture CALENDRIER (WIN64)
Source avec Zip COMMENTER CODE C <=> ASM (WIN64)
Source avec Zip CHANGEUR DATE FICHIER (WIN32)
Source avec Zip TESTS DE TRIS (WIN32)
Source avec Zip TXT SUPPRIMER LIGNES DOUBLONS (WIN32)

 Sources de la même categorie

Source avec Zip OPERATION SUR LES MATRICES CARREES AVEC CLASSE GENERIQUE par chouhad
Source avec une capture OPÉRATIONS SUR MATRICES C++ par Minilogus
[DEV-C++] CALCUL DE LA RACINE CARRÉE D'UN RÉEL par Jhep
PROGRAMME QUI CALCUL LE PPCM ET LE PGCD par AnoSantino
EVALUER UNE EXPRESSION MATHÉMATIQUE par begueradj

Commentaires et avis

Commentaire de BruNews le 01/03/2005 12:34:39 administrateur CS

Proposé par JCDjcd:

typedef unsigned __int32 U32;
typedef unsigned __int64 U64;
#define B31 0x80000000
#define B63 0x8000000000000000u

typedef U32 TYPE;
#define N   32
/* si on veut tester en 64 bits
typedef U64 TYPE;
#define N   64
*/

DWORD __fastcall Puiss2SupEgal_C(TYPE n)
{
  int i = 0;
  int di = N>>1;
  do {
    if(n >= (((TYPE)1) << (i+di))) i += di;
  } while((di >>= 1) > 0);
  return i;
}

Pas vérifié la validité de la fonction avec le cahier des charges mais est nettement + rapide que l'originale, à peine un peu + de 2 fois celle ASM, vraiment bien.

Commentaire de Matt67 le 01/03/2005 21:32:09

Bonsoir,

Dans le genre court et avec d'assez bonnes perfs :

unsigned Puiss2SupEgal_C(unsigned d)
{
  unsigned Depart = 0x80000000;

  while(((Depart >>= 1) > d));
  Depart <<= 1;

  if(d > 0x80000000) return 0xFFFFFFFF;

  return Depart;
}

Par contre à voir la validité de l'algo de JCDjcd, semble pas correspondre aux "cahiers des charges"

Matt.

Commentaire de BruNews le 01/03/2005 22:48:10 administrateur CS

Manque la verif pour retourner (DWORD) -1 en sortie dans celui de JCDjcd, il me l'avait passé sur le forum par la suite.

Même vitesse que JCDjcd, bravo Matt67 !!!

Commentaire de Urgo le 01/03/2005 22:50:37

BruNews, n'as tu pas oublier de traiter "2 puissance 0" (si je rentre 1, il me retourne 2!)???

Matt67, ta fonction devrait s'appeler "...Puiss2Sup_C..." (sans le Egal)

Je ferai d'autres tests demain...

Commentaire de BruNews le 01/03/2005 23:06:27 administrateur CS

Urgo > rien compris. Y a un cahier des charges, suffit de le respecter.

Commentaire de Urgo le 01/03/2005 23:33:59

Bon, je répète plus clairement :

La fonction de Matt67 ne respecte PAS le cahier des charges (la plus proche puissance de 2 >= au param); car LUI fait : la plus proche puissance de 2 > au param!

Bon, si c'est pas clair tanpis, je vais me coucher, j'ai besoin de repos...

Bye
Urgo

Commentaire de Hylvenir le 01/03/2005 23:43:03

mes essais... avec normalement toutes les spéc respectées (j'ai que la version Initation de 2003 donc je suis pas sûr des params d'optimisations - même si j'ai l'impression que seul l'interface est bloquée pas la compilo lui-même donc le projet garde ces paramètres).


DWORD __fastcall Puiss2SupEgal_C(DWORD n)
{
    DWORD i, n1 = n;
if ( !n ) return 0;
    if ( !( n & n-1 ) ) return (n&1)?2:n;
if ( n > 0x80000000 ) return 0xFFFFFFFF;
if ( n < 0x00008000 ) i = ( n < 0x00000080 )?0x00000080:0x00008000;
else i = ( n < 0x00800000 )?0x00800000:0x80000000;

n1 <<= 1;
while( !( n1 & i ) ) i >>= 1;
    return i;
}

Commentaire de Hylvenir le 01/03/2005 23:49:23

Au fait,
bravo BruNews pour l'animation.
Ca manque quand y'a rien à la télé  ;)

Commentaire de Hylvenir le 01/03/2005 23:55:46

Ma  dernière version liftée ;) et c'est l'heure du dodo.
Je ne vois plus comment améliorer sans changer l'algo de toute façon.
(tests : ASM 740000, C : 1280000, ASM vainqueur ;) )

DWORD __fastcall Puiss2SupEgal_C(DWORD d)
{
DWORD i, n1 = d, d1 = d - 1;
if ( !d ) return 0;
if ( !( d & d1 ) ) return (d&1)?2:d;
if ( d > 0x80000000 ) return 0xFFFFFFFF;
if ( d < 0x00008000 ) i = ( d < 0x00000080 )?0x00000080:0x00008000;
else i = ( d < 0x00800000 )?0x00800000:0x80000000;

n1 <<= 1;
while( !( n1 & i ) ) i >>= 1;
    return i;
}

Commentaire de BruNews le 02/03/2005 00:09:35 administrateur CS

Hylvenir pas mal du tout, très voisin des 2 autres pour les perfs.

Urgo > ok compris cette fois, faudrait vérifier mais comme je fais cela en bossant (pas trop ce jour mais tout de même un peu) j'ai pas le temps de tout analyser.

Commentaire de Urgo le 02/03/2005 14:52:37

BruNews, lorsque je rentre 4294967295 (0xFFFFFFFF), ton algo (en C) "plante"... et me retourne rien!
Alors qu'avec l'ago en ASM, aucun problème...!

Normal ou pas?

Bye
Urgo

Commentaire de BruNews le 02/03/2005 15:04:42 administrateur CS

oh oui me semble bien rien qu'en regardant le code que tu as tout a fait raison.
Je vais mettre le est > 0x80000000 en entree et maj du zip.

Commentaire de Urgo le 02/03/2005 15:57:48

// Version de Matt67 corrigée
DWORD __fastcall MyPuiss2SupEgal_C(DWORD d)
{
DWORD r = 0x80000000;
if(!d) return 0;
if(d > r) return 0xFFFFFFFF;
if(d == 1) return 2;
while((r >>= 1) >= d);
r <<= 1;
return r;
}

Commentaire de Matt67 le 02/03/2005 17:08:55

Merci Urgo, je rentre du boulot et j'allais la poster (exactement la même !!!).

Par contre avez vous regardé le code de JCDjcd, il me semble qu'il y avait un petit problème dans le retour de sa fonction ?
(Il me semble qu'il renvoyait l'exposant à 2)

Matt...

Commentaire de Urgo le 02/03/2005 17:47:03

Code de JCDjcd ne respecte pas du tout le cahier des charges effectivement...

D'après mes tests, Hylvenir est pour l'instant le premier avec son ALGO, il dépasse même la version ASM de BruNews (chez vous aussi?)... Enfin... je ne suis pas certain que mes tests soient exacts, donc pas taper svp! :)

Commentaire de JCDjcd le 02/03/2005 20:05:17

MaxPow2_v1 00000000 : 0
MaxPow2_v1 00000001 : 0
MaxPow2_v1 00000002 : 1
MaxPow2_v1 000003E8 : 9
MaxPow2_v1 FFFFFFF6 : -1
MaxPow2_v1 80000000 : -1
MaxPow2_v1 7FFFFFFF : 30

MaxPow2_v2 00000000 : 0
MaxPow2_v2 00000001 : 0
MaxPow2_v2 00000002 : 1
MaxPow2_v2 000003E8 : 9
MaxPow2_v2 FFFFFFF6 : -1
MaxPow2_v2 80000000 : -1
MaxPow2_v2 7FFFFFFF : 30

Commentaire de Matt67 le 02/03/2005 21:02:22

Bonsoir,

j'ai fait quelques tests sur un interval de 0 à 0x80000000

  QueryPerformanceCounter(&lideb);
  for(i=0; i<0x80000000; i++)
    r = Puiss2SupEgal_C(i);
  QueryPerformanceCounter(&lifin);

resultat (3 tests par fonctions) :
Fonction de Hylvenir :
101.364.469.072
101.339.293.005
101.459.063.767

Fonction de Matt corrigé par Urgo :
70.031.666.940
70.005.492.802
70.004.897.692

Fonction ASM :
42.974.330.512
42.914.916.886
43.126.926.097

Et vous ?

Matt...

Commentaire de BruNews le 02/03/2005 22:29:53 administrateur CS

Je confirme, algo de Matt67 est le meilleur tous, 30% sur asm y compris.

Commentaire de Hylvenir le 02/03/2005 22:36:55

Bonsoir, alors après quelques tests mon point suit.
Mais d'abord, je n'arrive pas à valider la fonction ASM original
(mes résultats sont faux), mais elle peut être plus lente que le C de Matt (cf plus bas).
Au niveau des perfs, faudrait se mettre d'accord sur 'performance' (sûrement en moyenne).
Pour faire le test de perf, j'ai utilisé une boucle sur toutes les valeurs possibles. ( 0 à 4 milliards environ ).
Ce qu'on peut voir, c'est que la moitié des valeurs son invalides (  n > 0x80000000 ), donc une bonne solution serait de tester rapidement ce cas et sortir ( comme Matt ), ensuite les valeurs valides ont plus souvent des bits élevés. ( 0x8FFF0000 ce mask doit représenter 80% des valeurs valides).
En conclusion pour faire un truc rapide :
1. traiter un priorité les 50% des valeurs en erreur.
(n > 0x80000000 par exemple)
2. traiter les bits de poids fort en priorité.
(le plus rapidement possible comme Matt )

Voici le source utilisé ( mode console avec vérification si argc > 1 ) compilé avec gcc (cl j'ai pas les optimisations)

http://hylvenir.free.fr/data/puissance.cpp  

Voici les temps que j'obtiens
C1 : 39sec 46ms   ( Version Brunews )
C2 : 71sec 293ms ( Version JCDjcd )
C3 : 27sec 950ms ( version Hylvenir)
C4 : 26sec 828ms ( Version Matt )

Pour info la version ASM tourne moins vite que la version C  de brunews. La version de Matt et la mienne tourne environ aussi vite selon.

Pour l'ASM, je ne sais pas si c'est normal que ça ne fonctionne pas. Pour le tester vous même il suffit de copier/coller le code asm dans une des fonctionc C1..4
et lancer l'exe avec un argument quelconque.
Brunews une idée ? est-ce le résultat peut dépendre de la manière de compiler ?
A t-on des précisions sur la nature des valeurs en entrée ?

Commentaire de Urgo le 02/03/2005 22:44:38

D'accord avec Matt67... Bien joué ;)

Commentaire de BruNews le 02/03/2005 23:09:54 administrateur CS

Pour compiler l'ASM, faut que soit absolument certain que le compilo ne t'insère pas une stackframe sinon bien sur c'est foutu d'avance pour les perfs, pour cela que __declspec(naked) sur VC++ et ainsi compilo n'y touche pas du tout, avec gcc je ne sais pas comment tu peux faire.
J'ai refait des tests et y a pas photo, Matt67 l'emporte haut la main.

Commentaire de JCDjcd le 02/03/2005 23:11:11

il existe deux manieres differentes de tester les performances, soit les nombres de departs sont uniformes, soit le resultat est uniforme
1er methode : Pow2(Random(0,0x80000000))
2nd methode : Pow2(1<<(Random(0,31)))

les performances changerons.

Commentaire de Hylvenir le 02/03/2005 23:39:13

Brunews, ok pour l'ASM, je vais essayer avec __declspec(naked) . je vais voir si la beta 2005 accepte les optimisations (faut que je réinstalle).

Voici ma dernière version, je ne peux la tester sur cl pour le moment mais elle est pas trop mal.
( en testant  le temps mis sur un cycle complet des 4 milliards, j'essaye selon tes randoms JCDjcd )

U32 Puiss2SupEgal_C3(U32 n)
{
  if ( n > 0x80000000 ) return 0xFFFFFFFF;
  if (  n & ( n - 1 ) )
  {
     U32 i = 0x80000000, n1 = n;
      n1 <<= 1;
      while( !( n1 & i ) ) i >>= 1;
      return i;  
  }
  return (n&1)?2:n;
}

En tout cas c'était rigolo j'ai appris pas mal sur ce simple exercice.

Commentaire de Hylvenir le 03/03/2005 00:25:17

Brunews, ok merci c'est marche maintenant.

Avec un 'faux' cl voici mes derniers résultat
MIN 0, MAX 4294967294
C1 : 63sec 40ms     (Brunews C )
C2 : 36sec 884ms   (Brunews ASM)
C3 : 41sec 980ms   (Hylvenir)
C4 : 47sec 218ms   (Matt)

Commentaire de JCDjcd le 03/03/2005 01:00:54

En fait tout depend de la facon de tester et du choix de la taille des nombres.

Commentaire de Hylvenir le 03/03/2005 08:35:36

1h??? tu dors jamais ? ;)
En fait, ça dépend de beauoup de chose en effet.

je n'ai utilisé que ton premier jeu de test (cas n°1).
C'est en gros le temps moyen que peut attendre l'utilisateur s'il lit des données au hasard.  Un simple chronometrage pour tester le temps à la faire.

J'ai remis une version (ASM compris)
http://hylvenir.free.fr/data/puissance.cpp

Je serai intrigué de savoir si vous trouvez des résultats différents avec une compilation cl /O2 par exemple.
Bonne journée de boulot ;)

Commentaire de JCDjcd le 03/03/2005 11:21:45

"s'il lit des données au hasard", justement tout est la dedans, si on teste le temps mis pour une boucle de 0 a 4milliards, alors le programme repondera -1 dans la moitie des cas, donc un teste au debut du programme et c'est fini, par contre si on s'amuse a comparer combien de temps mettent les algo. pour repondre au nombre 5, alors surement les performance seront differentes, car il faut faire 30 fois la boucle (5 fois la boucle dans ma version), donc les perfs. vont diminuer.

Commentaire de Hylvenir le 03/03/2005 11:50:58

Tout à fait d'accord,
dans les tests, je fais aussi des boucles sur les valeurs extrèmes et médianes.
( valeurs entre 0 + 500, entre 0xFFFF et 0xFFFF + 500,
et 0xFFFFFFF et 0xFFFFFFF + 500 )
mais je ne les ais pas postés.
Ca permet de voir tout de suite la puissance de l'ASM dans ce cas.

Commentaire de garslouche le 03/03/2005 13:41:17

Je ne suis pas spécialiste des optimisations mais avez-vous essayé avec la fonction log ?

pow( 2, (int) ( log(param) / log(2) ) + 1 )

(bien sur pow n'est pas la fonction adaptée - puisque c'est pour les double - mais c'est l'idée...)

Commentaire de JCDjcd le 03/03/2005 16:44:23

on a les droit d'utiliser des doubles ?

Commentaire de BruNews le 03/03/2005 17:16:47 administrateur CS

Seul compte que l'algo soit le plus performant possible.
Mis bon, rien que le temps de chargement en fpu (fild) puis dans l'autre sens (fistp), je n'ai même pas eu envie d'essayer. Ceci dit faudrait tester.

Commentaire de NitRic le 07/03/2005 03:00:30

C'est bon ca? Ca respect le cahier des charges?


#include <stdio.h>

#ifdef __cplusplus
extern "C" {
#endif

/* ca pourait très bien être une macro aussi:

#define PUISSANCE_2(x) ((x+0x00000001u) & ~(0x00000001u))

unsigned i = PUISSANCE_2(21);

*/
__inline
unsigned puissance_2( unsigned x ) {
if ( x < (((unsigned)-1)-1) )
return ( (x + 0x00000001u) & ~(0x00000001u) );
return (unsigned)-1;
}

#ifdef __cplusplus
}
#endif

int main()
{

  unsigned i;

  for ( i = 0u; i < ((unsigned)-1); i++ )
    printf("%u, ", puissance_2( i ));

  return 0;

}


désolé s'il y à des fautes de frappe, j'ai fait ca online



~(.:: NitRic ::.)~

Commentaire de NitRic le 07/03/2005 03:10:36

Correction:

__inline
unsigned puissance_2( unsigned x ) {
  if ( x < (unsigned)-1 ) {
    return ( (x + 0x00000001u) & ~(0x00000001u) );
  }
  return (unsigned)-1;
}




~(.:: NitRic ::.)~

Commentaire de NitRic le 07/03/2005 04:29:43

Autre correction:

__inline static
unsigned puissance_2( unsigned x )
{
  if ( x < (unsigned)-1 )
  {
    x = ( (x + 0x00000001u) & ~(0x00000001u) );
  }
  return x;
}

j'ai testé les différents algos présenté ici(version final)

je n'ai qu'un petit K7 550(génération P3) alors les résultat sont un peu plus élevés que les votre mais au final, ca revient au même

NitRic: 38.18 sec (38184 ms) - 0
BruNews_ASM: 138.16 sec (138159 ms) - 2
BruNews_C: 138.46 sec (138459 ms) - 0
Matt67: 125.98 sec (125981 ms) - 0
Hylvenir: 139.06 sec (139060 ms) - 0
Press any key to continue

le chiffre à la fin de chaque ligne c'est la valeur retourné de chaque fonction pour la valeur 0



au fait, si j'suis complètement dans l'champ avec mes affaires, faut me le dire hein!

voilà mon code:

/* main.c */
#include <stdio.h>
#include <time.h>


__declspec(naked) unsigned BruNews_ASM(unsigned d)
{
  __asm {
    cmp     ecx, 80000000h
    ja      short puissExit
    mov     eax, ecx
    cmp     eax, 1
    jb      short puissExit
    ja      short nbrOK
    inc     eax
nbrOK:
    mov     edx, eax
    bsr     ecx, eax
    mov     eax, 1
    shl     eax, cl
    cmp     eax, edx
    jae     short puissExit
    shl     eax, 1
    jnz     short puissExit
;moinsUn: ; << warning C4102: 'moinsUn' : unreferenced label
    mov     eax, -1
puissExit:
    ret     0
  }
}

unsigned __fastcall BruNews_C(unsigned d)
{
  unsigned r, n;
  if(!d) return 0;
  if(d > 0x80000000) return 0xFFFFFFFF;
  if(d & 1) d++;
  r = 0x80000000;
  n = d;
  if(d & 0x80000000) goto verifInf;
  do {
    r >>= 1;
    d <<= 1;
  } while(!(d & 0x80000000));
verifInf:
  if(r < n) r <<= 1;
  if(!r) r = 0xFFFFFFFF;
  return r;
}

unsigned __fastcall Matt67(unsigned d)
{
unsigned r = 0x80000000;
if(!d) return 0;
if(d > r) return 0xFFFFFFFF;
if(d == 1) return 2;
while((r >>= 1) >= d);
r <<= 1;
return r;
}

unsigned Hylvenir(unsigned n)
{
unsigned i, n1;
  if ( n > 0x80000000 ) return 0xFFFFFFFF;
  if (  n & ( n - 1 ) )
  {
     i = 0x80000000, n1 = n;
      n1 <<= 1;
      while( !( n1 & i ) ) i >>= 1;
      return i;  
  }
  return (n&1)?2:n;
}

__inline static
unsigned puissance_2( unsigned x )
{
  if ( x < (unsigned)-1 )
  {
    x = ( (x + 0x00000001u) & ~(0x00000001u) );
  }
  return x;
}

int main( int argc, char * argv[] )
{

unsigned i, a;
clock_t s, e;

i = (unsigned)-1;
a = 0u;

s = clock();
do {
a = puissance_2( i );
}while ( i-- );
e = clock();

printf("NitRic: %4.2f sec (%u ms) - %u\n", (e-s)/(double)CLOCKS_PER_SEC, (e-s), a);

i = (unsigned)-1;
a = 0u;

s = clock();
do {
a = BruNews_ASM( i );
}while ( i-- );
e = clock();

printf("BruNews_ASM: %4.2f sec (%u ms) - %u\n", (e-s)/(double)CLOCKS_PER_SEC, (e-s), a);

i = (unsigned)-1;
a = 0u;

s = clock();
do {
a = BruNews_C( i );
}while ( i-- );
e = clock();

printf("BruNews_C: %4.2f sec (%u ms) - %u\n", (e-s)/(double)CLOCKS_PER_SEC, (e-s), a);

i = (unsigned)-1;
a = 0u;

s = clock();
do {
a = Matt67( i );
}while ( i-- );
e = clock();

printf("Matt67: %4.2f sec (%u ms) - %u\n", (e-s)/(double)CLOCKS_PER_SEC, (e-s), a);

i = (unsigned)-1;
a = 0u;

s = clock();
do {
a = Hylvenir( i );
}while ( i-- );
e = clock();

printf("Hylvenir: %4.2f sec (%u ms) - %u\n", (e-s)/(double)CLOCKS_PER_SEC, (e-s), a);

return 0;

}


Je n'ai modifié que le nom des types, changé les U32/DWORD pour un unsigned

j'aurais peut-être utilisé votre QueryPerformanceCounter() mais vue les résultats, clock() suffisait amplement je crois ...

voilà, c'est tout


~(.:: NitRic ::.)~

Commentaire de NitRic le 07/03/2005 04:50:37

au fait BruNews, à ton premier jump(ja) dans ta fonction en ASM, j'crois que tu as oublié `eax`, c'est possible?

__asm {
  cmp ecx, 80000000h
  ja puissExit
  ; ...
  mov eax, -1
puissExit:
  ret 0
}

un label en plus ou un ajout au début devrait aider mais bon, j'suis pas expert en ASM alors j'dis peut-être n'importe quoi :}



~(.:: NitRic ::.)~

Commentaire de BruNews le 07/03/2005 08:56:28 administrateur CS

Salut NitRic,

pour ASM bonne remarque, il faut bien sur inverser la 2eme et 3eme ligne.

Ai-je mal transcrit ton code ??? pour 513 en entrée, il me sort 514 au lieu de 1024.

A propos du inline, même pas la peine de l'indiquer explicitement, dès le début j'avais vu que le compilo insère le C direct en inline sans rien lui demander (faut bien sur compiler avec les optimisations mais allait sans dire). Pour avoir des comparaison vraiment valables, faudrait donc que je réécrive ASM en format macro sinon dans l'état actuel il me met une stackframe à tout coup (bourrique de compilo..). Je corrigerai tout cela dès que je ne serai plus aux 35h de repos par semaine...

Commentaire de NitRic le 07/03/2005 17:46:23

Non, c'est moi qui n'est pas bien compris le `cahier des charges` je crois. Ma fonction renvoie les nombres paires, c'est à dire: 0, 2, 4, 6, 8, 10, 12, ... Il arrondit si on veut. Le prochain multiple >= 2. On dirait que mon cerveau à traduit `puissance` par `multiple` :} bref, j'vais corriger ma fonction et la reposter à nouveau.

Pour le `__inline`, moi j'en ai besoin, j'aime pas le laisser mettre ce qu'il veut `inline`. Pour ce qui est de ta stackframe, ici, VS6 n'en met pas, ton code est clean mais c'est vrai qu'en macro ca pourait être bien, un call en moin :}



~(.:: NitRic ::.)~

Commentaire de NitRic le 07/03/2005 17:59:53

Voilà, code corrigé:

__inline
unsigned puissance_2( unsigned x ) {
  if ( x < (unsigned)-1 )
  {
    x = (( (x + 0x00000001u) & ~(0x00000001u) ) * 2 );
  }
  return x;
}

on arrondit(prochain multiple >= 2) et ensuite *2

  for ( i = 0u; i < 513; i++ )
    printf("%u, ", puissance_2( i ));

résultat:

0, 4, 4, 8, 8, 12, 12, 16, 16, 20, 20, 24, 24, 28, 28, 32, 32, 36, 36, 40, 40, 4
4, 44, 48, 48, 52, 52, 56, 56, 60, 60, 64, 64, 68, 68, 72, 72, 76, 76, 80, 80, 8
4, 84, 88, 88, 92, 92, 96, 96, 100, 100, 104, 104, 108, 108, 112, 112, 116, 116,
120, 120, 124, 124, 128, 128, 132, 132, 136, 136, 140, 140, 144, 144, 148, 148,
152, 152, 156, 156, 160, 160, 164, 164, 168, 168, 172, 172, 176, 176, 180, 180,
184, 184, 188, 188, 192, 192, 196, 196, 200, 200, 204, 204, 208, 208, 212, 212,
216, 216, 220, 220, 224, 224, 228, 228, 232, 232, 236, 236, 240, 240, 244, 244,
248, 248, 252, 252, 256, 256, 260, 260, 264, 264, 268, 268, 272, 272, 276, 276,
280, 280, 284, 284, 288, 288, 292, 292, 296, 296, 300, 300, 304, 304, 308, 308,
312, 312, 316, 316, 320, 320, 324, 324, 328, 328, 332, 332, 336, 336, 340, 340,
344, 344, 348, 348, 352, 352, 356, 356, 360, 360, 364, 364, 368, 368, 372, 372,
376, 376, 380, 380, 384, 384, 388, 388, 392, 392, 396, 396, 400, 400, 404, 404,
408, 408, 412, 412, 416, 416, 420, 420, 424, 424, 428, 428, 432, 432, 436, 436,
440, 440, 444, 444, 448, 448, 452, 452, 456, 456, 460, 460, 464, 464, 468, 468,
472, 472, 476, 476, 480, 480, 484, 484, 488, 488, 492, 492, 496, 496, 500, 500,
504, 504, 508, 508, 512, 512, 516, 516, 520, 520, 524, 524, 528, 528, 532, 532,
536, 536, 540, 540, 544, 544, 548, 548, 552, 552, 556, 556, 560, 560, 564, 564,
568, 568, 572, 572, 576, 576, 580, 580, 584, 584, 588, 588, 592, 592, 596, 596,
600, 600, 604, 604, 608, 608, 612, 612, 616, 616, 620, 620, 624, 624, 628, 628,
632, 632, 636, 636, 640, 640, 644, 644, 648, 648, 652, 652, 656, 656, 660, 660,
664, 664, 668, 668, 672, 672, 676, 676, 680, 680, 684, 684, 688, 688, 692, 692,
696, 696, 700, 700, 704, 704, 708, 708, 712, 712, 716, 716, 720, 720, 724, 724,
728, 728, 732, 732, 736, 736, 740, 740, 744, 744, 748, 748, 752, 752, 756, 756,
760, 760, 764, 764, 768, 768, 772, 772, 776, 776, 780, 780, 784, 784, 788, 788,
792, 792, 796, 796, 800, 800, 804, 804, 808, 808, 812, 812, 816, 816, 820, 820,
824, 824, 828, 828, 832, 832, 836, 836, 840, 840, 844, 844, 848, 848, 852, 852,
856, 856, 860, 860, 864, 864, 868, 868, 872, 872, 876, 876, 880, 880, 884, 884,
888, 888, 892, 892, 896, 896, 900, 900, 904, 904, 908, 908, 912, 912, 916, 916,
920, 920, 924, 924, 928, 928, 932, 932, 936, 936, 940, 940, 944, 944, 948, 948,
952, 952, 956, 956, 960, 960, 964, 964, 968, 968, 972, 972, 976, 976, 980, 980,
984, 984, 988, 988, 992, 992, 996, 996, 1000, 1000, 1004, 1004, 1008, 1008, 101
2, 1012, 1016, 1016, 1020, 1020, 1024, 1024, Press any key to continue

pour ce qui est du temps d'exécution, il n'y à que ~5sec en plus, il reste le plus rapide, !?!?YOUPI!?!?



~(.:: NitRic ::.)~

Commentaire de BruNews le 07/03/2005 18:06:01 administrateur CS

pressé de tester ce code ce qui sera fait dans la soirée

Commentaire de Hylvenir le 07/03/2005 18:07:18

12, 20, 24 ? étrange puissance de 2 s'il en est ;)

Commentaire de NitRic le 07/03/2005 20:33:42

Je sais pas si tu le savais Hylvenir mais, tu as raison ...

J'avais fait une comparaison avec celle de Matt67 mais, j'ai du me tromper et appeler deux fois _ma_ fonction ...

J'vais retourner penser ...



~(.:: NitRic ::.)~

Commentaire de NitRic le 07/03/2005 22:29:31

Hey! Encore moi. Cette fois c'est la bonne:

#define ALIGN(x,y) ( x = ((x + (y - 0x00000001u)) & ~(y - 0x00000001u)) )

__inline
unsigned puissance_2( unsigned x )
{

    register unsigned y;

    if ( x < 0x80000000 && ALIGN(x, 2) )
    {

        y = 0x80000000;
        do
        {
        } while ( (y >>= 1) >= x );
        x = (y << 1);

    }

    return ( (x <= 0x80000000) ? x : 0xffffffffu );

}

Voilà, j'essais encore de trouver une méthode sans boucle mais c'est pas simple et j'commence à croire que c'est impossible d'avoir quelque chose de rapide/efficace/safe/... sans boucle mais bref, voilà, j'ai regardé vos exemples et j'ai fais une version `optimisée`:

NitRic: 80.59 sec (80595 ms) - 0
BruNews_C: 117.68 sec (117680 ms) - 0
Matt67: 108.11 sec (108105 ms) - 0
Hylvenir: 137.15 sec (137147 ms) - 0

J'ai perdu ~25sec avec la boucle mais bon, mieux vaut quelque chose de fonctionnel et ~rapide, que quelque chose de ~fonctionnel et rapide!

Ma fonction, pour la valeur 0, retourne 0, pour une valeur suppérieure à 0x80000000 retourne 0xffffffff

Donc, possibilitées: 0-0x80000000 ou 0xffffffff




~(.:: NitRic ::.)~

Commentaire de Matt67 le 08/03/2005 09:02:08

Bonsoir,

j'ai fait quelques tests sur un interval de 0 à 0x80000000

  QueryPerformanceCounter(&lideb);
  for(i=0; i<0x80000000; i++)
    r = Puiss2SupEgal_C(i);
  QueryPerformanceCounter(&lifin);

resultat (3 tests par fonctions)
NitRic
85356885810
85092196462
85845629587

Matt67
70374001567
70883189797
70309812128

donc c'est pas encore gagné pour toi NitRic,

Matt...

Commentaire de NitRic le 08/03/2005 16:41:42

Comment fais-tu pour arriver à ce résultat? Moi j'obtient ceci:

NitRic: 44.24 sec (44243 ms) - 2147483648
Matt67: 78.13 sec (78132 ms) - 2147483648

Presque le double!?!?!?!?

C'est bien ta fonction ca?:

unsigned __fastcall Matt67(unsigned d)
{
unsigned r = 0x80000000;
if(!d) return 0;
if(d > r) return 0xFFFFFFFF;
if(d == 1) return 2;
while((r >>= 1) >= d);
r <<= 1;
return r;
}


TEST:

  s = clock();
    for ( i =0; i < 0x80000000; i++ )
      a = puissance_2( i );
  e = clock();
  printf("NitRic: %4.2f sec (%u ms) - %u\n", (e-s)/(double)CLOCKS_PER_SEC, (e-s), a);

  s = clock();
    for ( i =0; i < 0x80000000; i++ )
      a = Matt67( i );
  e = clock();
  printf("Matt67: %4.2f sec (%u ms) - %u\n", (e-s)/(double)CLOCKS_PER_SEC, (e-s), a);


Avec le QueryPerformanceCounter() j'obtient ceci:

NitRic: 109646232
Matt67: 281617198
Press any key to continue

  LARGE_INTEGER begin, end;

  /*s = clock();*/
  QueryPerformanceCounter(&begin);
    for ( i =0; i < 0x80000000; i++ )
      a = puissance_2( i );
  QueryPerformanceCounter(&end);
  printf("NitRic: %u\n", (end.QuadPart - begin.QuadPart));
  /*e = clock();
  printf("NitRic: %4.2f sec (%u ms) - %u\n", (e-s)/(double)CLOCKS_PER_SEC, (e-s), a);*/

  /*s = clock();*/
  QueryPerformanceCounter(&begin);
    for ( i =0; i < 0x80000000; i++ )
      a = Matt67( i );
  QueryPerformanceCounter(&end);
  printf("Matt67: %u\n", (end.QuadPart - begin.QuadPart));
  /*e = clock();
  printf("Matt67: %4.2f sec (%u ms) - %u\n", (e-s)/(double)CLOCKS_PER_SEC, (e-s), a);*/

  return 0;


la version de ma fonction avec laquelle j'ai testé:
__inline
unsigned puissance_2( unsigned x )
{

  register unsigned y;

  if ( x < 0x80000000 && ALIGN(x, 2) )
  {

    y = 0x80000000;
    do
    {
    } while ( (y >>= 1) >= x );
    x = (y << 1);

  }

  return ( (x <= 0x80000000) ? x : 0xffffffffu );

}


J'aimerais bien comprendre ...


~(.:: NitRic ::.)~

Commentaire de NitRic le 08/03/2005 17:38:20

d'autres tests:

sans __inline
NitRic:   204736449
Matt67: 228632458
Press any key to continue


les deux __inline
NitRic:   95553604
Matt67: 113568378
Press any key to continue


J'arrive toujours pas à comprendre par contre. Même en regardant le source ASM généré derrière, on voit tout de suite tous les `jump/ret/...` dans ta fonction, pour les valeurs 0 et > 0x80000000 il fait ~trois `jump`, or, dans la mienne, aucun, sauf si > 0x80000000. Ta fonction et la mienne ce ressemble beaucoup, en ASM, le code est identique à l'exception de tes trois `jump` au début, or, un `jump` est loin d'être ce qu'il y à de plus performant. Dans nos tests, on test des valeurs valide, 0-0x80000000 donc, dans ma fonction: 1 `jump`, dans la tienne, 1+ `jump` ... Comment des `jump` peuvent ils arriver à `accelérer` l'exécution d'une fonction !?


Le source ASM des deux fonctions(non __inline):

La mienne:
_puissance_2 PROC NEAR
  mov eax, DWORD PTR _x$[esp-4] ; met x dans `eax`
  cmp eax, -2147483648  ; 80000000H
  jae SHORT $L20692 ; si > 0x80000000 => JUMP (une fois)
  inc eax
  and eax, -2  ; fffffffeH ; ALIGN(x, 2)
  je SHORT $L20491 ; si == 0 => JUMP (une fois)
  mov ecx, -2147483648  ; 80000000H ; aide pour la vitesse d'accès

$L20492: ; et la tite boucle, on est arrivé rapidement non?
  shr ecx, 1
  cmp ecx, eax
  jae SHORT $L20492
  lea eax, DWORD PTR [ecx+ecx] ; x = (y << 1)

$L20491:
  cmp eax, -2147483648  ; 80000000H

$L20692:
  jbe SHORT $L20690
  or eax, -1  ; si > 0x80000000

$L20690:
  ret 0
_puissance_2 ENDP



La tienne:
@Matt67@4 PROC NEAR
  test ecx, ecx  ; si pas zéro => JUMP
  jne SHORT $L20469
  xor eax, eax ; met à zéro et => return 0;
  ret 0

$L20469:
  cmp ecx, -2147483648  ; si <= 80000000H => JUMP
  jbe SHORT $L20470
  or eax, -1 ; return 0xffffffffu;
  ret 0

$L20470:
  cmp ecx, 1
  jne SHORT $L20681 ; si != 1 => JUMP
  mov eax, 2 ; return 2;
  ret 0

$L20681: ; un premier test avant d'entrer dans la boucle
  mov eax, 1073741824  ; 40000000H
  cmp ecx, eax
  ja SHORT $L20474

$L20473: ; et la tite boucle ici, enfin arrivé après trois JUMP
  shr eax, 1
  cmp eax, ecx
  jae SHORT $L20473

$L20474:
  add eax, eax ; r <<= 1;
  ret 0
@Matt67@4 ENDP



Comme j'ai déjà dis, j'suis pas expert en ASM mais j'ai quand même quelques bases et ces quelques bases me disent que des `jump` n'accelère pas l'exécution d'une fonction ...

Je ne pas veux pas avoir la fonction la plus rapide mais simplement arriver à comprendre :/

BruNews à l'air de connaître l'ASM, il pourait peut-être donner son avis!?



~(.:: NitRic ::.)~

Commentaire de BruNews le 08/03/2005 19:14:30 administrateur CS

Mais si, si on jmp sur une sortie directe c'est par force meilleur.
Regarde dans la tienne:
cmp eax, -2147483648  ; 80000000H
jae SHORT $L20692
donc si >= on s'en va dans la boucle, non il faudrait à la place:
cmp eax, -2147483648  ; 80000000H
je SHORT SortieDirecte ; valeur non modifiée
ja short SortieMoinsUn
; ici on entre dans la boucle

Commentaire de NitRic le 08/03/2005 19:35:23

Non, il ne va pas dans la boucle, le label 20692, c'est lui:

$L20692:
  jbe SHORT $L20690
  or eax, -1  ; si > 0x80000000
$L20690:
  ret 0
_puissance_2 ENDP


Cependant, j'ai fais une autre version, moin rapide que celle `__inline`, car ma nouvelle version n'est pas `__inline`, mais néanmoin plus rapide que celle de Matt67(sur mon poste en tout cas):

version assembleur de ma fonction:
NitRic: 153808384
Matt67: 283329521
Press any key to continue

la voilà:

__declspec(naked)
unsigned __fastcall pow_2( unsigned x )
{__asm{
; dans les tests que Matt67 et moi faisont,
; les jump ici ne seront exécutés que deux
; fois(test: 0-0x80000000)
  cmp ecx, -2147483648
  ja SHORT lbl_isover ; si >
  je lbl_isequal ; si ==
  inc ecx
  and ecx, -2
  je SHORT lbl_iszero ; si 0
  mov eax, -2147483648

lbl_boucle_001:
  shr eax, 1
  cmp eax, ecx
  jae SHORT lbl_boucle_001 ; tant que < x
  add eax, eax ; <<1
  ret 0

lbl_isequal: ; == 0x80000000
  mov eax, ecx
  ret 0
lbl_iszero: ; == 0x0
  xor eax, eax
  ret 0
lbl_isover: ; > 0x80000000 => return 0xffffffffu;
  or eax, -1
  ret 0
}}


Tous les tests que je fais, me font croire que _mes_ fonctions sont plus rapide, or, Matt67 nous donne des résultats prouvant le contraire, pourquoi? Ont fait pourant les même tests! Désolé mais je n'arrive toujours pas à comprendre et j'aimerais bien!

Dans mes tests, les jump ne sont exécutés que deux fois tout au plus or, dans la fonction de Matt67, ils seront exécutés `0x80000000-2/3` fois. Qui peut m'expliquer, s'il vous plaît?



~(.:: NitRic ::.)~

Commentaire de BruNews le 08/03/2005 19:51:06 administrateur CS

ah oui excuse pour le label de JMP, j'ai encore lu trop vite et en travers. Je m'en retourne à mes occupations.

Commentaire de NitRic le 08/03/2005 20:41:56

Okay BruNews, pas d'problème :}

J'ai fais un autre test, avec la valeur 5 seulement

  for ( i = 0; i < 0x80000000; i++ )
    a = func( 5 );

Matt67 l'emporte de peu:

NitRic: 338.14 sec (338136 ms) - 8
Matt67: 338.12 sec (338116 ms) - 8
Press any key to continue

Mais un soft ne fonctionne pas avec une seul valeur!

Bref, tout me porte à croire que ma/mes fonction(s) l'emporte sur toutes les autres. Ce que je n'arrive pas à comprendre(et vous le savez déjà), ce sont les résultats de Matt67 ...

Personne n'a de réponse à ce sujet ?




~(.:: NitRic ::.)~

Commentaire de NitRic le 08/03/2005 20:46:07

Au fait, avec la valeur 5, ca force les deux fonctions à entrer dans la boucle, dans tous les cas.

5 > 0
5 < 0x80000000
5 != 1
boucle:
...
...
ret



~(.:: NitRic ::.)~

Commentaire de Hylvenir le 08/03/2005 21:39:58

Salut,
Tu as ta ligne de commande complète de compilation ?

Commentaire de NitRic le 08/03/2005 22:13:20

J'ai VS6, la voilà:

/nologo /G6 /ML /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FAs /Fa"Release/" /Fo"Release/" /Fd"Release/" /FD /c

Je l'ai modifié quelques fois(sauf aujourd'hui) mais, mes résultats était les même ...


les derniers tests que j'ai fait(et ferai)
dans une boucle de 0 à 0x80000000 pour tous les tests

avec la valeur 0x80000000 seulement:
- NitRic: 45.37 sec (45365 ms) - 2147483648
- Matt67: 65.95 sec (65945 ms) - 2147483648

avec la valeur 0 seulement:
- NitRic: 49.58 sec (49581 ms) - 0
- Matt67: 29.93 sec (29933 ms) - 0

avec la valeur 5 seulement:
- NitRic: 325.51 sec (325508 ms) - 8
- Matt67: 338.00 sec (337996 ms) - 8

avec la valeur -1(>0x80000000) seulement:
- NitRic: 34.26 sec (34259 ms) - 4294967295
- Matt67: 41.16 sec (41159 ms) - 4294967295

avec la valeur 1 seulement:
- NitRic: 342.08 sec (342081 ms) - 2
- Matt67: 45.23 sec (45235 ms) - 2

avec toutes les valeurs de 0 à 0x80000000:
- NitRic: 45.43 sec (45425 ms) - 2147483648
- Matt67: 68.18 sec (68178 ms) - 2147483648


Note, pour les valeurs uniques(0, 1, 5, 0x80000000 et -1) je
n'ai pas pus mettre ma fonction `__inline` car le compilo
détectait que c'était toujours la même valeur donc
résultat: 0.00 sec (0 ms) pour ma fonction, cela n'entre
pas dans les stats évidemment ...

J'ai utilisé clock() pour ces tests, étant donné l'écart
entre les deux fonctions, clock() n'influence en rien
le temps d'exécution ...

Pourquoi avec la valeur `1` ma fonction est-elle si lente
comparée à celle de Matt67? C'est simple, ma fonction entre
dans la boucle si < 0x80000000 && > 0, donc, la boucle est
exécutée contrairement à Matt67. Cependant, comme j'ai déjà
dis, un soft ne fonctionne pas avec une seul valeur unique!
Faut prévoir! Les valeurs aléatoire sont le meilleur moyen
de tester un code/fonction si celle-ci doit évidemment recevoir
des valeurs aléatoire, comme dans le cas présent. Lorsqu'on
optimise ou code tout simplement une fonction, faut prévoir
les valeurs les plus succeptibles d'arriver et non l'inverse.
Généralement, lorsqu'on appel une fonction, on lui envoie des
valeurs valide! Alors, faut les prévoirs dès le départ.
Il ne faut pas optimiser les `bugs` et valeurs non valide
mais plutôt le contraire. Trouver le juste millieux.

Je cherche encore à comprendre comment, Matt67 arrive à
avoir un meilleur résultat que ma fonction sur son poste.
Il à retiré le keyword `__inline`? Si c'est ca alors il
ne faut pas, son point fort est justement le fait qu'elle
est `__inline`. Comme j'ai `encore` déjà dis, je ne cherche
pas à être le meilleur/avoir la meilleur fonction/etc ...
mais plutôt à comprendre comment, sur deux postes différents,
deux fonctions peuvent être de rapiditées inverse!?!?!? Je
test depuis hier, je ne fait que ca et je ne comprend pas ...
Donc si d'autre personnes peuvent tester aussi, ca pourait être
bien d'avoir une moyenne sans ce fier à deux poste et qui
donne des résultats inverse en plus ...





~(.:: NitRic ::.)~




Commentaire de NitRic le 08/03/2005 22:20:49

un p'tit dernier, en parlant de `__inline`, j'ai mis sa fonctione `__inline` aussi mais, ca change pas grand chose ...

NitRic: 46.02 sec (46016 ms) - 2147483648
Matt67: 57.48 sec (57482 ms) - 2147483648




~(.:: NitRic ::.)~

Commentaire de NitRic le 08/03/2005 22:27:03

C'est moi, encore et encore ...
Si tu veux celle du linker aussi:

kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /machine:I386 /out:"Release/test.exe"



Commentaire de Matt67 le 09/03/2005 09:15:47

Bonjour,

Voici le lien du projet que j'ai utilisé pour faire mes tests
(Celui de BruNews, modifié pour trois fonctions)

mirabon.free.fr/win32/Test_Expo2.zip

si tu peux essayer et me tenir au courant,

Matt...

Commentaire de NitRic le 09/03/2005 20:10:41

J'ai du retirer ton dialog étant donné que je n'utilise pas les MFC's et ne les est pas installés. Mais je n'ai pas touché au reste de ton code que voici:

#include <windows.h>
#include <iostream>

using namespace std;

#define MAXVAL 0xFFFFFF

HWND hMatt, hAutre, hasm;
char szappname[] = "PowTwo";

#define ALIGN(x,y) ( x = ((x + (y - 0x00000001u)) & ~(y - 0x00000001u)) )

__inline unsigned Autre( unsigned x )
{
  register unsigned y;

  if ( x < 0x80000000 && ALIGN(x, 2) )
  {
    y = 0x80000000;
    do
    {
    } while ( (y >>= 1) >= x );
    x = (y << 1);
  }
  return ( (x <= 0x80000000) ? x : 0xffffffffu );
}


unsigned  Matt(unsigned d)
{
  unsigned r = 0x80000000;

  if(!d) return 0;
  if(d > r) return 0xFFFFFFFF;
  if(d == 1) return 2;

  while((r >>= 1) >= d);
  r <<= 1;

  return r;
}

__declspec(naked) DWORD __fastcall Puiss2SupEgal_ASM(DWORD d)
{
  __asm {
    mov     eax, ecx
    cmp     eax, 1
    jb      short ramExit
    ja      short nbrOK
    inc     eax
nbrOK:
    mov     edx, eax
    bsr     ecx, eax
    mov     eax, 1
    shl     eax, cl
    cmp     eax, edx
    jae     short ramExit
    shl     eax, 1
    jnz     short ramExit
    mov     eax, -1
ramExit:
    ret     0
  }
}

void Teste_Autre()
{
  LARGE_INTEGER lideb, lifin;
  DWORD i = MAXVAL, r;
  char buff[20];
  QueryPerformanceCounter(&lideb);
  for(i=0; i<=0x80000000; i++)
    r = Autre(i);
  QueryPerformanceCounter(&lifin);
  
  lifin.QuadPart -= lideb.QuadPart;
  _ui64toa(lifin.QuadPart, buff, 10);
  cout << "Autre: " << buff << endl;
}

void Teste_Matt()
{
  LARGE_INTEGER lideb, lifin;
  DWORD i = MAXVAL, r;
  char buff[20];
  QueryPerformanceCounter(&lideb);
  for(i=0; i<=0x80000000; i++)
    r = Matt(i);
  QueryPerformanceCounter(&lifin);
  
  lifin.QuadPart -= lideb.QuadPart;
  _ui64toa(lifin.QuadPart, buff, 10);
  cout << "Matt67: " << buff << endl;
}

void Teste_ASM()
{
  LARGE_INTEGER lideb, lifin;
  DWORD i = MAXVAL, r;
  char buff[20];
  QueryPerformanceCounter(&lideb);
  for(i=0; i<0x80000000; i++)
    r = Puiss2SupEgal_ASM(i);

  QueryPerformanceCounter(&lifin);
  lifin.QuadPart -= lideb.QuadPart;
  _ui64toa(lifin.QuadPart, buff, 10);
  cout << "ASM: " << buff << endl;
}

int main( int argc, char * argv[] )
{

unsigned i, a;
for ( i = 0u; i <= 0x80000000; i++ )
a = Autre(i);

cout << a << endl << endl;

Teste_Matt();
Teste_Autre();
Teste_ASM();

cout << endl;
return 0;

}

/****************************************
* Résultats:

    2147483648

    Autre   : 112422269
    Matt67 : 300881971
    ASM     : 327010421

    Press any key to continue
*
****************************************/

Au fait, oubliez les dialogs et compagnie pour ce genre de test, un bouton pour Matt67, un autre pour ASM, etc .... Donnez une chance égale à chaque fonction. Faire ce genre de test de votre facon ne fait que fausser les résultats.



~(.:: NitRic ::.)~

Commentaire de Matt67 le 09/03/2005 20:22:58

Bonsoir,

Pas de MFC dans mon projet, que du WIN32.
Tu compiles avec quoi ?
VC++ (6) tu ouvres le projet et tu compiles et normalement pas de probleme (je me repete, pas de MFC).

DEV C++,  nouveau projet et tu ajoutes les differents fichiers (un .cpp, un .h et un .rc) et hop ca roule.

Je ne vois pas en quoi les dialogs viennent perturber le resultat ???
As tu regardé le code car le fait d'appuyer sur l'un ou l'autre bouton ne change rien sinon qu'on appelle une fonction differentes !!!

Matt...

Commentaire de NitRic le 09/03/2005 21:02:24

j'vais me faire un jolie GUI avec boutons, editbox et compagnie et j'vais lancer les tests derrière tout ca ...

J'ai parlé de MFC parce que dans ton fichier resource il y avait un #include <afxres.h> ou quelque chose du genre, et moi pas avoir ca ...


d'autres résultats:
-----------------------------------
Autre(__inline) - Matt67(!__inline)
-
Autre: 99894968
Matt67: 267824238
-
Matt67: 267612270
Autre: 99645088

------------------------------------
Autre(!__inline) - Matt67(__inline)
-
Autre: 211826517
Matt67: 106929026
-
Matt67: 107290040
Autre: 212106307

------------------------------------
Autre(!__inline) - Matt67(!__inline)
-
Autre: 212236292
Matt67: 267871849
-
Matt67: 267834713
Autre: 211729585

-------------------------------------
Autre(__inline) - Matt67(__inline)
-
Autre: 99666052
Matt67: 107482668
-
Matt67: 107109181
Autre: 99901842

--------------------------------------

Le tout avec le même code(test) qui ce trouve plus haut.

Au fait, je sais comment créer un projet, le configurer, compiler, etc ... et je me répète mais, j'utilise VS6.

Je me demande encore pourquoi sur ton poste, ma fonction est plus lente que la tienne ...

Je n'ai pas inclus le test de la fonction ASM car elle arrive toujours derrière alors c'est inutile ...



~(.:: NitRic ::.)~

Commentaire de Hylvenir le 09/03/2005 22:51:02

Bonsoir, de retour sur ce thread rigolo.
J'ai branché ma fonction sur ton prog de test du dessus.
Voilà ce que j'obtiens...
c'est marrant à 3 machines, trois résultats différents.
Autre est un peu plus rapide que Matt67, mais Hylvenir est toujours un peu plus rapide.  J'ai lancé plusieurs fois le test et l'ordre est toujours identique.
Pour compiler :
cl /Ox /G6 /GX performance.cpp  

Par contre, quand je génère l'asm issus d'une fonction C (Matt67 par exemple) et que je l'intègre pour remplacer le C original, les performances chutent au niveau de l'ASM.
Je ne sais pas trop pourquoi.
J'attends ta GUI :)

D:\>performance.exe
2147483648

Autre: 25843818
Matt67: 27430273
Hylvenir : 23833085
ASM: 69672336


unsigned Hylvenir(unsigned n)
{
  if ( n < 0x80000000 )
  {
if (  n & ( n - 1 ) )
{
unsigned i = 0x80000000, n1 = n;
n1 <<= 1;
while( !( n1 & i ) ) i >>= 1;
return i;  
}
return (n&1)?2:n;
  }
  return 0xFFFFFFFF;
}

Commentaire de BruNews le 09/03/2005 23:31:06 administrateur CS

Hylvenir > j'avais déjà expliqué pourquoi, le compilo ne mettra pas direct le code dans la fonction si est asm alors que le tout petit code C est mis direct inline, la différence de perf devient donc énorme. Pour comparer vraiment faudrait écrire toute la func de test en asm.

Commentaire de NitRic le 10/03/2005 00:01:20

Pour le GUI, je te laisse relire les messages précédents et deviner pour quelle raison j'avais écrit ca, sinon tu risque d'attendre très longtemps après moi pour du GUI =P

Autre: 238871380
Matt67: 301855115
Hylvenir: 387281082

encore et toujours des résultats différents ...
à croire que nos PC favorises notre propre code au détriments de ceux des autres ... et je n'ai même pas mis ma fonction `__inline` ...

Une question qui restera surement sans réponse un bon moment; Pourquoi?

Au fait, BruNews à raison, prendre le code ASM généré par le compilo et le compiler dans un source C/C++ n'est _vraiment_ pas une bonne idée =P


~(.:: NitRic ::.)~

Commentaire de Hylvenir le 10/03/2005 22:05:00

Brunews > Ok. J'avais mis jusqu'à maintenant de côté l'asm et le __inline (c'est pas trop mon truc l'asm).
Mais en tout cas, ça m'aura donné l'occasion d'avoir à réouvrir mes docs d'asm :)

NitRic > No problemo. Je ne fais pas non plus de GUI sous windows.

PS : Sous hpux et un vieux proc, c'est aussi ta fonction qui est plus rapide.

Commentaire de JCDjcd le 12/03/2005 18:55:54

"Pas de table précalculée ni série de 32 'if' "


on a le droit a 6 ou 7 if ?

Commentaire de BruNews le 12/03/2005 19:07:37 administrateur CS

bien sûr

Commentaire de JCDjcd le 12/03/2005 22:36:44

//--------------------------------------------
#define FLAG1 0xFFFF0000
#define FLAG2 0xFF00FF00
#define FLAG3 0xF0F0F0F0
#define FLAG4 0xCCCCCCCC
#define FLAG5 0xAAAAAAAA

unsigned the7(unsigned int d)
{
int res;
if(0          == (d & 0xFFFFFFFE)) return 0x00000000;
if(0x80000000 <= d)                return 0xFFFFFFFF;

res = 0;
if(d & FLAG1) { d &= FLAG1; res += 16; }
if(d & FLAG2) { d &= FLAG2; res +=  8; }
if(d & FLAG3) { d &= FLAG3; res +=  4; }
if(d & FLAG4) { d &= FLAG4; res +=  2; }
if(d & FLAG5) { d &= FLAG5; res +=  1; }
return res;
}

Commentaire de NitRic le 13/03/2005 18:58:37

tes résultats ne sont pas bon ...

0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7
, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9
, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9
, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9
, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9
, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9
, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9
, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9
, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10,



void test_func()
{

unsigned i, a, z;

for ( a = -1, i = 0u; i <= 1025; i++ )
{

z = the7( i );
/*if ( z != a )
{*/
printf("%u, ", z);
/* a = z;
}*/

}

}


voilà ce que ca devrait donner normalement:

0, 2, 2, 4, 4, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 32, 32, 32, 32, 32, 3
2, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 64, 64, 64, 64, 64, 64, 64, 64, 64, 6
4, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 6
4, 64, 64, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
256, 256, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512,
512, 512, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 102
4, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1
024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 102
4, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1
024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 102
4, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1
024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 102
4, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1
024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 102
4, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1
024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 102
4, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1
024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 102
4, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1
024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 102
4, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1
024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 102
4, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1
024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 102
4, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1
024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 102
4, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1
024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 102
4, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1
024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 102
4, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024,
1024, 1024, 1024, 1024, 1024, 1024, 1024, 2048,






~(.:: NitRic ::.)~

Commentaire de JCDjcd le 13/03/2005 19:39:56

bon bon, oki



//--------------------------------------------
#define FLAG1 0xFFFF0000
#define FLAG2 0xFF00FF00
#define FLAG3 0xF0F0F0F0
#define FLAG4 0xCCCCCCCC
#define FLAG5 0xAAAAAAAA

unsigned the7(unsigned int d)
{
int res;
if(0          == (d & 0xFFFFFFFF)) return 0x00000000;
if(0x80000000 <= d)                return 0xFFFFFFFF;

d --;
res = 1;
if(d & FLAG1) { d &= FLAG1; res <<= 16; }
if(d & FLAG2) { d &= FLAG2; res <<=  8; }
if(d & FLAG3) { d &= FLAG3; res <<=  4; }
if(d & FLAG4) { d &= FLAG4; res <<=  2; }
if(d & FLAG5) { d &= FLAG5; res <<=  1; }
return res << 1;
}

Commentaire de Hylvenir le 13/03/2005 20:09:29

La classe ;)
Bravo.

Commentaire de Matt67 le 13/03/2005 20:35:25

Bonsoir,

NitRic avec ton source ta fonction est plus rapide, avec mon source ma fonction est plus rapide ???

J'ose plus trop donner mon avis mais il me semble que la fonction de JCDjcd est assez lente.

Bonne soirée,

Matt...

Commentaire de NitRic le 15/03/2005 05:46:02

Résultats:

!__inline
the7: 324506902
NitRic: 213095092
Matt67: 269217699

__inline
the7: 92350761
NitRic: 100074803
Matt67: 107929266


en `__inline`, JCDjcd nous dépasse de peu !mais! elle contient encore un bogue, ce qui l'exclus des stats.

Pour la valeur 0x80000000, elle renvoie 4294967295(-1) plutôt que de renvoyer 0x80000000 ....


Matt67, oui en effet, mais j'ignore pourquoi :|




~(.:: NitRic ::.)~

Commentaire de JCDjcd le 20/03/2005 01:52:32

juste un question de if au debut, Pb de <= au lieu de < :

//--------------------------------------------
#define FLAG1 0xFFFF0000
#define FLAG2 0xFF00FF00
#define FLAG3 0xF0F0F0F0
#define FLAG4 0xCCCCCCCC
#define FLAG5 0xAAAAAAAA

unsigned the7(unsigned int d)
{
int res;
if(0          == (d & 0xFFFFFFFF)) return 0x00000000;
if(0x80000000 < d)                return 0xFFFFFFFF;

d --;
res = 1;
if(d & FLAG1) { d &= FLAG1; res <<= 16; }
if(d & FLAG2) { d &= FLAG2; res <<=  8; }
if(d & FLAG3) { d &= FLAG3; res <<=  4; }
if(d & FLAG4) { d &= FLAG4; res <<=  2; }
if(d & FLAG5) { d &= FLAG5; res <<=  1; }
return res << 1;
}


celle-ci remplie-t-elle toutes les specification ?

Commentaire de NitRic le 20/03/2005 04:55:34

Oui mais, il faudrait `forcer` le compilateur à la mettre `inline`, parce que avec un `call` elle est très lente.

Mais sinon, félicitation !!!



~(.:: NitRic ::.)~

Commentaire de gnairod le 22/12/2008 15:33:17

Brunews y a un probleme je pense.
Tu dis que la fonction doit retourne la plus proche puissance de 2 sup ou egale au param mais, lorsque i vaut 1 tu retournes 2 pourtant 1 est bien une puissance de 2. 2^0 = 1.

Non?

Commentaire de JCDjcd le 22/12/2008 17:18:50

houlala cette discussion date de longtemps !!
sujet passionnant... oui normalement 2^0=1

on pourrait tout refaire en 64 bits et voir qui va gagner !
je n'aurai qu'a rajouter un "if" et ca tourne !
d'ailleur au passage pour parler un peu de complexite
des algorithmes : le mien est en log(log(param))

Commentaire de gnairod le 22/12/2008 17:22:44

Ben j'ai gagne.

__declspec(naked) DWORD __fastcall Puiss2SupEgal_GNairod(DWORD d) {
__asm {
cmp ecx, 80000000h
ja short sup
test ecx, ecx
jz short zero
mov eax, ecx
bsr ecx, eax
bsf edx, eax
cmp ecx, edx
je short powof2
mov eax, 1
add ecx, 1
shl eax, cl
ret
powof2:
ret
sup:
mov eax, -1
ret
zero:
xor eax, eax
ret
}
}

Plus rapide que la version de Brunews.

 Ajouter un commentaire




Nos sponsors


Sondage...

CalendriCode

Février 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,437 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales