Jeux d’instructions multimédia (Multimedia instruction sets) Jacques-Olivier Haenni EPFL - DI - LSL 1er décembre 1999 Plan z Introduction z Jeux d’instructions multimédia y généralités y données y instructions z Utilisation de ces instructions z Etat de la recherche z Conclusion Introduction z Applications multimédia : y données sur 8, 12 ou 16 bits 64 bits y boucles, calculs répétitifs z Processeurs actuels : 64 bits ⇒ gaspillage des ressources 16 bits 16 bits 16 bits 16 bits z Solution : plusieurs valeurs dans un registre z Les instructions multimédia ou instructions SIMD traitent des vecteurs de nombres entiers ou à virgule flottante. Généralités z Jeux d’instructions multimédia y y y y y y y y y VIS (Visual Instruction Set), SUN 1995 MAX-2 (Multimedia Acceleration eXtensions), HP 1996 MMX (Multimedia Extensions), Intel 1997 MVI (Motion Video Instructions), Digital 1997 3DNow!, AMD 1998 Altivec, Motorola 1999 MDMX (Mad Max, MIPS Digital Media eXtensions), SGI 1999? Internet SSE (Streaming SIMD Extensions), Intel 1999 Merced, HP - Intel 2000 z Nombre d’instructions : de 13 à 162 Types de données z Vecteurs d’entiers (et virgule fixe) : y 8x8 bits, 4x16 bits, 2x32 bits y 16x8 bits, 8x16 bits, 4x32 bits 64 bits 16 bits 16 bits 16 bits 16 bits z Vecteurs de nombres à virgule flottante y 2x32 bits y 4x32 bits z Stockés : 128 bits 32 bits 32 bits y dans les registres à virgule flottante y dans les registres entiers y dans des registres dédiés 32 bits 32 bits Instructions z Instructions load/store z Instructions arithmétiques et logiques y sources et destination de même taille y sources et destination de tailles différentes y réduction z Instructions de comparaison z Instructions de réarrangement des données z Instructions spéciales Instructions arithmétiques Source 1 Source 2 add/sub (un)signed mod/sat, avg, abs. diff., min/max,... Destination z Ex. : addition 8 bits non signée avec saturation : • + = 32 62 94 45 230 255 87 12 99 184 100 255 Instructions arithmétiques z Multiplication 8x16 (VIS Fmul8x16) x rés. : 16 bits de poids fort du produit Source 1 Source 2 Destination z Multiplication 16x16 (Merced pmpyshr2) Source 1 Source 2 multiplication 16x16-->32 Res. int. (sur 32 bits) shift right and mask (0x0000FFFF) Destination Instructions arithmétiques z “Packed multiply-add word to doubleword”, MMX Source 1 A3 A2 A1 A0 Source 2 B3 B2 B1 B0 multiplication 16x16-->32 Res. int. (sur 32 bits) A1.B1 A0.B0 addition Destination A3.B3 + A2.B2 A1.B1 + A0.B0 Instructions de comparaison Source 1 Source 2 ==, !=, <, >,... Destination z Exemple : Source 1 200 93 32 192 Source 2 53 152 32 245 > Destination 0xFFFF 0x0000 0x0000 0x0000 Instructions de comparaison z Exemple : y for i=0… do if a[i] > 0 then s[i] = s[i] + a[i] a 63 -78 -1 12 0 0 0 0 > 0xFFFF 0x0000 0x0000 0xFFFF 63 a -78 & s 57 29 112 59 63 0 + 120 29 112 71 0 12 -1 12 Instructions de réarrangement z Mix (Merced) z Pack avec saturation (Merced) Instructions de réarrangement z Mux (Merced) 7 6 5 4 3 2 1 0 2 3 4 5 1 6 1 7 Autres instructions z Psad (Merced), Parallel sum of absolute difference a b = c 7 c = ∑ ai − bi = a0 − b0 + a1 − b1 + L + a7 − b7 i =0 z Se retrouve aussi dans VIS (pdist) par exemple Stockage des données en mémoire z Ex.: image couleur avec z-buffer (4 composantes 8 bits : R, G, B et Z) y 1ère possibilité : un tableau de points RGBZRGBZRGBZRGBZ…. y 2ème possibilité : 4 tableaux distincts RRRR…GGGG…BBBB…ZZZZ… Stockage des données en mémoire z Problèmes des alias y for (i = 0; i < 100; i++) { c[i] = a[i] + b[i]; } y for (i = 0; i < 100; i++) { c[i] = a[i] + b[i] // c[i+1] = a[i+1] + b[i+1] // c[i+2] = a[i+2] + b[i+2] // c[i+3] = a[i+3] + b[i+3]; } z Est-ce que a, b et c se chevauchent ? z Problème dû aux pointeurs de C... Comment utiliser ces instructions ? z Les compilateurs actuels ne supportent pas les instructions multimédia z Solutions : y code assembleur y instrinsics y Vector Class Library y Intel vectorizing compiler y bibliothèques de routines Code assembleur z Exemple, iDCT (MMX) : void MMX_iDCT8x8AAN(short *coef_block) { __asm { …… movq mm5, [eax][8*8] psubw mm1, mm0 //new three below: movq mm7, xm1 psllw mm1, 2 pmulhw mm1, mm7 paddw mm2, mm0 movq mm0, mm2 movq mm4, mm3 paddw mm3, mm5 psubw mm1, mm0 psubw mm4, mm5 movq mm6, mm3 paddw mm3, mm2 ……… ; V8 ; V16 (s1) ; 23170 ->V18 (s3) ; ; ; ; ; ; ; ; V17 duplicate V17 duplicate V0 V19 V21, mm0 free V20, mm5 free duplicate t74=t81 V22 Code assembleur z Exemple, add8 (VIS) : for (j = 0; j < size; j++) { *da = ((*sa1) + (*sa2)) >> 1; sa1++; sa2++; da++; } ld fexpand [%g4],%f2 %f4,%f8 add ld add cmp fexpand ld add fexpand fexpand fpadd16 fpadd16 fpack16 st fpack16 st add bcs,a,pt ld %g2,1,%g2 [%g5+4],%f5 %g5,8,%g5 %g2,%g1 %f2,%f12 [%g4+4],%f3 %g4,8,%g4 %f5,%f6 %f3,%f10 %f8,%f12,%f8 %f6,%f10,%f6 %f8,%f0 %f0,[%g3] %f6,%f0 %f0,[%g3+4] %g3,8,%g3 %icc,.L900000414 [%g5],%f4 Intrinsics z Exemple (SSE) : void toto () { for (int j=0; j<SIZE; j++) xa[j] = xb[j] + q*xc[j]; } void toto () { __m128 tmp0, tmp1; tmp1 = _mm_set_ps1(q); for (int j=0; j<SIZE; j+=VECTOR_SIZE) { tmp0 = _mm_mul_ps(*((__m128*)&xc[j]), tmp1); *(__m128*)&xa[j] = _mm_add_ps(tmp0, *((__m128*)&xb[j])); } } Intrinsics z Exemple, add8 (VIS) : for (j = 0; j < size; j++) { *da = ((*sa1) + (*sa2)) >> 1; sa1 ++; sa2 ++; da ++; } for (j = 0; j < size; j++) { sd1 = *sa1; sd2 = *sa2; rd1h = vis_fexpand_hi(sd1); rd2h = vis_fexpand_hi(sd2); rd1l = vis_fexpand_lo(sd1); rd2l = vis_fexpand_lo(sd2); rdh = vis_fpadd16(rd1h, rd2h); rdl = vis_fpadd16(rd1l, rd2l); dd = vis_fpack16_to_hi(dd, rdh); dd = vis_fpack16_to_lo(dd, rdl); *da sa1 sa2 da } = dd; ++; ++; ++; Vector Class Library z Exemple (SSE) : void toto () { for (int j=0; j<SIZE; j++) xa[j] = xb[j] + q*xc[j]; } void toto F32vec4 F32vec4 F32vec4 F32vec4 () { q_xmm = *xa_xmm *xb_xmm *xc_xmm (q, q, q, q); = (F32vec4*)&xa; = (F32vec4*)&xb; = (F32vec4*)&xc; for (int j=0; j < SIZE/VECTOR_SIZE; j++) xa_xmm[j] = xb_xmm[j] + q_xmm*xc_xmm[j]; } Intel Vectorizing Compiler z Le programmeur doit aider le compilateur z Beaucoup de restrictions __declspec(align(16)) float xa[SIZE], xb[SIZE], xc[SIZE]; float q; float xa[SIZE], xb[SIZE], xc[SIZE]; float q; void toto (float *restrict a, float *restrict b, float *restrict c) { #pragma vector aligned void toto () { for (int j=0; j<SIZE; j++) xa[j] = xb[j] + q*xc[j]; } } void main () { toto(); } void main () { toto (xa, xb, xc); } for (int j=0; j<SIZE; j++) a[j] = b[j] + q*c[j]; Performances z Intel MMX iDCT y démo fournie par Intel Speed-up 6 5 4 3 2 1 0 C version MMX assembly z Sun VIS add8 y exemple tiré du development kit de Sun MMX intrinsics Vector Class Library Speed-up 5 4 3 2 1 0 C version VIS Les jeux vidéo z Principal problème : graphisme 3D y nombres à virgule flottante z La plupart des jeux n’utilisent pas directement les instructions multimédia y elles sont arrivées trop tard y MMX ne supporte par les nombres à virgule flottante y l’assembleur n’est utilisé qu’en dernier recours Etat de la recherche (1) z High-level tools and compiler technology for multimedia instruction sets, University of Bristol z Compilation for SWAR (SIMD Within a Register) Processors, Purdue University y dialecte C z An optimizer for Multimedia Instruction Sets, Standford University y basé sur SUIF Etat de la recherche (2) z A Vectorizing SUIF Compiler, University of Toronto y utilise des vecteurs de 32 à 128 composantes y M.A.Sc. Thesis: Automatic Compilation for Short Vector Extensions z Replication vs. widening, Universitat Politècnica de Catalunya z Performance of Image and Video Processing with General-Purpose Processors and Media ISA Extensions, Rice University & Compaq Conclusion z Les jeux d’instructions multimédia sont devenus : y plus complets y mieux intégrés y mieux adaptés pour la compilation ? z Travail futur : y adaptation de Impact pour les jeux d’instructions multimédia