Finalement, voici le code assembleur de la fonction suivante g�n�r� pour un 
processeur Itanium. Note : j'ai pris un tableu assez grand pour �viter les 
"loop unrolling" et poub=voir tester les performances (pas fait pour finir)

        uint BitCount(uint *w)
        {
                uint r = 0;
                uint i;

                for (i = 0; i < 65536; i++)
                {
                        r += *w & 0x2;
                        *w <<= 1;
                }

                return(r);
        }

Ce code doit �tre interpr�t� apr�s avoir lu les documents mentionn�s dans un 
de mes mails d'hier. Sinon, toute conclusion rel�ve du folklore... Pour 
m�moire, Itanium a quadrupl� chacune de ses unit� fonctionnelle, il engendre 
(dans ce cas) du code en "modulo scheduled loop" et il peut effectuer jusqu'� 
4 op�ration en // par unit� fonctionelle...

..L2:
BitCounter::
//file/line/col vm_app.c/45/1
//      ***EntryOp***   CMid911, r32 =             // A [vm_app.c: 45/1]
        alloc           r31 = ar.pfs, 1, 9, 0, 8   // M [vm_app.c: 45/1] [UVU: ]
        mov             ar.ec = 2                  // I
        brp.loop.few.imp ..L3, ..LB918             // B
        ld4             r33 = [r32]                // M [vm_app.c: 54/9] [UVuse]
        add             r8 = 0xffff, r0         ;; // I
        mov             r40 = ar.lc                // I [vm_app.c: 45/1]
        add             r9 = 0, r32             ;; // M
        nop.m           0                          // M
        mov             r41 = pr                   // I [vm_app.c: 45/1]
//      ***PseudoFenceOp***                        // A [vm_app.c: 45/1] [UVU: ]
        cmp.ne.or.andcm p16, p17 = 42, r0       ;; // M
        nop.m           0                          // M
        mov             ar.lc = r8                 // I
//file/line/col vm_app.c/50/6,52/5,54/9
        add             r8 = 0, r0                 // M [vm_app.c: 50/6] [UVU: ]
        nop.i           0                          // I
        nop.b           0                       ;; // B

..L3:
        nop.m           0                          // M
(p16)   extr.u          r32 = r33, 16, 16          // I [vm_app.c: 55/9]
(p16)   and             r34 = 2, r33               // I [vm_app.c: 54/9]
(p17)   add             r8 = r8, r35               // M [vm_app.c: 54/9]
        nop.f           0                          // F
[..LB918:] br.ctop.dptk.few ..L3                ;; // B [vm_app.c: 52/16]

..L4:
//file/line/col vm_app.c/58/5
        add             r33 = 0, r34               // M
        mov             ar.lc = r40                // I
        add             r32 = 0, r9             ;; // I
        st4             [r32] = r33                // M [vm_app.c: 55/9] [UVuse]
        mov             pr = r41, 0x1fffe          // I [vm_app.c: 58/5]
        br.ret.sptk.few rp                      ;; // B [vm_app.c: 58/5]

..L1:
//      ***EndOp***                             ;; // A

        .endp   BitCounter

Un mec d'HP m'a signal� qu'il existe une isnstruction beaucoup plus efficace 
pour compter les bits. Voici donc le code :

        #include <machine/inline.h>

        uint BitCount(uint *w)
        {
                uint r = 0;
                uint i;
                for (i = 0; i < 65536; i++)
                {
                        r += _Asm_popcnt(*w);
                        w++;
                }
        }

A mon avis, il faut aussi r�duire le nombre de boucle car l'op�ration 
s'effectue sans doute sur 32 bits � la fois. DOnc pour un tableau de 128K  
bits (131072), on n'effectue plus que 4096 boucles, au lieu de 65536 avec la 
m�thode pr�c�dente. De plus, l'instruction popcnt n'utilise qu'un seul cycle 
machine au lieu de plusieurs isntructions avec '& <<'. Notez aussi que 
l'incr�mentation de w et i peut se faire dans le m�me cycle machine.

Un nouveau m�tier se dessine : programmeur assembleur sur Itanium :-)

Daniel




--
http://www-internal.alphanet.ch/linux-leman/ avant de poser
une question. Ouais, pour se d�sabonner aussi.

Répondre à