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.