1 / 39

SIMD

SIMD. Single Instruction Multiple Data. Piotr Dałek. Motywacja. Złożone przetwarzanie dużej ilości danych Dużo kodu Głodzone segmenty procesorów Coraz większe wymagania względem jakości treści Marketing i wojny rynkowe. Dużo kodu. Pascal:. Dużo kodu.

chaka
Download Presentation

SIMD

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. SIMD Single InstructionMultiple Data Piotr Dałek

  2. Motywacja • Złożone przetwarzanie dużej ilości danych • Dużo kodu • Głodzone segmenty procesorów • Coraz większe wymagania względem jakości treści • Marketing i wojny rynkowe

  3. Dużo kodu • Pascal:

  4. Dużo kodu ainUnit.pas.152: destvtx.x := ((srcvtx.x*(transmat^)[0]) + (srcvtx.y * (transmat^)[1]) + (srcvtx.z * (transmat^)[2])); 00453A2E D906 flddwordptr [esi] 00453A30 D808 fmuldwordptr [eax] 00453A32 D94604 flddwordptr [esi+$04] 00453A35 D84804 fmuldwordptr [eax+$04] 00453A38 DEC1 faddpst(1) 00453A3A D94608 flddwordptr [esi+$08] 00453A3D D84808 fmuldwordptr [eax+$08] 00453A40 DEC1 faddpst(1) 00453A42 D91B fstpdwordptr [ebx] 00453A44 9B wait MainUnit.pas.153: destvtx.y := ((srcvtx.x*transmat^[4]) + (srcvtx.y * transmat^[5]) + (srcvtx.z * transmat^[6])); 00453A45 D906 flddwordptr [esi] 00453A47 D84810 fmuldwordptr [eax+$10] 00453A4A D94604 flddwordptr [esi+$04] 00453A4D D84814 fmuldwordptr [eax+$14] 00453A50 DEC1 faddpst(1) 00453A52 D94608 flddwordptr [esi+$08] 00453A55 D84818 fmuldwordptr [eax+$18] 00453A58 DEC1 faddpst(1) 00453A5A D95B04 fstpdwordptr [ebx+$04] 00453A5D 9B wait MainUnit.pas.154: destvtx.z := ((srcvtx.x*transmat^[8]) + (srcvtx.y * transmat^[9]) + (srcvtx.z * transmat^[10])) + 400; 00453A5E D906 flddwordptr [esi] 00453A60 D84820 fmuldwordptr [eax+$20] 00453A63 D94604 flddwordptr [esi+$04] 00453A66 D84824 fmuldwordptr [eax+$24] 00453A69 DEC1 faddpst(1) 00453A6B D94608 flddwordptr [esi+$08] 00453A6E D84828 fmuldwordptr [eax+$28] 00453A71 DEC1 faddpst(1) 00453A73 D805043B4500 fadddwordptr [$00453b04] 00453A79 D95B08 fstpdwordptr [ebx+$08] 00453A7C 9B wait […] Zaledwie fragment!

  5. Dużo kodu movups xmm0, [ecx] movups xmm1, [ecx+$10] movups xmm2, [ecx+$20] @next: movups xmm4, [eax+esi] movups xmm5, xmm4 movups xmm6, xmm4 mulps xmm4, xmm0 movups [edx+esi], xmm4 mulps xmm5, xmm1 movups [edx+esi+$10], xmm5 fld [edx+esi] fadd [edx+esi+4] fadd [edx+esi+8] mulps xmm6, xmm2 movups [edx+esi+$20], xmm6 fstp [edx+esi] fld [edx+esi+16] fadd [edx+esi+20] fadd [edx+esi+24] fstp [edx+esi+4] fld [edx+esi+32] fadd [edx+esi+36] fadd [edx+esi+40] fadd [eax+esi+12] // srcvrt.zero fst [edx+esi+8] fldxe fdivst(0), st(1) fldst(0) fmul [edx+esi] fstp [edx+esi] movups xmm4, [edx+esi] mulps xmm4, xmm4 movups [edi], xmm4 fld [edi] fadd [edi+4] fadd [edi+8] fstp [edi] addedi, 4 addesi, $10 jnz @next pop edi movesi, 196608*4 moveax, maxmem addeax, esi negesi movups xmm0, [eax+esi] sqrtps xmm1, xmm0 movups xmm1, [eax+esi] sqrtps xmm0, xmm1 @nextmax: movups xmm2, [eax+esi] sqrtps xmm2,xmm2 maxps xmm0, xmm2 movups [eax+esi], xmm2 minps xmm1, xmm2 addesi, 16 jnz @nextmax moveax, maxmem movups [eax], xmm0 movups [eax+16], xmm1 Całość!

  6. Głodzone segmenty procesora • XOR jako instrukcja prosta SIMD • Potoki U oraz V • Niewykorzystana przepustowość szyny • Hyperthreading jako automat do zwiększania utylizacji segmentów procesora

  7. XOR - SIMD • Performs a bitwise exclusive OR (XOR) operation on the destination (first) and source (second) operands andstores the result in the destination operand location. The source operand can be an immediate, a register, or amemory location; the destination operand can be a register or a memory location. (However, two memory operandscannot be used in one instruction.) Each bit of the result is 1 if the corresponding bits of the operands aredifferent; each bit is 0 if the corresponding bits are the same. • This instruction can be used with a LOCK prefix to allow the instruction to be executed atomically.

  8. XOR - SIMD

  9. XOR - SIMD • XOR EAX, EBX A B C D EAX XOR W X Y Z EBX A^W B^X C^Y D^Z EAX

  10. XOR - SIMD • Szyfrowanie 8-miobitowym kluczem • Szyfrowanie po 8, 16 i 32 bity naraz • Pętla warunkowa bez warunku • Base+Displacement

  11. XOR - SIMD • Zawodnik #1: Pentium I (200MHz) • 8KB L1 Cache • 8bit – ZZZzzZZZzzZzzzzzzzzzzz… …477,40s • 16bit – 310,35s = 1,53x • 32bit – 268, 4 s = 1,77x • 32bit_4 – 268,4 s = 1,77x

  12. XOR - SIMD • Zawodnik #2: Atom 330 (1,6GHz, HT) • 24kB L1 Cache (x2, per rdzeń) • 8bit – 101,6 s = 1x • 16bit – 47,2 s = ~2,15x • 32bit – 17,38 s = ~5,84x • 32bit_4 – 16,97 = ~5,98x

  13. XOR - SIMD • Zawodnik #3 - Core 2 Duo E4400 (2GHz + ovrclk 0,4GHz) • 64kB L1 cache (per rdzeń, 32kB instrukcje, 32kB dane) • 8bit – 10,1 s = 1x • 16bit – 7,75 s = ~1,30x • 32bit – 7,50 s = ~1,34x • 32bit_4 – 7,30s = ~1,38x

  14. XOR - SIMD • Zawodnik #4 - Corei7 2660 (3,4GHz) • 64kB L1 cache (per rdzeń) • 8bit – 9,44 s = 1x • 16bit – 4,90 s = ~1,92x • 32bit – 2,65 s = ~3,56x • 32bit_4 – 2,11 s = ~4,47x

  15. XOR - SIMD • Pamięć wąskim gardłem? • 16MB*1000/7,30 = 2191 MB/s = >2GB/s • E4400 ma zaledwie 2 MB cache l2, wykluczamy „palenie cache” • DDR2/800 ma teoretyczną przepustowość 6,4GB/s • Dlaczego takie małe różnice dla C2d i takie gigantyczne dla Atoma330 i Core i7?

  16. Potoki U i V • Pentium procesorem superskalarnym • V na instrukcje proste • U na wszystkie instrukcje • Instrukcje w potoku U wykonują się równolegle z instrukcjami z potoku V • Out-of-orderexecution automatyzuje to

  17. Niewykorzystana przepustowość • 2,1GB < 6,4GB • FPU jako akcelerator kopiowania pamięci • 8 bajtów > 4 bajty • Dobre rozwiązanie nie zawsze brzmi rozsądnie ;) @@Loop: fildqwordptr [eax+ecx] fistpqwordptr [edx+ecx] addecx, 8 jl @@Loop

  18. Rosnące wymagania • Doom: 320x200x8bpp

  19. Rosnące wymagania • GLQuake: WOOO SVGA!!!1111oneoneoneeleven • (640x480x16bpp)

  20. Rosnące wymagania • SupremeCommander - dwa monitory (1680x1050 + 1024x768), pełne 3D

  21. MMX • MultiMediaeXtensions • 1997 rok • Nikt nie był na to przygotowany, WIEEELKI zawód ze strony Wintela • EMMS

  22. MMX

  23. MMX na przykładzie PADDB A B C D E F G H MM0 PACKED ADD BYTES S T U V W X Y Z MM1 A+S B+T C+U D+V E+W F+X G+Y H+Z MM0

  24. MMX na przykładzie PADDB • Jedna instrukcja równoważna ośmioprzebiegowej pętli albo 16 instrukcjom • Problem – ilości danych nie wyrównane do paczek MMX

  25. MMX – kolejny przykład • Unicode • Dwa bajty na znak • ASCII to podzbiór Unicode • Kompresja 50% bez strat! • Przepleść znaki zerami • Wersja MMX 4x szybsza niż x86 • Oszczędność miejsca bez wyraźnej straty wydajności Wikipedia - weryfikacja adresu e-mail P.i.o.t.r. .D.a.B☺e.k.

  26. MMX – kolejny przykład • pxor mm0, mm0 • @next: • movq mm1, [eax ] • movq mm2, [eax+8] • addeax, 16 • packuswb mm1, mm2 • movq [edx], mm1 • addedx, 8 • cmpeax, ecx • jne @next • emms • @nextslow: • pop ecx • cmpecx, eax • jbe @sret • @nextsl: • movbl, [eax] • mov [edx], bl • addeax, 2 • addedx, 1 • cmpecx, eax • jne @nextsl • @sret: • pop ebx • @qret: pxor mm0, mm0 @next: movd mm1, [eax] movd mm2, [eax+4] punpcklbw mm1, mm0 punpcklbw mm2, mm0 movq [edx ], mm1 movq [edx+8 ], mm2 addeax, 8 addedx, 16 cmpeax, ecx jb @next emms

  27. 3DNow • MMX nie zapewniało instrukcji obsługujących wektory zmiennoprzecinkowe • Pole do popisu dla AMD, próba monopolizowania rynku • Intel oczywiście tego nie wspiera… • Niedawno się z tego całkowicie wycofali, więc odłóżmy to do lamusa • Perełki: FEMMS, PREFETCH/PREFETCHW, operacje horyzontalne (Intel śpi aż do SSE3)

  28. SSE • Streaming SIMD Extensions • Odpowiedź Intela na 3DNow • Szereg nowych instrukcji, nowe rejestry (XMMx) • MOVUPS, MOVAPS, i „nie rozumiem czemu *TU* mam GPFy!” • Przykładowy program

  29. SSE2 • 128-bitowe typy danych • DUŻO instrukcji do zabawy z wektorami zmiennoprzecinkowymi • Instrukcje do hurtowej konwersji Single/Double/Int • Kontrola nad Cache • CFLUSH • MOVNTI, MOVNTDQ, MOVNTPD • Pause

  30. SSE3 • Działanie w poziomie • HSUBPS, HADDPS, HADDPD, HSUBPD • MONITOR, MWAIT • Zwiększenie wydajności przy dostępie na skraju linii pamięci cache • LDDQU • Duplikacja elementów • MOVSHDUP, MOVSLDUP, MOVDDUP

  31. AES-NI • Intel pozazdrościł VIA ichniego PadlockEngine • Nowe instrukcje zapewniające sprzętowe szyfrowanie AES: • AESDEC, AESDECLAST, AESENC, AESENCLAST, AESIMC, AESKEYGENASSIST.

  32. AVX • AdvancedVectorExtensions • 256-bitowe typy danych • Wyższa szkoła jazdy ;)

  33. Problemy z SIMD • Niebanalne • Optymalny układ danych nie jest optymalny w rozumieniu X0 Y0 Z0 00 X1 Y1 Z1 00 X0 X1 X2 X3 Y0 Y1 Y2 Y3

  34. Problemy z SIMD • Wymagane dokładne rozumienie, co i jak działa • Trik z pętlą bez cmp to chleb powszedni • Wymaga dużo czasu programisty • Różne wsparcie dla różnych instrukcji i konieczność radzenia sobie z różnymi konfiguracjami • Mam SSE, ale nie mam HADDPS, bo to jest dopiero w SSE3 • Używam recznej serii FADD(P) albo tak organizuję dane, bym mógł użyć ADDPS

  35. Przykładowa aplikacja • „Obraz na powierzchni” • Wcale nie texture-mapping

  36. Przykładowa aplikacja • Delphi 7, natywny kod • Wersja z „przelicznikiem” działającym po FPU • Wersja SSE • Wersja CUDA (w trakcie) • C#, p-c0de • ASM niedopuszczalny (zasadniczo) • Wskaźniki są be • Nie oczekujmy cudów

  37. Wyniki

  38. Konkluzje • Kod SSE słabo zoptymalizowany • Użycie HADDPS albo reorganizacja elementów wektorów zapewne poprawiłaby wydajność • Wynik, jak na pierwszy raz, zadowalający • Duży potencjał leżący w instrukcjach SSE który nie jest łatwy w wykorzystaniu • Zabawa dla kombinatorów 

  39. Wsparcie mechaniczno-merytoryczne • Intrinsice • Wszędzie • Automatyczna wektoryzacja (GCC, ICC, MSVC?) • ICC drogi i wredny • Udowodniono, że wygenerowany kod „degraduje” się na procesorach AMD • vTune i inne wynalazki • Dokumentacja Intela

More Related