Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1549 connectés 

 


 Mot :   Pseudo :  
 
 Page :   1  2  3  4
Auteur Sujet :

[Concours No 3] A vos cerveaux !

n°776111
Ummon
Posté le 24-06-2004 à 15:12:01  profilanswer
 

Reprise du message précédent :
Et voila, encore une fois : il vaut mieux un code de haut niveau bien pensé plutot que du bidouillage de bas niveau (assembleur). (je vais me faire taper mais c pas grave)

mood
Publicité
Posté le 24-06-2004 à 15:12:01  profilanswer
 

n°776217
NeKoFuchik​oma
Posté le 24-06-2004 à 15:59:04  profilanswer
 

Je pose le code de tentacle après avoir intégré ses remarques et enlevé des petits trucs en trop (pas de zéro ni de 100000 dans la liste), mon nouveau score tombe à 180ms autant en faire profiter :
 

Code :
  1. #include <stdio.h>
  2.   #include <windows.h>
  3.  
  4.   #define TABLE_LENGTH 100000
  5.  
  6.   int main(int argc, char* argv[])
  7.   {
  8.      SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
  9.      SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
  10.      
  11.     int i, incr;
  12.    
  13.     for (unsigned short p = 0; p < 10; p++) {
  14.    
  15.      DWORD dwTimeBefore = GetTickCount (); // Bon je commence pas au début m'en voudrez pas :p
  16.      unsigned int count[10] = {0}; // Statistiques finales
  17.      unsigned short tmpCount[TABLE_LENGTH] = {0}; // Statistiques intermédiaires       
  18.      int error; // Correction du nombre de 0  
  19.      unsigned long lValue, lTmpValue;
  20.      unsigned long j, tmpJ;
  21.      error = 0;
  22.      for (i = 0, lValue = 0; i < 5000000; i++) {
  23.         lValue = (( 1664525 * lValue ) + 1013904223 ) & 0x7FFFFFFF;
  24.         lTmpValue = lValue;
  25.        
  26.         /////////////////////////////////////////////////////////////////////////////////////////  
  27.            if (lTmpValue >= TABLE_LENGTH) {
  28.               incr = lTmpValue % TABLE_LENGTH;
  29.               lTmpValue /= TABLE_LENGTH;
  30.              
  31.               // Incrémentation de 'error' en fonction du nb de 0 à gauche (sur 5 chiffres)  
  32.               if (incr < 10000) {
  33.                  error++;
  34.                  if (incr < 1000) {
  35.                     error ++;
  36.                     if (incr < 100) {
  37.                        error ++;
  38.                        if (incr < 10) {
  39.                           error ++;
  40.                           if (incr == 0) {
  41.                              error ++;
  42.                           }
  43.                        }
  44.                     }
  45.                  }
  46.               }
  47.              } else {
  48.               incr = lTmpValue;
  49.               lTmpValue = 0;
  50.            }
  51.            
  52.            tmpCount[incr]++;
  53.          
  54.            incr = lTmpValue; 
  55.            tmpCount[incr]++;
  56.            /////////////////////////////////////////////////////////////////////////////////
  57.          
  58.         //}  
  59.      }
  60.      
  61.      // Calcul statistiques finales  
  62.      for (j = 0; j < TABLE_LENGTH; j++) {
  63.         incr = tmpCount[j];
  64.         tmpJ = j;
  65.         while (tmpJ > 0) {
  66.            count[tmpJ%10] += incr;
  67.            tmpJ /= 10;
  68.         }
  69.      }
  70.      count[0] += error; // Correction du nombre de 0  
  71.    
  72.      printf ("\ntest %d : %d ms\n", p, GetTickCount() - dwTimeBefore);
  73.      // Affichage statistiques  
  74.      for (i = 0; i < 10; i++) {
  75.          printf ("%d - %d occurences\n", i, count[i]);
  76.      }
  77.      }
  78.    
  79.      return 0;
  80.   }


 
:lol:
 
 
A+
:: NeKo ::


Message édité par NeKoFuchikoma le 24-06-2004 à 16:00:18
n°776256
christophe​_d13
L'efficacité à tout prix.
Posté le 24-06-2004 à 16:15:57  profilanswer
 

De mon côté, entre deux lignes de codes à mon boulot, j'ai encore cogité. Il existe un moyen de se passer de la division et du modulo sans pour autant manipuler autant de pointeur comme je l'avais fait...
Dés que j'aurais plus de temps je m'en occupe.
 
Ceci dit, en assembleur il est possible qu'avec la manipulation de pointeurs, on soit plus rapide.
 
Les temps progresses et tant mieux !
En plus, vous trichez un peu avec Windows en passant en TC. Mais c'est autorisé puisque pas spécifié dans le problème.

n°776260
Tentacle
Posté le 24-06-2004 à 16:21:02  profilanswer
 

Neko on peut encore fait ceci mais ça n'apporte pas grand chose :
 

Code :
  1. for (i = 0, lValue = 0; i < 5000000; i++) {
  2.  lValue = (( 1664525 * lValue ) + 1013904223 ) & 0x7FFFFFFF;
  3.  lTmpValue = lValue;
  4.  if (lTmpValue >= TABLE_LENGTH) {
  5.   incr = lTmpValue % TABLE_LENGTH;
  6.   lTmpValue /= TABLE_LENGTH;
  7.   // Incrémentation de 'error' en fonction du nb de 0 à gauche (sur 5 chiffres)
  8.   if (incr < 10000) {
  9.    error++;
  10.    if (incr < 1000) {
  11.     error ++;
  12.     if (incr < 100) {
  13.      error ++;
  14.      if (incr < 10) {
  15.       error ++;
  16.       if (incr == 0) {
  17.        error ++;
  18.       }
  19.      }
  20.     }
  21.    }
  22.   }
  23.   tmpCount[incr]++;
  24.  }
  25.  tmpCount[lTmpValue]++;
  26. }


 
Je pense aussi qu'en assembleur il doit y avoir moyen d'aller plus vite, l'algo ne suffit pas.
 
christophe_d13: que veux-tu dire par TC ? le GetTickCount ? il vaudrait mieux utiliser quoi ?


Message édité par Tentacle le 24-06-2004 à 16:23:58
n°776311
NeKoFuchik​oma
Posté le 24-06-2004 à 16:32:42  profilanswer
 

ah oui bien vu tentacle !  :lol:  
 
Pour l'assembleur j'ai un collegue (qui se prend pour un compilo) qui s'amuse en ce moment à adapter la technique de tentacle en asm mais pour l'instant, son prog met 250ms pour faire le calcul...
 
edit: le code asm tombe à 240ms ça descend ça descend  :D  
edit2: je viens de comprendre  TC = Time Critical  
désolé christophe j'avais pas envie de fermer toutes mes applis  :jap:  
 
A+
:: NeKo ::


Message édité par NeKoFuchikoma le 24-06-2004 à 16:40:38
n°776335
antp
Super Administrateur
Champion des excuses bidons
Posté le 24-06-2004 à 16:41:59  profilanswer
 

christophe_d13 a écrit :


En plus, vous trichez un peu avec Windows en passant en TC. Mais c'est autorisé puisque pas spécifié dans le problème.


 
vu que c'est testé sur des machines différentes on n'est plus à ça près, non ? :D


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
n°776375
Tentacle
Posté le 24-06-2004 à 16:57:53  profilanswer
 

et puis de toute facon j'obtiens le même résultat sans cela ...
 
Mais sinon on va pas demander à christophe_d13 de tester chez lui chaque algo :/

n°776396
NeKoFuchik​oma
Posté le 24-06-2004 à 17:09:30  profilanswer
 

allez moi je vais me cacher  :sweat:  
 
voici le code de mon collegue :

Code :
  1. #include <stdio.h>
  2.   #include <windows.h>
  3.  
  4.   #define TABLE_LENGTH 100000
  5. unsigned long res[10] = {
  6. 4454792 ,
  7. 6919549 ,
  8. 4821073 ,
  9. 4474832 ,
  10. 4473815 ,
  11. 4457929 ,
  12. 4454968 ,
  13. 4451157 ,
  14. 4450771 ,
  15. 4455972 };
  16.   int main(int argc, char* argv[])
  17.   {
  18.    Sleep(500);
  19.  
  20.    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
  21.    SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
  22.    
  23.  
  24. for(unsigned short p = 0; p < 10; p++)
  25. {
  26.  DWORD dwTimeBefore = GetTickCount ();
  27.      unsigned int count[10] = {0}; // Statistiques finales
  28.      unsigned short tmpCount[TABLE_LENGTH] = {0}; // Statistiques intermédiaires
  29.      int i, incr;
  30.      unsigned long lValue;
  31.      unsigned long j, tmpJ;
  32.   unsigned short* ptab = &tmpCount[0];
  33. // for (i = 0, lValue = 0; i < 5000000; i++) {
  34. // lValue = (( 1664525 * lValue ) + 1013904223 ) & 0x7FFFFFFF;
  35. // /!\ asm visual studio
  36.   __asm {
  37.    mov  edi, ptab
  38.    xor  ecx, ecx
  39.    xor  esi, esi
  40.    push ebp
  41.    mov  ebp, 5000000
  42.   label_for:
  43.    mov  edx, 1664525
  44.    mov  eax, esi
  45.    mul  edx
  46.    add  eax, 1013904223
  47.    and  eax, 7fffffffh
  48.    mov  esi, eax
  49.    mov  ebx, TABLE_LENGTH
  50.    cmp  eax, ebx
  51.    jb  label_else
  52.    xor  edx, edx
  53.    div  ebx
  54.    cmp  edx, 10000
  55.    jae  lbl1
  56.    inc  ecx
  57.    cmp  edx, 1000
  58.    jae  lbl1
  59.    inc  ecx
  60.    cmp  edx, 100
  61.    jae  lbl1
  62.    inc  ecx
  63.    cmp  edx, 10
  64.    jae  lbl1
  65.    inc  ecx
  66.    and  edx, edx
  67.    jnz  lbl1
  68.    inc  ecx
  69.   lbl1:
  70.    inc  word ptr [edi + 2 * edx]
  71.    inc  word ptr [edi + 2 * eax]
  72.    dec  ebp
  73.    jnz  label_for
  74.    jmp  label_the_end
  75.   label_else:
  76.    mov  edx, eax
  77.    inc  word ptr [edi]
  78.    inc  word ptr [edi + 2 * edx]
  79.    dec  ebp
  80.    jnz  label_for
  81.    jmp  label_the_end
  82.    inc  word ptr [edi + 2 * edx]
  83.    inc  word ptr [edi + 2 * eax]
  84.    dec  ebp
  85.    jnz  label_for
  86.   label_the_end:
  87.    pop  ebp
  88.    add  count[0], ecx
  89.   }
  90. // }
  91.      // Calcul statistiques finales
  92.      for (j = 0; j < TABLE_LENGTH; j++) {
  93.         incr = tmpCount[j];
  94.         tmpJ = j;
  95.         while (tmpJ > 0) {
  96.            count[tmpJ%10] += incr;
  97.            tmpJ /= 10;
  98.         }
  99.      }
  100.      printf ("%d ms\n", GetTickCount() - dwTimeBefore);
  101.    
  102.      // Affichage statistiques
  103.      for (i = 0; i < 10; i++) {
  104.    printf ("%d - %d occurences [%s]\n", i, count[i], (res[i]==count[i])?("true " ):("false" ));
  105.      }   
  106. }
  107.      return 0;
  108.   }


 
résultat sur ma machine 170ms  :heink:  
 
à vous de tester les différents algo chez vous si vous souhaitez comparer
 
A+
:: NeKo ::

n°776471
Tentacle
Posté le 24-06-2004 à 17:27:35  profilanswer
 

Christophe a raison, on peut se séparer du modulo ... et d'ailleurs on est bête de pas y avoir pensé :
 

Code :
  1. for (i = 0, lValue = 0; i < 5000000; i++) {
  2.  lValue = (( 1664525 * lValue ) + 1013904223 ) & 0x7FFFFFFF;
  3.  lTmpValue = lValue;
  4.  if (lTmpValue >= TABLE_LENGTH) {
  5.   lTmpValue /= TABLE_LENGTH;
  6.   incr = lValue - lTmpValue * TABLE_LENGTH;
  7.   // Incrémentation de 'error' en fonction du nb de 0 à gauche (sur 5 chiffres)
  8.   if (incr < 10000) {
  9.    error++;
  10.    if (incr < 1000) {
  11.     error ++;
  12.     if (incr < 100) {
  13.      error ++;
  14.      if (incr < 10) {
  15.       error ++;
  16.       if (incr == 0) {
  17.        error ++;
  18.       }
  19.      }
  20.     }
  21.    }
  22.   }
  23.   tmpCount[incr]++;
  24.  }
  25.  tmpCount[lTmpValue]++;
  26. }


 
=> 125ms en pointe
 
en fait ça sert à rien de faire une division et un modulo vu que ce dernier est obtenable à partir de la division : a mod b = a - E(a / b) * b
 
Neko: tu pourrais le mettre en assembleur ?

n°776505
NeKoFuchik​oma
Posté le 24-06-2004 à 17:38:52  profilanswer
 

Terrible, mais jusqu'ou ça va descendre  :bounce:  
 
Le reste est donnée lorsque l'on fait une division assembleur du coup on n'utilise pas d'instruction supplémentaire...  
 
Pour infos sans le modulo, je tombe à 130ms et mon pote viens de se jetter par la fenêtre  :lol:  
 
A+
:: NeKo ::

mood
Publicité
Posté le 24-06-2004 à 17:38:52  profilanswer
 

n°776546
red factio​n
Posté le 24-06-2004 à 17:55:05  profilanswer
 

Vu les temps dexecutions qui deviennent de + en + cours, il ne vaudrait pas mieux utiliser qqch de plus precis comme QueryPerformanceCounter ???

n°776549
NeKoFuchik​oma
Posté le 24-06-2004 à 17:56:21  profilanswer
 

Bon demain on remplace quelques éléments dans le code asm, ce soir je deviens  :pt1cable:  
 
A+
:: NeKo ::  :hello:


Message édité par NeKoFuchikoma le 24-06-2004 à 17:58:56
n°776577
christophe​_d13
L'efficacité à tout prix.
Posté le 24-06-2004 à 18:12:36  profilanswer
 

Si vous voulez, je vous donne un code d'une ligne pour faire une division, mais sans division... ça vous dit ?
Un indice : Juste en faisant une multiplication et un décalage...
 
red faction> On pourrait également boucler 10 ou 20 fois sur le traîtement et obtenir une moyenne.

n°776600
Tentacle
Posté le 24-06-2004 à 18:22:44  profilanswer
 

Red Faction: soit, mais vu qu'on a tous des ordis différents on peut difficilement comparer. Sur 100 essais, j'obtiens 122.893169 ms.
 
Christophe_d13: attends je vais essayer de trouver :)

n°776602
Evadream -​jbd-
Posté le 24-06-2004 à 18:23:55  profilanswer
 

christophe_d13 > attends un peu, ca m'excite les neurones :D

n°776604
Tentacle
Posté le 24-06-2004 à 18:28:28  profilanswer
 

c'est bon j'ai trouvé, j'avais déjà cherché sur cette voie hier soir mais je ne voyais pas comment en sortir le modulo, mais pour extraire le résultat de la division c'est impéccable !! :D J'essais de suite.

n°776606
christophe​_d13
L'efficacité à tout prix.
Posté le 24-06-2004 à 18:29:54  profilanswer
 

Dans quelques jours, je prendrai chaque source et je ferai un test complet.


Message édité par christophe_d13 le 24-06-2004 à 18:31:30
n°776616
christophe​_d13
L'efficacité à tout prix.
Posté le 24-06-2004 à 18:45:27  profilanswer
 

Je vois également des trucs rigolos dans les algos :
J'ai précisé dans le problème que la valeur aléatoire va de 0 à 2^31-1. Donc vérifiez bien que le zéro marche !

Code :
  1. for (i=0;i<5000000;i++)
  2. {
  3.     lValue = i;
  4.     //Votre code
  5.     //....
  6. }

n°776627
Tentacle
Posté le 24-06-2004 à 18:55:06  profilanswer
 

la valeur 0 doit-elle ajouter 1 point pour le nombre de 0 alors ?
 
Edit: la méthode alternative pour la division me donne un temps supérieur pour le moment ... c'est peut la mauvaise méthode :/


Message édité par Tentacle le 24-06-2004 à 18:59:44
n°776631
christophe​_d13
L'efficacité à tout prix.
Posté le 24-06-2004 à 18:56:31  profilanswer
 

Et bien, c'est logique, puisque l'on ne compte que les zéros réellement présent. Et le zéro ne dispose que d'un seul chiffre.
 
Ton code passe à 78ms avec la suppression de la division.

n°776641
christophe​_d13
L'efficacité à tout prix.
Posté le 24-06-2004 à 18:59:42  profilanswer
 

Le seul hic du code c'est le fait que les stats se fassent dans des valeurs de 16 bits. Si la valeur aléatoire est toujours la même, il y a dépassement. ça marche pour la graine 0 et l'algo de Knutz, mais je ne l'ai posé que pour que chacun est la même suite aléatoire :

Cela permet à tous d'avoir la même série de nombres et une bonne rapidité de fabrication du nombre aléatoire.  
Le travail d'analyse peut également inclure la fabrication même de ce nombre aléatoire...


 
Cela dit, les résultats seront pris en compte.

n°776655
Tentacle
Posté le 24-06-2004 à 19:04:58  profilanswer
 

Bon déjà, j'ai pas du trouver la bonne méthode pour la division où je l'ai mal exploitée :/
Pour le zéro, à la limite ça fait une addition supplémentaire tout à la fin.
 
Pour les stats en 16bits, je sais que ça risque le dépassement mais dans notre cas ça marche, c'est pour ça que je l'ai laissé. En fait si je passe en 32bits, j'ai des temps désastreux apparement dû parce que le tableau devient trop gros (le traitement est apparement différent ... histoire du cache ?).
 
Est-ce important ?

n°776696
NeKoFuchik​oma
Posté le 24-06-2004 à 19:24:02  profilanswer
 

Citation :

Si vous voulez, je vous donne un code d'une ligne pour faire une division, mais sans division... ça vous dit ?


 
Merci bien christophe mais on va la retrouver  :sweat: c'était un truc avec une multiplication d'un nombre négatif magique et un décalage d'apres ce que j'ai pu sortir de g++
 
Bon j'espere que demain le score ne se sera pas trop envolé  :lol:  
 
 
A+
:: NeKo ::

n°776697
Evadream -​jbd-
Posté le 24-06-2004 à 19:24:14  profilanswer
 

J'ai rien trouvé qui me donne qqchose de mieux (en reprenant ton code Tentacle) en essayant de remplacer la division par multiplication + decalage, je dois mal m'y prendre :/ Je ne suis pas contre une solution [:ddr555]

n°776711
Tentacle
Posté le 24-06-2004 à 19:34:50  profilanswer
 

de mon côté je fais, par exemple pour une division par 10, (int)(n * 1.6) >> 4
(1.6 = 16/10 = 2^4/10)
Ca marche mais l'opération sur des réels est trop lente :/

n°776720
Evadream -​jbd-
Posté le 24-06-2004 à 19:42:23  profilanswer
 

Moi je multipliais par 104858 et divisait par 2^20 avec un décalage, mais comment dire, je sens que c'est pas çà.

n°776830
darkoli
Le Petit Dinosaure Bleu
Posté le 24-06-2004 à 20:50:40  profilanswer
 

Tentacle a écrit :

de mon côté je fais, par exemple pour une division par 10, (int)(n * 1.6) >> 4
(1.6 = 16/10 = 2^4/10)
Ca marche mais l'opération sur des réels est trop lente :/

Et il y a aussi la converion entier=>réel=>entier qui doit être longue.

n°776839
Joel F
Real men use unique_ptr
Posté le 24-06-2004 à 20:57:06  profilanswer
 

pourquoi vous ne travaillais pas en entier tt du long ?

n°776892
red factio​n
Posté le 24-06-2004 à 21:23:18  profilanswer
 

ce serait bien qd on aura pratiquement fini loptimisation du prog de faire une compte rendu avec les diffrentes instruction et leur temps dexecution (ou du moins les classer suivant cette valeur) :o  

n°777127
Ummon
Posté le 24-06-2004 à 23:10:45  profilanswer
 

Avouez que je vous aie tous bluffé avec mon temps d'exécution de 10min  :sol:

n°777146
christophe​_d13
L'efficacité à tout prix.
Posté le 24-06-2004 à 23:20:17  profilanswer
 

Je vous donne la solution pour une division par 100000.
Vous prenez la valeur sur 32 bits et vous la multipliez par un autre 32 bits : 351843721. Le nombre résultant est un 64 bits. Vous faites un décalage à droite de 45 bits si vous traîtez le bloc de 64 bits ou simplement de 13 bits avec le bloc supérieur de 32 bits.
 

Code :
  1. ulValueH = (unsigned long)(((__int64)lValue * (__int64)351843721)>>45);


 
On fait l'erreur de calcul (il y en a une) est reportée dans les bits inférieur...
351843721/2^45 = 1,0000000003174136509187519550323e-5
L'erreur est extrèment faible...
 
En ASM, cela nous donne...

Code :
  1. mov eax, 351843721
  2. imul lValue             //edx:eax = eax * lValue
  3. shr edx, 13             //On garde uniquement edx, ainsi on ne décale que de 13 et pas de 45.
  4. mov ulValueH, edx       //Le résultat se trouve dans edx...


 
Dommage que peut de gens s'interresse à ce genre de technique...
 
Et pourquoi on multiplie par cette valeur ? et pourquoi on décale de 45 ? Cherchez un peu !


Message édité par christophe_d13 le 24-06-2004 à 23:24:08
n°777280
darkoli
Le Petit Dinosaure Bleu
Posté le 25-06-2004 à 00:24:24  profilanswer
 

Tiens j'ai essayé de faire la même chose avec la division par 10 mais il y avait une perte trop importante, pour diviser N par 10 je faisais N = (N>>16)+(N>>32)+(N>>128) ce qui correspondait à N / ~9.84615384615. Mais je n'avais pas eu l'idée de le faire pour la découpe des nombres (/ et % 100000)!
 
Par contre le gain est à peine de 10% sur ma machine : ~240ms.
=> Athlon XP 2100+, DevCPP, XP.
Je teste demain matin sur mon P4 1.7Ghz (boulot).

n°777423
darkoli
Le Petit Dinosaure Bleu
Posté le 25-06-2004 à 09:45:03  profilanswer
 

Bon voilà j'ai viré la division et j'obtiens une durée d'envrion ~160ms (Algo de base ~1830ms).
 
Le nombre de division est passé de 47414858 à 488889 soit ~97x moins et idem pour le modulo ! Mais le temps de traitement a été divisé seulement par 10 ! :D
 

Code :
  1. void cas_opti4(void)
  2. {
  3. /* Chronometrage */
  4. time_t     tdebut=0;
  5. time_t     tfin=0;
  6. clock_t    cdebut=0;
  7. clock_t    cfin=0;
  8. /* Traitement */
  9. int        i=0;
  10. int        v=0;
  11. int        v1=0;
  12. int        v_old=0;
  13. short int  table[100000];
  14. int        decompte[10];
  15. int        nb_zeros=0;
  16. /* Statistiques */
  17. int        nb_divisions=0;
  18. int        nb_modulos=0;
  19. /* Initialisation */
  20. memset(table, 0, sizeof table);
  21. memset(decompte, 0, sizeof decompte);
  22. /* Debut */
  23. tdebut=time(NULL);
  24. cdebut=clock();
  25. /* Traitement */
  26. for (i=0;i<5000000;i++)
  27.   {
  28.    v = ((1664525 * v_old) + 1013904223) & 0x7FFFFFFF;
  29. /*   fprintf(stdout, "v = %d.\n", v);*/
  30.    v_old=v;
  31.    if (v > 100000)
  32.     {
  33.      asm("movl $351843721, %eax" );
  34.      asm("imull %0"::"r"(v));     /* edx:eax = eax * v */
  35.      asm("shr  $13, %edx" );       /* On garde uniquement edx, ainsi on ne décale que de 13 et pas de 45. */
  36.      asm("movl %%edx, %0":"=r"(v)::"%eax" );   
  37.      v1=v_old-(v*100000);
  38.      table[v1]++;
  39.      if (v1 < 10000)
  40.       {
  41.        nb_zeros++;
  42.        if (v1 < 1000)
  43.         {
  44.          nb_zeros++;
  45.          if (v1 < 100)
  46.           {
  47.            nb_zeros++;
  48.            if (v1 < 10)
  49.             {
  50.              nb_zeros++;
  51.              if (v1 == 0) nb_zeros++;
  52.             }
  53.           }
  54.         }
  55.       }
  56.     }
  57. /*   fprintf(stdout, "v1 = %d, v2 = %d.\n", v, v1);*/
  58.    table[v]++;
  59.   }
  60. decompte[0]=nb_zeros;
  61. for (i=1;i<100000;i++)
  62.   {
  63.    v1=table[i];
  64.    if (v1 < 1) continue;
  65.    v=i;
  66. /*   fprintf(stdout, "%d = x%d.\n", i, v1);*/
  67.    while (v > 0)
  68.     {
  69.      decompte[v%10]+=v1;
  70. /*     nb_modulos++;*/
  71.      v=v/10;
  72. /*     nb_divisions++;*/
  73.     }
  74.   }
  75. /* Fin */
  76. tfin=time(NULL);
  77. cfin=clock();
  78. /* Bilan */
  79. fprintf(stdout, "Duree : %.fms (~%ds).\n", ((double)(cfin-cdebut)/(double)CLOCKS_PER_SEC)*1000, tfin-tdebut);
  80. /*
  81. for (i=0;i<10;i++) fprintf(stdout, "%d = x%d.\n", i, decompte[i]);
  82. fprintf(stdout, "Nombre de divisions  =  %d.\n", nb_divisions);
  83. fprintf(stdout, "Nombre de modulos    =  %d.\n", nb_modulos);
  84. */
  85. /* Fin */
  86. return;
  87. }


Le type des entier pour le tableau table est très important et cela permet de diviser par 4 le temps de traitement (de ~800ms à ~200ms) ! :ouch:
 
Processeur : P4 1.7Ghz
Os : Linux Debian testing.
Compilateur : gcc 3.3.4.


Message édité par darkoli le 25-06-2004 à 09:54:07
n°777430
NeKoFuchik​oma
Posté le 25-06-2004 à 09:54:08  profilanswer
 

Pour infos :
A ma grande surprise, il semblerai que Visual Studio 7.1 ai optimisé les divisions comme un grand car je tourne à présent entre 115 et 109ms sur mon P4m 1.3Ghz ...
Avec g++ je suis en pointe à 130ms.
 
edit qui ne sert pas à grand chose: 100ms à 110ms en repassant en TC  :lol:  
 
A+
:: NeKo ::


Message édité par NeKoFuchikoma le 25-06-2004 à 10:01:29
n°777531
Yttrium
Furtif
Posté le 25-06-2004 à 10:36:16  profilanswer
 

Il faudrait encore jeter un oeil du côté des SSE. Je n'en suis pas sûr, mais il me semble qu'il y a quelques instructions qui permettent plusieurs opérations sur entiers par cycle.
 
Et ces 'if' imbriqués... Ne sont-ils pas des candidats pour CMOV ?
 
Et il reste encore éventuellement l'Hyper-Threading.
 
Non ? :D

n°777536
Yttrium
Furtif
Posté le 25-06-2004 à 10:38:19  profilanswer
 

Military technology.
Not for office or personal use.
Made in HFR.
 
:D

n°777542
christophe​_d13
L'efficacité à tout prix.
Posté le 25-06-2004 à 10:40:07  profilanswer
 

Les if imbriqués peuvent laisser place à des cmp/setxx/add

n°777558
Yttrium
Furtif
Posté le 25-06-2004 à 10:49:46  profilanswer
 

Y a-t-il une liste de nombre de cycle par opération pour les instruction asm (sur p4) ?

n°777618
christophe​_d13
L'efficacité à tout prix.
Posté le 25-06-2004 à 11:17:02  profilanswer
 

Va voir les docs Intel ou AMD.
Il n'y a pas que les opérations par cycle, il y aussi la latence. Car les opérations sont pipelinées.

n°777751
christophe​_d13
L'efficacité à tout prix.
Posté le 25-06-2004 à 12:30:52  profilanswer
 

C'est une mauvaise idée de mettre le code en ASM directement.
Il vaut mieux laisser le compilateur réarranger le code lui-même ou tout faire en ASM.
 

Code :
  1. ulValueH = (unsigned long)(((__int64)lValue * (__int64)351843721)>>45);


 
PS: Ce concours au final ne sert pas à grand chose (pour ce problème), il serait peut-être plus interressant dans l'avenir de proposer des problèmes plus utiles (des problèmes que l'on rencontre souvent par exemple).
On pourrait également faire 1 ou 2 concours par mois ?

n°777754
Tentacle
Posté le 25-06-2004 à 12:33:06  profilanswer
 

darkoli a écrit :

Le type des entier pour le tableau table est très important et cela permet de diviser par 4 le temps de traitement (de ~800ms à ~200ms) ! :ouch:


 
C'est ce que j'avais remarqué aussi. Si on passe en int, les meilleurs performances étaient obtenus en divisant par 10000 ce qui faisait un calcul supplémentaire. En 100000, malgré l'opération en moins, le temps d'exécution était trop augmenté, d'où le fait de passer en short int.

mood
Publicité
Posté le   profilanswer
 

 Page :   1  2  3  4

Aller à :
Ajouter une réponse
 

Sujets relatifs
Le concours de programmation ICFP 2004 a commencé[Concours] Recherche de doublons dans une séquence
[java/algo] Concours - implémenter une itf simple de gestion d'agenda.[IA] petite idée de concours
concours de code[C++] Concours de code : new test en cours, proposez votre solution !
Concours programmation[PHP] Comment organiser un concours
organiser un concours .[Concours] Votre Requête MySQL la plus complexe
Plus de sujets relatifs à : [Concours No 3] A vos cerveaux !


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR