Calcul sur une matrice, optimisation ?

Calcul sur une matrice, optimisation ? - C - Programmation

Marsh Posté le 12-10-2004 à 15:09:49    

:hello: ,
J ai une matrice de [512]*[512],
je dois calculer la somme de chaque colone et ligne de la matrice.
 

Code :
  1. void sums_slow (int x[MAX][MAX], int colsums[MAX], int rowsums[MAX])
  2. {
  3. }


en sauvant le resultat de chaque operation dans colsums[n] ou rowsums[m].
 
Il y a t-il une methode/algo plus rapide que ce genre de chose

Code :
  1. {
  2. int j,i;
  3. int colsum = 0;
  4. for (i=0; i<MAX; i++)
  5. {
  6.  int temp = 0;
  7.  for (j=0; j<MAX; j++)
  8.  {
  9.   temp += x[j][i];  //x[0],[j]  row  x[j][0] column
  10.   //printf ("%d \n", x[0][j]);
  11.  }
  12.  //printf ("%d \n", temp);  
  13.  colsums[i] = temp;
  14. }
  15. //printf ("\n" );
  16. for (i=0; i<MAX; i++)
  17. {
  18.  int temp = 0;
  19.  for (j=0; j<MAX; j++)
  20.  {
  21.   temp += x[i][j];
  22.   //printf ("%d \n", x[0][j]);
  23.  }
  24.  //printf ("%d \n", temp);  
  25.  rowsums[i] = temp;
  26. }
  27. }


 
merci  [:alarmclock119]  

Reply

Marsh Posté le 12-10-2004 à 15:09:49   

Reply

Marsh Posté le 12-10-2004 à 15:21:07    

ta pile te dit merci

Reply

Marsh Posté le 12-10-2004 à 15:30:51    

quand tu calcul la somme d'une colonne, pour respecter l'ordre de ton code, tu peux en profiter pour ajouter la valeur courante à la ligne correspondante.
 
=> une seule boucle au lieu de 2.

Reply

Marsh Posté le 12-10-2004 à 15:31:05    

pour faire un peu plus rapide (mais surement encore optimisable, tu peux utiliser 2 iterateurs.
l'un commence au debut de ta ligne, l'autre a la fin (idem si c'est des colonne)  
Et tu les fais aller, simultanément pour qu'ils se rejoingne a MAX/2
T'as plus qu'a additioner les 2 valeurs recupéré par tour de boucle.
Ya surement mieux, mais cette amélioration divise quand meme par deux le temps de calcul.

Reply

Marsh Posté le 12-10-2004 à 15:32:14    

oui, un seul parcour suffit
 
un truc dans ce genre la
 
...
colsums[i] = 0;
rowsums[i] = 0;
for( j = 0; j < MAX; j++ )  
{  
    colsums[i] += x[j][i];  
    rowsums[i] += x[i][j];  
}  
...

Reply

Marsh Posté le 12-10-2004 à 15:32:15    

c0wb0y a écrit :

pour faire un peu plus rapide (mais surement encore optimisable, tu peux utiliser 2 iterateurs.
l'un commence au debut de ta ligne, l'autre a la fin (idem si c'est des colonne)  
Et tu les fais aller, simultanément pour qu'ils se rejoingne a MAX/2
T'as plus qu'a additioner les 2 valeurs recupéré par tour de boucle.
Ya surement mieux, mais cette amélioration divise quand meme par deux le temps de calcul.


Non.

Reply

Marsh Posté le 12-10-2004 à 15:33:17    

hu ?
Je ne comprends pas pourquoi c'est incorrect =/

Reply

Marsh Posté le 12-10-2004 à 15:35:41    

cris56 a écrit :

oui, un seul parcour suffit
 
un truc dans ce genre la
 
...
colsums[i] = 0;
rowsums[i] = 0;
for( j = 0; j < MAX; j++ )  
{  
    colsums[i] += x[j][i];  
    rowsums[i] += x[i][j];  
}  
...


 
Il y a du mieux, mais tu continues à faire 2 accès aléatoires pour chaque case visitée.  Si tu fais:
   rowsums[j] += x[j][i];
 
Ca a plus de gueule, car rowsums a plus de chance d'être en cache (il ne fait que 512 cases, contre 262144 pour la matrice x), et tu n'accèdes qu'une fois à chaque case de ta matrice (en fait, 2, mais le compilateur l'optimisera).
 

Reply

Marsh Posté le 12-10-2004 à 15:38:04    

cris56 a écrit :

oui, un seul parcour suffit
 
un truc dans ce genre la
 
...
colsums[i] = 0;
rowsums[i] = 0;
for( j = 0; j < MAX; j++ )  
{  
    colsums[i] += x[j][i];  
    rowsums[i] += x[i][j];  
}  
...

euh la tu ferais bien de mesurer, tu risques de foutre en l'air ton cache (et si la matrice est grande, faire plein de défauts de pages). prudence donc

Reply

Marsh Posté le 12-10-2004 à 15:38:23    

Code :
  1. pour i = 1 à N  -- lignes
  2.    pour j = 1 à N  -- colonnes
  3.       rowsum[i] += x[i][j]
  4.       colsum[j] += x[i][j]
  5.    fin pour
  6. fin pour


non ?

Reply

Marsh Posté le 12-10-2004 à 15:38:23   

Reply

Marsh Posté le 12-10-2004 à 15:38:57    

( hum, si mon erreur était par rapport au "temps de calcul divisé par deux" alors j'ai compris, j'ai dis n'importequoi en fait (: ya autant de calcul, c'est juste la longueur des parcours qui est réduite, m'enfin on doit y gagner un peu qd meme je pense )
Si c'était pas par rapport a ca, alors j'vois pas  :??:

Reply

Marsh Posté le 12-10-2004 à 15:39:44    

Lam's a écrit :


rowsums[j] += x[j][i];
 


 
tout a fais, j'y avais meme pensé mais la je m'etais d'abord servi du fait que la matrice etais carré, si elle ne l'etais pas ta solution s'imposait d'elle meme
 
merci
 
edit : taz > oue, je viens de voir


Message édité par cris56 le 12-10-2004 à 15:41:44
Reply

Marsh Posté le 12-10-2004 à 15:40:27    

c0wb0y a écrit :

Si c'était pas par rapport a ca, alors j'vois pas  :??:


Vi c'était ça. Mais tu peux aussi bien simplement dérouler ta boucle, sans avoir à passer par l'arrière...
 

Reply

Marsh Posté le 12-10-2004 à 15:49:03    

( j'sais pas ce que ca veut dire derouler une boucle http://hellien.free.fr/smileys/god.gif
C'est ca quand on se limite au poly de C qu'on a en cours :] http://hellien.free.fr/smileys/mad_overclocker.gif)

Reply

Marsh Posté le 12-10-2004 à 15:55:05    

loop unrolling en anglais. A mon avis, google a 2 ou 3 trucs à dire à ce propos ;)

Reply

Marsh Posté le 12-10-2004 à 23:08:20    

Merci les gas, justement cest pour nous aprendre a utiliser le cache, on doit tout dabord faire une methode la plus pourrie possible (je vais essayer de retoucher mon premier exemple), et une optimise le mieux que l on peut.
 
 le cache :
64kB, 4-way set associative, with a 32-byte cache line
 
je vais esseyer plusieurs methode et poster les temps.
 
 
 

Reply

Marsh Posté le 12-10-2004 à 23:21:31    

for(i=0;i<SIZE;i++) truc(i);
 
=>
 
for(i=0;i<SIZE/4;i++)
{
  truc(4*i);
  truc(4*i+1);
  truc(4*i+2);
  truc(4*i+3);
}
 
poru i < 300 a peu pres, vitesse x2 a x3 sur du Pentium, x4-5 sur du PPC

Reply

Marsh Posté le 12-10-2004 à 23:31:22    

t'as déjà essayé avec les __builtins de prefetch de gcc ?
 
 
bah bah bah, faut pas faire comme ça, faut faire avec i < SIZE; i += 4; tu dois au moins sauver 2/3 instructions avec ça :D

Reply

Marsh Posté le 12-10-2004 à 23:34:32    

Taz a écrit :


bah bah bah, faut pas faire comme ça, faut faire avec i < SIZE; i += 4; tu dois au moins sauver 2/3 instructions avec ça :D


 
bizzarement non :| et au moins avec ma version je ne me chie pas dednas ^^

Reply

Marsh Posté le 12-10-2004 à 23:44:26    

je te parle de traiter les quelques éléments qui restent si SIZE % 4 != 0
 
avec gcc3.3 (et 3.4), j'ai un registre de plus utilisé pour stocker le i * 4

Reply

Marsh Posté le 12-10-2004 à 23:46:25    

si SIZE%4 evidemment ^^
 
sous gcc 3.3 Apple j'ai pas ce registre en plus.

Reply

Marsh Posté le 12-10-2004 à 23:49:25    

Code :
  1. void f(int);
  2. #ifdef JOELF
  3. void g()
  4. {
  5.   const int N = 100;
  6.   int i;
  7.   for(i = 0; i < N / 4; ++i)
  8.     {
  9.       f(4 * i);
  10.       f(4 * i + 1);
  11.       f(4 * i + 2);
  12.       f(4 * i + 3);
  13.     }
  14. }
  15. #else
  16. void g()
  17. {
  18.   const int N = 100;
  19.   int i;
  20.   for(i = 0; i < N; i += 4)
  21.     {
  22.       f(i);
  23.       f(i + 1);
  24.       f(i + 2);
  25.       f(i + 3);
  26.     }
  27. }
  28. #endif // JOELF


 
en gcc -O3 -S ça te donne quoi respectivement ?


Message édité par Taz le 12-10-2004 à 23:49:50
Reply

Marsh Posté le 13-10-2004 à 01:13:29    

la matrice est de [512*512] donc multiple de 4.
voila different methodes plus leur temps.
compiler avec cc -O
bi proc ultra sparc
 
methode du premier post : 8.29 ms
seconde methode

Code :
  1. int j,i;
  2. for ( i=0; i<MAX; i++)
  3. {
  4.   colsums[i] = 0;
  5.   rowsums[i] = 0;
  6.  
  7.   for( j=0; j<MAX; j++)
  8.   {
  9.        rowsums[i] += x[i][j]; 
  10.    colsums[i] += x[j][i]; 
  11.        
  12.   }
  13. }


11,90 ms     [:dams86]  
 
Pour celle qui utilise le 4 way associative cache,  
truc(i) est censez faire quoi ?

Reply

Marsh Posté le 13-10-2004 à 01:44:44    

déjà si tu veux faire un benchmark, il faut que ton processus tourne au moins une minute et que tu prennes un temps moyen sur au moins 3 exécutions consécutives

Reply

Marsh Posté le 13-10-2004 à 02:08:38    

j ai utilise le prog donne par le prof. :/
lequel servira amesurer nos algo.

Code :
  1. int j,i;
  2. for ( i=0; i<MAX; i++)
  3. {
  4.   colsums[i] = 0;
  5.   rowsums[j] = 0;
  6.  
  7.   for( j=0; j<MAX; j++)
  8.   {
  9.    colsums[i] += x[j][i]; 
  10.    rowsums[j] += x[j][i];
  11.        
  12.   }
  13. }


 
8,77 ms
 
je comprend pas trop l exemple pour le 4 way cache assiociative, pouriez vous develope un peu ?
merci  
 :jap:


Message édité par xiluoc le 13-10-2004 à 02:29:34
Reply

Marsh Posté le 13-10-2004 à 09:19:00    

fait des vrais mesures ! tu peux pas conclure sur des durées aussi ridicules.

Reply

Marsh Posté le 13-10-2004 à 09:33:30    

Taz a écrit :


en gcc -O3 -S ça te donne quoi respectivement ?


-- truc effacé paske faux


Message édité par Joel F le 13-10-2004 à 20:18:39
Reply

Marsh Posté le 13-10-2004 à 09:50:17    

Pour la version la plus lente possible, jacced au column et row de la matrice 8 par 8 (32 byte line, 4 way associative il load 8 word a chaque fois) pour avoir un maximum de miss.
grace a ca je tombe a 14.8 m/s, c est yune moyenne apres plusieurs test.
Taz tu peus aller verifier : http://www.comp.mq.edu.au/units/co [...] nts/3.html
 
J aimerai savoir si il existe es outils montrant le nombre de miss sur le cache ? de facon a savoir ou sa coince.
 
Pourais je avoir plus dexplication sur :

Code :
  1. for(i=0;i<SIZE;i++) truc(i);
  2. =>
  3. for(i=0;i<SIZE/4;i++)
  4. {
  5.   truc(4*i);
  6.   truc(4*i+1);
  7.   truc(4*i+2);
  8.   truc(4*i+3);
  9. }


 

Reply

Marsh Posté le 13-10-2004 à 09:52:32    

Code :
  1. // JOELF
  2. g:
  3. stwu 1,-32(1)
  4. mflr 3
  5. stw 29,20(1)
  6. stw 3,36(1)
  7. stw 31,28(1)
  8. li 31,0
  9. .L6:
  10. slwi 29,31,2
  11. addi 31,31,1
  12. mr 3,29
  13. bl f
  14. addi 3,29,1
  15. bl f
  16. addi 3,29,2
  17. bl f
  18. addi 0,29,3
  19. mr 3,0
  20. bl f
  21. cmpwi 0,31,24
  22. ble+ 0,.L6
  23. lwz 3,36(1)
  24. lwz 29,20(1)
  25. lwz 31,28(1)
  26. mtlr 3
  27. addi 1,1,32
  28. blr


 
 

Code :
  1. // sans JOELF
  2. g:
  3. stwu 1,-32(1)
  4. mflr 3
  5. stw 3,36(1)
  6. stw 31,28(1)
  7. li 31,0
  8. .L6:
  9. mr 3,31
  10. bl f
  11. addi 3,31,1
  12. bl f
  13. addi 3,31,2
  14. bl f
  15. addi 3,31,3
  16. addi 31,31,4
  17. bl f
  18. cmpwi 0,31,99
  19. ble+ 0,.L6
  20. lwz 3,36(1)
  21. lwz 31,28(1)
  22. addi 1,1,32
  23. mtlr 3
  24. blr

Reply

Marsh Posté le 13-10-2004 à 09:53:50    

moi je veux savoir comment tu peux tirer des conclusions sur des laps de temps aussi ridicule ?

Reply

Marsh Posté le 13-10-2004 à 09:55:34    

comme ca

Code :
  1. /* dotest.c: Speed test module for COMP226 Assignment 3
  2. *  2004.  Copyright Leonard G C Hamey 2001-2004.  All rights reserved.
  3. * This program may only be used by COMP226 students at Macquarie
  4. * University for the purposes of developing their solution to
  5. * assignment 3.
  6. *
  7. * This is the source code version from which I compiled the object module
  8. * for the students to test their programs with.
  9. */
  10. # include "dotest.h"
  11. # if DOALIGN
  12. DATAITEM memory[NR*NC*3*MAXTEST+GAP*3*MAXTEST+ALIGN];
  13. # else
  14. DATAITEM mem[NR*NC*3*MAXTEST+GAP*3*MAXTEST];
  15. # endif
  16. DATAITEM *xp[MAXTEST], *yp[MAXTEST], *zp[MAXTEST];
  17. int xim[MAXM] = { 1, 3, 1, 3, 2, -1, 2, -1, 5, 3, 5, 3 };
  18. int xjm[MAXM] = { -1, 1, 3, -1, -1, 2, 1, -3, -1, 1, 3, -1};
  19. int yim[MAXM] = { 1, 2, 3, 4, -1, -2, -3, -4, 3, 2, 1, 4 };
  20. int yjm[MAXM] = { -3, -5, 7, 2, 8, 4, 5, 3, -3, -5, -7, 2 };
  21. int zim[MAXM] = { 0, 1, 2, 0, -1, -2, 0, 1, 2, 0, -1, -2 };
  22. int zjm[MAXM] = { 0, 0, 1, 1, 2, 2, -2, -2, -1, -1, 0, 0 };
  23. /* Routines to implement a simple timer mechanism. */
  24. # include <sys/time.h>
  25. # include <sys/timeb.h>
  26. # include <sys/resource.h>
  27. /* Static data structures used by abstract object timer. */
  28. static struct timeb wall_on, wall_off;
  29. static struct rusage user_on, user_off;
  30. static long int wall = 0L, user = 0L;
  31. /* Timer on: Start timing program execution */
  32. void timer_on ()
  33. { ftime (&wall_on);
  34.   getrusage (RUSAGE_SELF, &user_on);
  35. }
  36. /* Timer off: Stop timing program execution
  37. * Current time interval is added to accumulated time.
  38. */
  39. void timer_off ()
  40. { getrusage (RUSAGE_SELF, &user_off);
  41.   ftime (&wall_off);
  42.   wall += (wall_off.time - wall_on.time) * 1000 +
  43.       wall_off.millitm - wall_on.millitm;
  44.   user += (user_off.ru_utime.tv_sec - user_on.ru_utime.tv_sec) *
  45.       1000 + (user_off.ru_utime.tv_usec -
  46.       user_on.ru_utime.tv_usec) / 1000;
  47. }
  48. /* Timer display: Prints the current accumulated time */
  49. void timer_display (FILE *out)
  50. { fprintf (out, "wall %d.%03d  user %d.%03d\n",
  51.       wall/1000, wall % 1000, user / 1000, user % 1000);
  52. }
  53. /* timer_user_ms: Returns user CPU time in ms currently accumulated */
  54. int timer_user_ms ()
  55. { return user;
  56. }
  57. /* timer_wall_ms: Returns wall clock (true elapsed) time accumulated */
  58. int timer_wall_ms ()
  59. { return wall;
  60. }
  61. /* timer_reset: Reset timer accumulators to zero. */
  62. void timer_reset ()
  63. { wall = user = 0;
  64. }
  65. int timer_begin ()
  66. {
  67.   timer_reset ();
  68.   timer_on ();
  69. }
  70. int timer_end ()
  71. {
  72.   timer_off ();
  73.   /* timer_display (stdout); */
  74.   return user;
  75. }
  76. /* -------------------------------------------------------------- */
  77. /* The rest of this program does the timing */
  78. float exec_test (void (*op)(), int ntests, int is_test1);
  79. float do_test (char *name, void (*op)(), int is_test1)
  80. {
  81.   float time;
  82.   int ntests;
  83.   fprintf (stderr, "do_test version 3.0\n" );
  84.   fprintf (stderr, "Testing your %s operator %s\n", is_test1 ? TEST1 : TEST0, name);
  85.   alarm (15);
  86.   /* First test 3 times to estimate how many tests required for
  87.    * sufficient accuracy of measurement */
  88.   time = exec_test (op, 0, is_test1);
  89. # ifdef VERBOSE
  90.     printf ("[3]: %.5f\n", time);
  91. # endif
  92.   if (time < -0.5)
  93.     return time;  /* Execution failure - no time data recorded */
  94.   ntests = 3;
  95.   /* The estimate of number of iterations required must be based on
  96.    * at least 0.05 seconds of data */
  97.   while (time * ntests < 0.05)
  98.   {
  99.     ntests = ntests * 10;
  100.     time = exec_test (op, ntests, is_test1);
  101. # ifdef VERBOSE
  102.       printf ("[%d]: %.5f\n", ntests, time);
  103. # endif
  104.   }
  105.  
  106.   /* Absolutely must have at least 0.75 seconds of data to base estimate
  107.    * on. */
  108.   while (time * ntests < 0.75)
  109.   {
  110.     /* Estimate number of tests required for 1.2 second of data */
  111.     ntests = (int) (1.2 / time) + 1;
  112.     if (ntests > MAXTEST)
  113.       ntests = (ntests + MAXTEST - 1) / MAXTEST * MAXTEST;
  114.     time = exec_test (op, ntests, is_test1);
  115.   }
  116.    
  117. # if TIMEONLY
  118.   printf ("%8.2f", time*1000.0);
  119. # else
  120.   printf ("%s: %.2fms/operation (executed %d times)\n", name, time * 1000.0, ntests);
  121. # endif
  122.   return time * 1000.0;
  123. }
  124. void initialise (DATAITEM x[NR][NC], DATAITEM y[NR][NC], DATAITEM z[NR][NC],
  125.     int xim, int xjm, int yim, int yjm, int zim, int zjm)
  126. {
  127.   int i, j;
  128.   for (i = 0; i < NR; i++)
  129.     for (j = 0; j < NC; j++)
  130.     {
  131.       if (x != NULL)
  132.         x[i][j] = FORMULAX;
  133.       if (y != NULL)
  134.         y[i][j] = FORMULAY;
  135.       if (z != NULL)
  136.         z[i][j] = FORMULAZ;
  137.     }
  138. }
  139. float exec_test (void (*op)(), int ntests, int is_test1)
  140. {
  141.   RETURN_TYPE0 (*op0)() = 0;
  142.   RETURN_TYPE1 (*op1)() = 0;
  143. # if RETURN0
  144.     RETURN_TYPE0 result0[MAXTEST];
  145. # else
  146.     char result0[1];
  147. # endif
  148. # if RETURN1
  149.     RETURN_TYPE1 result1[MAXTEST];
  150. # else
  151.     char result1[1];
  152. # endif
  153.   int i, j;
  154.   int nrun, utime, check_correctness;
  155. # if DOALIGN
  156.   DATAITEM *mem;
  157. # endif
  158.   DATAITEM *x, *y, *z;
  159.   check_correctness = ntests == 0;
  160.   if (ntests == 0)
  161.     ntests = 5;  /* Initial test to estimate time required for testing */
  162.   /* Determine how many tests to run */
  163.   nrun = ntests;
  164.   if (nrun > MAXTEST)
  165.     nrun = MAXTEST;
  166. # if DOALIGN
  167.   /* Align memory array mem to multiple of ALIGN bytes which must be a power of 2 */
  168.   mem = memory + ALIGN;
  169.   mem = (DATAITEM *) ((int) (mem) & ~(ALIGN-1));
  170. # endif
  171.   /* Now set up the array pointers. */
  172.   for (i = 0; i < nrun; i++)
  173.   {
  174. # if XYZ
  175.     /* x, y, z, x, y, z, x, y, z order in memory
  176.      */
  177.     xp[i] = mem + i * (NR * NC + GAP) * 3;
  178.     yp[i] = xp[i] + NR * NC + GAP;
  179.     zp[i] = yp[i] + NR * NC + GAP;
  180. # else
  181.     /* x, x, x, ..., y, y, y, ..., z, z, z, ... in memory
  182.      */
  183.     xp[i] = mem + i * (NR * NC + GAP);
  184.     yp[i] = xp[i] + (NR * NC + GAP) * MAXTEST;
  185.     zp[i] = yp[i] + (NR * NC + GAP) * MAXTEST;
  186. # endif
  187.   }
  188. # if INFO
  189.   fprintf (stderr, "xp[0] = %x  xp[1] = %x  yp[0] = %x  zp[0] = %x\n",
  190.     xp[0], xp[1], yp[0], zp[0]);
  191. # endif
  192.   /* Initialise the arrays with some data. */
  193.   fprintf (stderr, "Data initialisation..." );
  194.   for (i = 0; i < nrun; i++)
  195.   {
  196.   /* casting pointers to void * prevents compiler from complaining  
  197.    * about their eventual use as 2-D arrays */
  198.     initialise ((void *) xp[i], (void *) yp[i],
  199.          (void *) zp[i], xim[i % MAXM], xjm[i % (MAXM-1)],
  200.                 yim[i % MAXM], yjm[i % (MAXM-1)],
  201.                 zim[i % MAXM], zjm[i % (MAXM-1)]);
  202.   }
  203.   /* Perform operations */
  204.   fprintf (stderr, "Executing your routine..." );
  205.   timer_begin ();
  206.   for (i = 0; i < ntests; i++)
  207.   {
  208.     x = xp[i % MAXTEST];
  209.     y = yp[i % MAXTEST];
  210.     z = zp[i % MAXTEST];
  211.     if (is_test1)
  212. {
  213.   op1 = (RETURN_TYPE1 (*)()) op;
  214. # if RETURN0
  215.   result1[i % MAXTEST] = (*op1) (ARG1);
  216. # else
  217.       (*op1) (ARG1);
  218. # endif
  219. }
  220.     else
  221. {
  222.   op0 = (RETURN_TYPE0 (*)()) op;
  223. # if RETURN0
  224.   result0[i % MAXTEST] = (*op0) (ARG0);
  225. # else
  226.       (*op0) (ARG0);
  227. # endif
  228. }
  229.   }
  230.   utime = timer_end ();
  231.   fprintf (stderr, "Execution completed.\n" );
  232.   STAFF_PROCESSING
  233.   return ((float) (utime) / 1000.0 / ((float) ntests));
  234. }

Reply

Marsh Posté le 13-10-2004 à 09:59:04    

xiluoc a écrit :


grace a ca je tombe a 14.8 m/s, c est yune moyenne apres plusieurs test.


53 km/h. C'est une vitesse raisonnable en ville. Pourquoi veux-tu aller plus vite ?  
 
Tu as fais un google sur "loop unrolling" ou bien tu veux qu'on fasse le copier/coller pour toi ?
 
Et sinon, tu es sûr du copier/coller de la solution du prof ? Ca me parrait bizarre qu'il accède à la matrice colonne par colonne...

Reply

Marsh Posté le 13-10-2004 à 10:00:29    

comment je t'ai bien eu Joelf, le gcc de MacOSX est pourri ! tu fais à chaque fois la multiplication ! alors que moi le calcul est factorisé ! (et je parle pas de tous les load pour recharger i à chaque fois)
 
ma version fait donc du code franchement meilleur ! et mon GCC rox !


Message édité par Taz le 13-10-2004 à 10:08:56
Reply

Marsh Posté le 13-10-2004 à 10:09:45    

Lam's a écrit :

[...]Et sinon, tu es sûr du copier/coller de la solution du prof ? Ca me parrait bizarre qu'il accède à la matrice colonne par colonne...


+1
et pis

Code :
  1. rowsums[j] = 0;

hors de la boucle j ca me paraît louche.

Reply

Marsh Posté le 13-10-2004 à 10:18:59    

Taz a écrit :

comment je t'ai bien eu Joelf, le gcc de MacOSX est pourri ! tu fais à chaque fois la multiplication ! alors que moi le calcul est factorisé ! (et je parle pas de tous les load pour recharger i à chaque fois)
 
ma version fait donc du code franchement meilleur ! et mon GCC rox !


 
han, na c'est moi qui est la plus grosse :o
hmmm 2sec ...
 
j'etais pas en -o3  :sweat:  
 
ma version

Code :
  1. LCFI0:
  2. mtctr r3
  3. addi r2,r1,32
  4. .p2align 4,,15
  5. L14:
  6. stw r9,0(r2)
  7. stw r11,4(r2)
  8. addi r9,r9,8
  9. addi r11,r11,8
  10. stw r10,8(r2)
  11. stw r8,12(r2)
  12. addi r10,r10,8
  13. addi r2,r2,16
  14. addi r8,r8,8
  15. bdnz L14
  16. lwz r1,0(r1)
  17. blr


Reply

Marsh Posté le 13-10-2004 à 10:21:25    

euh je bigle ou y a pas un seul f dans ton truc ?

Reply

Marsh Posté le 13-10-2004 à 10:24:05    

ben peut etre que si ta fonction f etait pas vide, -O3 la laisserrai vivre [:autobot]
 
fiel moi exactement le code que tu utilise.

Reply

Marsh Posté le 13-10-2004 à 10:26:10    

mon code :
 

Code :
  1. int f(int i) { return 2*i; }
  2. #define N 10000
  3. int j[N];
  4. void g()
  5. {
  6. int i;
  7. for(i = 0; i < N / 4; ++i)
  8. {
  9. j[4 * i] = f(4 * i);
  10. j[4 * i+1] = f(4 * i + 1);
  11. j[4 * i+2] = f(4 * i + 2);
  12. j[4 * i+3] = f(4 * i + 3);
  13. }
  14. }
  15. void h()
  16. {
  17. int i;
  18. for(i = 0; i < N; i += 4)
  19. {
  20. j[i] = f(i);
  21. j[i+1] = f(i + 1);
  22. j[i+2] = f(i + 2);
  23. j[i+3] = f(i + 3);
  24. }
  25. }
  26. int main(int,char**)
  27. {
  28. g();
  29. h();
  30. }


 
la sortie assembleur en -O3 -mcpu=ppc-g5
 

Code :
  1. .section __TEXT,__text,regular,pure_instructions
  2. .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
  3. .globl _j
  4. .data
  5. .align 2
  6. _j:
  7. .space 40000
  8. .section __TEXT,__text,regular,pure_instructions
  9. .align 2
  10. .align 2
  11. .p2align 4,,15
  12. .globl __Z1fi
  13. .section __TEXT,__text,regular,pure_instructions
  14. .align 2
  15. __Z1fi:
  16. LFB6:
  17. slwi r3,r3,1
  18. blr
  19. LFE6:
  20. .align 2
  21. .p2align 4,,15
  22. .globl __Z1gv
  23. .section __TEXT,__text,regular,pure_instructions
  24. .align 2
  25. __Z1gv:
  26. LFB7:
  27. mflr r7
  28. bcl 20,31,"L00000000001$pb"
  29. "L00000000001$pb":
  30. li r8,6
  31. li r10,4
  32. li r11,2
  33. mflr r2
  34. mtlr r7
  35. addis r6,r2,ha16(_j-"L00000000001$pb" )
  36. li r2,0
  37. la r5,lo16(_j-"L00000000001$pb" )(r6)
  38. addis r0,r5,0x1
  39. mr r9,r5
  40. subf r4,r5,r0
  41. addi r3,r4,-25536
  42. srwi r0,r3,4
  43. mtctr r0
  44. .p2align 4,,15
  45. L14:
  46. stw r2,0(r9)
  47. stw r11,4(r9)
  48. addi r2,r2,8
  49. addi r11,r11,8
  50. stw r10,8(r9)
  51. stw r8,12(r9)
  52. addi r10,r10,8
  53. addi r9,r9,16
  54. addi r8,r8,8
  55. bdnz L14
  56. blr
  57. LFE7:
  58. .align 2
  59. .p2align 4,,15
  60. .globl __Z1hv
  61. .section __TEXT,__text,regular,pure_instructions
  62. .align 2
  63. __Z1hv:
  64. LFB8:
  65. mflr r7
  66. bcl 20,31,"L00000000002$pb"
  67. "L00000000002$pb":
  68. li r8,6
  69. li r10,4
  70. li r11,2
  71. mflr r2
  72. mtlr r7
  73. addis r6,r2,ha16(_j-"L00000000002$pb" )
  74. li r2,0
  75. la r5,lo16(_j-"L00000000002$pb" )(r6)
  76. addis r0,r5,0x1
  77. mr r9,r5
  78. subf r4,r5,r0
  79. addi r3,r4,-25524
  80. srwi r0,r3,4
  81. mtctr r0
  82. .p2align 4,,15
  83. L27:
  84. stw r2,0(r9)
  85. stw r11,4(r9)
  86. addi r2,r2,8
  87. addi r11,r11,8
  88. stw r10,8(r9)
  89. stw r8,12(r9)
  90. addi r10,r10,8
  91. addi r9,r9,16
  92. addi r8,r8,8
  93. bdnz L27
  94. blr
  95. LFE8:
  96. .align 2
  97. .p2align 4,,15
  98. .globl _main
  99. .section __TEXT,__text,regular,pure_instructions
  100. .align 2
  101. _main:
  102. LFB9:
  103. mflr r2
  104. stw r2,8(r1)
  105. LCFI0:
  106. stwu r1,-80(r1)
  107. LCFI1:
  108. bl __Z1gv
  109. bl __Z1hv
  110. lwz r2,88(r1)
  111. li r3,0
  112. addi r1,r1,80
  113. mtlr r2
  114. blr
  115. LFE9:
  116. .globl _Z1fi.eh
  117. _Z1fi.eh = 0
  118. .no_dead_strip _Z1fi.eh
  119. .globl _Z1gv.eh
  120. _Z1gv.eh = 0
  121. .no_dead_strip _Z1gv.eh
  122. .globl _Z1hv.eh
  123. _Z1hv.eh = 0
  124. .no_dead_strip _Z1hv.eh
  125. .globl main.eh
  126. main.eh = 0
  127. .no_dead_strip main.eh
  128. .data
  129. .constructor
  130. .data
  131. .destructor
  132. .align 1
  133. .subsections_via_symbols

Reply

Marsh Posté le 13-10-2004 à 10:28:04    

ben je te l'ai filé !
 
c'est clair pourtant, il a pas le code de f ... et pourtant il vire les appels, mais il garde la boucle ... (alors que chez moi évidemment si void f(int i) { } g est alors vide ...
 
y a un truc qui foire terrible là ...

Reply

Marsh Posté le 13-10-2004 à 10:29:28    

Joel F a écrit :

mon code :
 

Code :
  1. int f(int i) { return 2*i; }
  2. #define N 10000
  3. int j[N];



tu peux pas faire comme tout le monde ? si je te file du code, c'est justement pour qu'on compare ...

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed