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.