[memcpy] L'importance de l'optimisation dans la copie des données

L'importance de l'optimisation dans la copie des données [memcpy] - C++ - Programmation

Marsh Posté le 11-07-2004 à 11:26:17    

Je travaille actuellement sur memcpy (ré-écriture).
En effet, j'ai découvert que les routines officielles (intel et AMD) n'étaient pas aussi performantes que ces fondeurs pouvaient le laisser croire.
Pour illustrer mes propos, voici un graphe utilisant plusieurs routines SSE et/ou MMX, j'ai enlever les routines CPU et FPU car elles n'apportent rien de plus (et polluent le graphe)
<Erreur dans le graphe, voir plus bas>


Message édité par christophe_d13 le 11-07-2004 à 13:15:57
Reply

Marsh Posté le 11-07-2004 à 11:26:17   

Reply

Marsh Posté le 11-07-2004 à 11:53:42    

La suite... Pour ce test, on essaye de ne pas utiliser le cache (flush).
<Erreur dans le graphe, voir plus bas>


Message édité par christophe_d13 le 11-07-2004 à 13:16:06
Reply

Marsh Posté le 11-07-2004 à 11:57:56    

Ces tests confirment largement la supériorité de la copy SSE avec movaps/movntps quand il s'agit de traîter des zones ne se trouvant pas dans le cache.
 
Attention toutefois, on effectue une copie ! Cet à dire que l'on lit puis on écrit. Certains logiciels affichent des résultats doubles.
En accès RAM, le débit entrant/sortant est de 3238Mo/s et le global de 1619Mo/s.
 
Le processeur ayant un bus de 180,409MHz soit un vitesse DDR de 360,818MHz. A chaque front, on peut transmettre 64 bits. Soit un débit théorique entrant ou sortant de 23092MBits/s soit 2886Mo/s. Alors pourquoi je suis à 3238Mo/s ? A mon avis, le Write-Back y est pour quelque chose.
 
Pour illustrer un processeur AthlonXP Barton, un test fait HFR.
http://www.hardware.fr/medias/photos_news/00/06/IMG0006225.gif
Attention, pour ce test, la mémoire est en 2-2-2-6 d'où les résultats élevés. Sandra ne dit pas si les débits sont doublés ou pas.
 
Une autre test à 200MHz avec différents timings
http://www.hardware.fr/medias/photos_news/00/06/IMG0006606.gif


Message édité par christophe_d13 le 11-07-2004 à 12:21:26
Reply

Marsh Posté le 11-07-2004 à 13:15:14    

Enfin OUF !
J'ai compris. Il y avait un soucis dans ma routine.

J'atteind donc un débit crête de 1377Mo/s contre 1343Mo/s pour la routine d'AMD. Soit mon gain initial de 2,5% pour le débit en mode DDR.


Message édité par christophe_d13 le 11-07-2004 à 13:16:30
Reply

Marsh Posté le 11-07-2004 à 13:28:30    

oui mais est-ce que tu as fait des mesures applicatives réelles, je veux dire, faire des memcpy en boucles, d'accord, mais dans une application de calcul (ou bien un tri, ça peut être très bien) pour évaluer ça en condition réelles, voir comment ça souille le cache ou bien les temps de bascule selon les routines. tu peux faire ça, un tri générique en C avec des memcpy, avec des tailles de données différentes ?

Reply

Marsh Posté le 11-07-2004 à 13:43:48    

Le but final est de fournir plusieurs routines memcpy dont une permettant de faire une liste de memcpy.
Toutes ces routines utiliseront la meilleure routine selon les besoins.

Reply

Marsh Posté le 11-07-2004 à 13:47:45    

oui, mais pour pouvoir déterminer qui réponds le mieux à quoi ...

Reply

Marsh Posté le 11-07-2004 à 13:50:48    

Taz> C'est l'intérêt de fournir plusieurs routines au programmeur qui au final font la même chose mais de façon différentes.
 
http://kristahl.design.free.fr/Perso/Copy%20Test%20with%20cache.png
 
Up> Je travaille surtout sur les problèmes d'alignement 8/16 octets.


Message édité par christophe_d13 le 11-07-2004 à 13:53:21
Reply

Marsh Posté le 11-07-2004 à 13:59:52    

moi, je veux voir ça dans un algorithme

Reply

Marsh Posté le 11-07-2004 à 17:07:16    

Taz> De toute façon, t'es tout le temps en train de critiquer. Si le monde t'écoutait, on serait pas prêt d'évoluer.
Une routine relativement générique qui permet de gagner un peu de vitesse est toujours bonne à prendre.

Reply

Marsh Posté le 11-07-2004 à 17:07:16   

Reply

Marsh Posté le 11-07-2004 à 17:52:45    

mais putain, tu comprends rien !
t'auras beau montrer que l'avion va 4 fois plus vite que le train, il faut bien 2H pour embarquer/débarquer dans un voil, donc sur énormément de distances, le train est, de manière pratique, plus rapide que l'avion.

Reply

Marsh Posté le 11-07-2004 à 18:26:51    

Si je te suis dans ton raisonnement, il faut laisser tomber l'avion...
PS: ça sert à rien de jurer.

Reply

Marsh Posté le 11-07-2004 à 18:58:05    

non, d'apres son raisonnement, il faut prendre l'avion sur des grandes distances peu frequemment et le train sur des petites distances frequemment, et jpense qu'il associe ton memcpy a l'avion et celui de l'os (vu qu'il parle de cache) au train.


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 11-07-2004 à 19:06:49    

vous me sidérez : exercice pratique. La voiture va bien plus vite que la marche (on va dire 130km/h contre 4km/h). Votre boulangerie est au coin de la rue. Allez-y a pied. Allez-y en voiture. Vous allez voir ...

Reply

Marsh Posté le 11-07-2004 à 19:09:19    

et j'associe rien du tout : je demande un benchmark applicatif pour justement savoir qui est plus efficace.

Reply

Marsh Posté le 11-07-2004 à 19:29:02    

On est d'accord Taz, c'est clair, n'empêche que ce genre de bench/test est intéressant à mon avis, on s'est déjà posé le problème ( K!TV pour ne pas le nommer), on a fait un paquet de tests ( c'est pas moi qui m'en suis occuppé ...), sans vraiment arriver à qq chose de top, faut dire qu'il y a plusieurs cas, copie de mémoire à mémoire ( pour les plugins), et copie de mémoire dans l'overlay à la fin; et là c'est clairement différent car on tape dans la vidéo ...
Mais bon, on s'égarre ... ;)

Reply

Marsh Posté le 11-07-2004 à 19:37:32    

mais ou j'ai dit que c'était inintéressant ?

Reply

Marsh Posté le 11-07-2004 à 19:48:50    

nulle part , effectivement, donc continue Christophe ! ;)

Reply

Marsh Posté le 11-07-2004 à 19:51:31    

Et indique la source/destination, car comme déjà dit de mémoire à overlay ça n'est pas du tout pareil, enfin je pense que tes tests sont de mémoire à mémoire.

Reply

Marsh Posté le 11-07-2004 à 20:57:15    

Mes tests ont un seul but : Fournir au programmeur plusieurs routines de copy adaptées à ses besoins.
Il y a plus d'un millier de tests qui sont effectués au démarrage de l'application pour choisir les meilleurs compromis (vitesse, taille, overlap, alignement) pour les routines :
- Copie en considérant que les données sont probalement dans le cache L1, L2 ou la mémoire
- Idem mais uniquement pour le L2 et la mémoire
- Idem mais uniquement pour la mémoire
- Copie en effectuant le meilleur compromis taille/vitesse (même si on perd des performances sur le L1).
- Et puis surtout la copie listée...
 
L'intérêt c'est bien de fournir les routines les plus rapides quel que soit l'os, le CPU, le cache ou la mémoire.
C'est pour cela que mes fonctions testent le processeur (CPUID), la vitesse et la taille des caches ainsi que la vitesse de la mémoire.

Reply

Marsh Posté le 12-07-2004 à 07:51:19    

« Fournir au programmeur plusieurs routines de copy adaptées à ses besoins. »
 
Ariane va à 28.800km/h, mais elle est loin d'être adaptée à mes besoins

Reply

Marsh Posté le 12-07-2004 à 09:02:52    

Bah, joelf fait bien le meme genre d'optimisations avec son altivec, non ?
C'est clair que dans la plupart des applis lambda, c'est inutile voire deconseille, mais il se peut tjrs que dans qq cas particuliers (genre K!TV, avec lequel je regarde la tele d'ailleurs, merci CriCri :) ), ca serve.


Message édité par el muchacho le 12-07-2004 à 09:11:03
Reply

Marsh Posté le 12-07-2004 à 09:13:33    

non, il fait pas du tout la même chose, lui il fait du SIMD, pas de la branlette qui accélère l'internet

Reply

Marsh Posté le 12-07-2004 à 09:18:56    

Taz a écrit :

non, il fait pas du tout la même chose, lui il fait du SIMD, pas de la branlette qui accélère l'internet


 :love: c'est bien Taz ça  
 [:kenshirooo]


---------------
What if I were smiling and running into your arms? Would you see then what I see now?  
Reply

Marsh Posté le 12-07-2004 à 09:39:53    

Taz a écrit :

non, il fait pas du tout la même chose, lui il fait du SIMD, pas de la branlette qui accélère l'internet

 
Signe Taz ! [:alphat]  :D
 
En fait, son truc, je pense que ca peut marcher seulement si le jeu de tests au demarrage est suffisamment bien selectionne pour evaluer correctement l'utilisation de la memoire cache dans l'appli, ce qui est loin d'etre evident (il faut essayer dans de nombreuses appli differentes, gros calcul, video, quicksort par exemple), mais certainement instructif, sinon ca peut faire une excellente librairie memoire.


Message édité par el muchacho le 12-07-2004 à 09:53:21
Reply

Marsh Posté le 12-07-2004 à 12:42:55    

Je deviens fous !
 
Etant donné que j'ai besoin de mesurer la taille des caches, j'ai donc fait plusieurs routines pour cela. Et dans la dernière, j'ai des résultats ahurissants : (j'ai converti pour les vrai Mo - 1Mo = 1048576 octets et non 1000000)
L1 = 28455Mo/s
L2 = 11884Mo/s
DDR = 2752Mo/s

 
Processeur AthlonXP 2164,91MHz (Diviseur /12)
Bus à 180,4092MHz
Débit DDR max = 23093MBits/s soit 2753Mo/s
 
Voici ma routine de test de lecture (via le CPU uniquement)
(c) 2004 Christophe Gossa, Tous droits réservés.
 
A noter que je ne mesure pas la latence de RDTSC/MOV EBX,EAX/RDTSC, et que la routine travaille sur 5 passes.

#define PROCESSORTESTREAD_MOV256RD64(x)  __asm mov     eax, [esi+ecx+  4+x]      \
                                         __asm mov     eax, [esi+ecx+  8+x]      \
                                         __asm mov     eax, [esi+ecx+ 12+x]      \
                                         __asm mov     eax, [esi+ecx+ 16+x]      \
                                         __asm mov     eax, [esi+ecx+ 20+x]      \
                                         __asm mov     eax, [esi+ecx+ 24+x]      \
                                         __asm mov     eax, [esi+ecx+ 28+x]      \
                                         __asm mov     eax, [esi+ecx+ 36+x]      \
                                         __asm mov     eax, [esi+ecx+ 40+x]      \
                                         __asm mov     eax, [esi+ecx+ 44+x]      \
                                         __asm mov     eax, [esi+ecx+ 48+x]      \
                                         __asm mov     eax, [esi+ecx+ 52+x]      \
                                         __asm mov     eax, [esi+ecx+ 56+x]      \
                                         __asm mov     eax, [esi+ecx+ 60+x]
 
#define PROCESSORTESTREAD_MOV256    __asm push    ebx                       \
                                    __asm mov     esi, pData                \
                                    __asm mov     edx, 0x7FFFFFFF           \
                                    __asm mov     ecx, lNbElements          \
                                    __asm mov     edi, 5                    \
                                    __asm add     esi, ecx                  \
                                    __asm mov     dwCycleStampSpeed, edx    \
                                    __asm neg     ecx                       \
                                    __asm mov     dwTemp0, esi              \
                                    __asm mov     dwTemp1, ecx              \
                                    __asm align   16                        \
                                    __asm _$ReadTestLoop_mov:               \
                                    __asm rdtsc                             \
                                    __asm mov     ebx, eax                  \
                                    __asm _$ReadTestReadLoop_mov:           \
                                    __asm mov     eax, [esi+ecx    ]        \
                                    __asm mov     edx, [esi+ecx+ 64]        \
                                    __asm mov     eax, [esi+ecx+128]        \
                                    __asm mov     edx, [esi+ecx+192]        \
                                    __asm mov     eax, [esi+ecx+ 32]        \
                                    __asm mov     edx, [esi+ecx+ 96]        \
                                    __asm mov     eax, [esi+ecx+160]        \
                                    __asm mov     edx, [esi+ecx+224]        \
                                    PROCESSORTESTREAD_MOV256RD64(0)         \
                                    PROCESSORTESTREAD_MOV256RD64(64)        \
                                    PROCESSORTESTREAD_MOV256RD64(128)       \
                                    PROCESSORTESTREAD_MOV256RD64(192)       \
                                    __asm add     ecx, 256                  \
                                    __asm jnz     _$ReadTestReadLoop_mov    \
                                    __asm rdtsc                             \
                                    __asm mov     esi, dwTemp0              \
                                    __asm sub     eax, ebx                  \
                                    __asm mov     ecx, dwTemp1              \
                                    __asm cmp     eax, dwCycleStampSpeed    \
                                    __asm ja      _$ReadTestNoBetter_mov    \
                                    __asm mov     dwCycleStampSpeed, eax    \
                                    __asm _$ReadTestNoBetter_mov:           \
                                    __asm dec     edi                       \
                                    __asm jnz     _$ReadTestLoop_mov        \
                                    __asm pop     ebx


 
Je vous fait une petite routine d'appel simple

Code :
  1. DWORD TestLecture ( long lNbElements, BYTE * pData )
  2. {
  3.     DWORD dwTemp0, dwTemp1;
  4.     DWORD dwCycleStampSpeed;
  5.     lNbElements &= 0x7FFFFF00; //Paquets de 256 octets uniquement
  6.     SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
  7.     SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
  8.     PROCESSORTESTREAD_MOV256
  9.     SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
  10.     SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
  11.     return dwCycleStampSpeed;
  12. }


L'avantage de la routine : Vitesse maximale avec une ligne de cache de 32 ou 64 octets.


Message édité par christophe_d13 le 12-07-2004 à 13:38:15
Reply

Marsh Posté le 12-07-2004 à 12:46:02    

el muchacho> Il y a tellement de tests...

Reply

Marsh Posté le 12-07-2004 à 13:00:43    

Je viens de faire un test sur un PIII-866 (133*6.5)
Débit mémoire plafonnant à plus de 1Go/s (débit également théorique).
 
Pour l'instant, je considère que le test est concluant et que ma routine est fiable.
 
Up: Sur un PIV (un serveur pas top à 2,66GHz pour 1Go de ram), j'obtiens 3616Mo/s. CPU-Z m'apprend :
- L1 Cache : 8Ko (de la daube !)
- L2 Cache : 512Ko
- FSB 133
- Bus 533
- Mémoire : 2/3/3/6


Message édité par christophe_d13 le 12-07-2004 à 13:36:12
Reply

Marsh Posté le 12-07-2004 à 13:23:37    

En comparant d'Athlon et le P4:
L1 = 28455 contre 17337
L2 = 11884 contre 14539
RAM = 2752 contre 3616
 
Je comprend mieux pourquoi le P4 se prend des claques de la part de l'athlon. On se demande d'ailleurs à quoi sert le cache L1 chez intel... Faudrait qu'ils pensent à le passer à 32Ko.


Message édité par christophe_d13 le 12-07-2004 à 16:24:57
Reply

Marsh Posté le 12-07-2004 à 15:32:48    

christophe_d13 a écrit :

En comparant d'Athlon et le P4:
L1 = 28455 contre 14539
L2 = 11884 contre 17337
RAM = 2752 contre 3616
 
Je comprend mieux pourquoi le P4 se prend des claques de la part de l'athlon. On se demande d'ailleurs à quoi sert le cache L1 chez intel... Faudrait qu'ils pensent à le passer à 32Ko.


 
Oui, c'est bizarre que les bursts du cache L1 soient inférieurs à ceux du L2.
Sinon, ton code, tu peux le faire "portable" (Linux/FreeBSD inside) ?


Message édité par el muchacho le 12-07-2004 à 15:33:14

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
Reply

Marsh Posté le 12-07-2004 à 16:24:45    

Erreur de ma part en écrivant les chiffres. Mais je confirme le peu d'importance (en cas de linear-read) du cache L1.
 
Pour le porter sous Linux, il faut tout passer en mode AT&T et j'ai pas trop le temps pour cela : "mov eax, ebx" => "movl %ebx, %eax"

Reply

Marsh Posté le 12-07-2004 à 21:06:49    

Petite mise à jour.
 
En tout, j'ai calculé 1856 combinaisons pour :
- Type de routine (L1, L2, RAM ou compromis)
- Taille de l'overlap
- Alignement
- Taille du transfert

Reply

Marsh Posté le 13-07-2004 à 00:59:09    

Je propose une fonction de copie nécessitant un CPU supportant SSE ou 3DNow!
Comparativement à la fonction de copie livrée avec visual C :
Sur le cache L1 : +112%
Sur le cache L2 : +41%
Sur la mémoire  : +6%
Cette routine n'est pas la plus performante, mais elle est assez simple à comprendre.

Code :
  1. void _MemoryCopy_MMX_SSE_hpf_fcache_o08_br01bw01_s0064 ( void * pTarget, void * pSource, long lSize )
  2.     {
  3.         __asm {
  4.             push        ebx
  5.             mov         eax, 568
  6.             mov         esi, pSource
  7.             xor         ebx, ebx
  8.             mov         ecx, lSize
  9.             mov         edx, 64
  10.            
  11.             mov         edi, pTarget
  12.             and         ecx, 0xFFFFFFC0
  13.             //Ne surtout pas aligner  
  14.         _$memcpy_loop:
  15.             //Occupe 4 octets de code
  16.             prefetchnta [esi+eax]
  17.            
  18.             //Occupe 64 octets de code
  19.             movq        mm0, [esi+ebx]
  20.             movq        mm1, [esi+8]
  21.             movq        [edi+ebx], mm0
  22.             movq        [edi+8], mm1
  23.             movq        mm2, [esi+16]
  24.             movq        mm3, [esi+24]
  25.             movq        [edi+16], mm2
  26.             movq        [edi+24], mm3
  27.             movq        mm4, [esi+32]
  28.             movq        mm5, [esi+40]
  29.             movq        [edi+32], mm4
  30.             movq        [edi+40], mm5
  31.             movq        mm6, [esi+48]
  32.             movq        mm7, [esi+56]
  33.             movq        [edi+48], mm6
  34.             movq        [edi+56], mm7
  35.             //Occupe 8 octets de code
  36.             add         esi, edx
  37.             add         edi, edx
  38.             sub         ecx, edx
  39.             jnz         _$memcpy_loop
  40.             emms
  41.             pop ebx
  42.         }
  43.     }


 
Voici une autre fonction plus tordue (qui n'apporte pas grand chose) mais qui, sur les cpu avec une FPU lente (6x86) permet de gratter un peu (très peu en fait 5-15%):

Code :
  1. //Routine de copie 2 à 2 : esi+ecx => edi+ecx
  2.     #define OPCODE_COPY_2BY2(opread, opwrite, reg0, reg1, offset0, offset1, offsetglobal)                    \
  3.                                                 __asm opread    reg0, [esi+ecx+offset0+offsetglobal]         \
  4.                                                 __asm opread    reg1, [esi+ecx+offset1+offsetglobal]         \
  5.                                                 __asm opwrite   [edi+ecx+offset0+offsetglobal], reg0         \
  6.                                                 __asm opwrite   [edi+ecx+offset1+offsetglobal], reg1
  7.     #define MEMCPY_PREPARE_ESI_EDI_ECX(blocsize)                                                             \
  8.                                                 __asm mov         ecx, lSize                                 \
  9.                                                 __asm mov         esi, pSource                               \
  10.                                                 __asm and         ecx, 0xFFFFFFFF^(blocsize-1)               \
  11.                                                 __asm mov         edi, pTarget                               \
  12.                                                 __asm add         esi, ecx                                   \
  13.                                                 __asm add         edi, ecx                                   \
  14.                                                 __asm neg         ecx
  15. void _MemoryCopy_MOV_____mpf_fcache_o04_br01bw01_s0064 ( void * pTarget, void * pSource, long lSize )
  16.     {
  17.         __asm {
  18.             push ebx
  19.             push ebp
  20.             MEMCPY_PREPARE_ESI_EDI_ECX(64)
  21.             align 16
  22.         _$memcpyloop:
  23.             OPCODE_COPY_2BY2(mov,mov,eax,ebx, 0,32,0)
  24.             OPCODE_COPY_2BY2(mov,mov,edx,ebp, 4, 8,0)
  25.             OPCODE_COPY_2BY2(mov,mov,eax,ebx,12,16,0)
  26.             OPCODE_COPY_2BY2(mov,mov,edx,ebp,20,24,0)
  27.             OPCODE_COPY_2BY2(mov,mov,eax,ebx,28,36,0)
  28.             OPCODE_COPY_2BY2(mov,mov,edx,ebp,40,44,0)
  29.             OPCODE_COPY_2BY2(mov,mov,eax,ebx,48,52,0)
  30.             OPCODE_COPY_2BY2(mov,mov,edx,ebp,56,60,0)
  31.             add         ecx, 64
  32.             jnz         _$memcpyloop
  33.             pop         ebp
  34.             pop         ebx
  35.         }
  36.     }


 
Par rapport à une fonction de copie plus classique par 'mov reg,mem' puis 'mov mem,reg' :
- Sur le cache L1 : +15%
- Sur le cache L2 : +6%
- Sur la mémoire : +2%
 
En comparant avec la classique memcpy de visual
- Sur le cache L1 : +18%
- Sur le cache L2 : +15%
- Sur la mémoire : +4%
 
 
Codes (c) 2004 Christophe Gossa


Message édité par christophe_d13 le 13-07-2004 à 01:02:52
Reply

Marsh Posté le 13-07-2004 à 08:39:02    

Histoire de se prendre le choux encore un peu...
Une variante de la copie 'mov reg/mem,reg/mem' précédente :
Comparaison avec la précédente version
- Cache L1 : +5%  
- Cache L2 : +2%
- Mémoire  : 0%
 

Code :
  1. void _MemoryCopy_MOV2____mpf_fcache_o04_br01bw01_s0064 ( void * pTarget, void * pSource, long lSize )
  2.     {
  3.         __asm {
  4.             mov     ecx, lSize
  5.             mov     edx, 64
  6.             mov     esi, pSource
  7.             xor     eax, eax
  8.             mov     edi, pTarget         
  9.             and     ecx, 0xFFFFFFC0
  10.             sub     edi, 64
  11.             push ebx
  12.             push ebp
  13.         _$memcpyloop:
  14.             mov     ebx, [esi+eax]
  15.             mov     ebp, [esi+ 32]
  16.             mov     [edi+ 64], ebx
  17.             mov     [edi+ 96], ebp
  18.             lea     edi, [edi+edx]
  19.             sub     ecx, edx
  20.             mov     ebx, [esi+ 4]
  21.             mov     ebp, [esi+ 8]
  22.             mov     [edi+ 4], ebx
  23.             mov     [edi+ 8], ebp
  24.             mov     ebx, [esi+12]
  25.             mov     ebp, [esi+16]
  26.             mov     [edi+12], ebx
  27.             mov     [edi+16], ebp
  28.             mov     ebx, [esi+20]
  29.             mov     ebp, [esi+24]
  30.             mov     [edi+20], ebx
  31.             mov     [edi+24], ebp
  32.             mov     ebx, [esi+28]
  33.             mov     ebp, [esi+36]
  34.             mov     [edi+28], ebx
  35.             mov     [edi+36], ebp
  36.             mov     ebx, [esi+40]
  37.             mov     ebp, [esi+44]
  38.             mov     [edi+40], ebx
  39.             mov     [edi+44], ebp
  40.             mov     ebx, [esi+48]
  41.             mov     ebp, [esi+52]
  42.             mov     [edi+48], ebx
  43.             mov     [edi+52], ebp
  44.             mov     ebx, [esi+56]
  45.             mov     ebp, [esi+60]
  46.             mov     [edi+56], ebx
  47.             mov     [edi+60], ebp
  48.             lea     esi, [esi+edx]
  49.             jnz     _$memcpyloop
  50.             pop         ebp
  51.             pop         ebx
  52.         }
  53.     }


Code (c) 2004 Christophe Gossa


Message édité par christophe_d13 le 13-07-2004 à 08:40:53
Reply

Marsh Posté le 13-07-2004 à 08:56:21    

christophe_d13 a écrit :

Erreur de ma part en écrivant les chiffres. Mais je confirme le peu d'importance (en cas de linear-read) du cache L1.
 
Pour le porter sous Linux, il faut tout passer en mode AT&T et j'ai pas trop le temps pour cela : "mov eax, ebx" => "movl %ebx, %eax"


 
Demande à Taz, je suis sûr que ça l'intéresse. :whistle:  
Mais pour cela, il faut que tu passes ta librairie en LGPL.


Message édité par el muchacho le 13-07-2004 à 08:57:44

---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
Reply

Marsh Posté le 13-07-2004 à 09:00:05    

christophe_d13 a écrit :


Code (c) 2004 Christophe Gossa


:ange:


Message édité par jagstang le 13-07-2004 à 09:14:42

---------------
What if I were smiling and running into your arms? Would you see then what I see now?  
Reply

Marsh Posté le 13-07-2004 à 09:00:27    

Taz a écrit :

non, il fait pas du tout la même chose, lui il fait du SIMD, pas de la branlette qui accélère l'internet


 
LMAO ^^ je quote

Reply

Marsh Posté le 13-07-2004 à 09:01:10    

el muchacho a écrit :

Bah, joelf fait bien le meme genre d'optimisations avec son altivec, non ?


 
Ouais sauf que c'est pas des copies mémoires que j'optimise ^^

Reply

Marsh Posté le 13-07-2004 à 10:11:48    

Après avoir testé sur plusieurs plateformes (PII, PIII, P4, AthlonXP) une trentaine de fonctions, j'en ai retenue que 13. Les autres n'apportent jamais rien et ralentissent la procédure de test :
- les classiques MOVSB et MOVSD
- 2 routines "mov reg/mem, reg/mem"
- 2 routines utilisant la FPU (pratique sur les vieilles bécanes)
- 1 routine MMX
- 2 routines SSE
- 4 routines MMX/SSE compatibles MMX/3DNow! (utilisation prefetch)
 


Message édité par christophe_d13 le 13-07-2004 à 10:17:12
Reply

Marsh Posté le 15-07-2004 à 00:26:11    

ça avance encore.
J'ai terminé la phase de sélection du compromis.
Il ne me reste qu'à faire la routine de copie à proprement parlé qui sélectionnera la meilleure routine.
 
Je vais également inclure un test de performance pour comparer le memcpy de visual c avec ma routine.
Hélas je ne pourrait comparer avec celle de AMD, car elle ne supporte pas l'overlap inférieur à 8.
 
Le grand intérêt de ma routine c'est que chacun peu ajouter son code et le programme choisira toujours parmis le meilleur.
Actuellement, j'ai 152 tests pour chacune des 13 routines soit 3780 tests allant de 128 octets à 2Mo.
 
Au final, j'ai réussi à réduire le nombre de combinaisons à 928.


Message édité par christophe_d13 le 15-07-2004 à 00:30:17
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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