8. Architektura Power

Transkrypt

8. Architektura Power
Materiały do wykładu
8. Architektura Power
Marcin Peczarski
Instytut Informatyki
Uniwersytet Warszawski
31 maja 2009
Narodziny
 .
⊲ 1991 konsorcjum AIM
⊲ Apple – komputery Macintosh z procesorami serii 68000
⊲ IBM – procesor POWER (Performance Optimization With Enhanced RISC) – superskalarny prawie RISC
⊲ Motorola – wtedy główny konkurent Intela, bardzo popularne CISC
serii 68000 i niezbyt popularne RISC serii 88000
⊲ PPC = PowerPC = Power Performance Computing
Rozwój
⊲ 1993 – 32-bitowy PPC 601
⊲ 1995 – PPC 603, 604
⊲ 1997 – 64-bitowy PPC 620
⊲ 1997 – PPC 750 – Power Macintosh G3
⊲ 1999 – PPC 7400 – obliczenia wektorowe
⊲ 2005 – PPC 970, dwurdzeniowy 64-bitowy POWER5
⊲ 2007 – POWER6
⊲ 2010 – POWER7 ?
 .
Najważniejsze zastosowania
⊲ Macintosh (1994–2006)
⊲ AS/400, System i, System p
⊲ Blade Center – komputery modułowe
⊲ Superkomputery Blue Gene
⊲ Konsole do gier: PlayStation 3, Nintendo Wii, Xbox 360
⊲ Urządzenia sieciowe
⊲ Systemy wbudowane (ang. embedded)
 .
Obecnie
 .
⊲ Konsorcjum Apple-IBM-Motorola rozpadło się.
⊲ Motorola sprzedała dział mikroprocesorów firmie Freescale.
⊲ Apple montuje w Macintoshach procesory Intela.
⊲ Powstało Power.org: IBM, Freescale Semiconductor, Applied Micro
Circuits Corporation, . . . .
⊲ Jedna z najbardziej popularnych architektur RISC
Jugene
 .
Power ISA (1)
⊲ Power Instruction Set Architecture
⊲ Wersja 2.03
⋄ e200, e500, e700 – Freescale
⋄ PPC 405, 440, 460, 970, POWER5 – IBM
⋄ Cell PPE – IBM
⊲ Wersja 2.05
⋄ POWER6 – IBM
⊲ Wersja 2.06
⋄ POWER7 – IBM
 .
Power ISA (2)
 .
Power ISA (3)
 .
⊲ Book I Power ISA User Instruction Set Architecture
⊲ Book II Power ISA Virtual Enviroment Architecture
⊲ Book III-S Power ISA Operating Environment Architecture – Server
Environment
⊲ Book III-E Power ISA Operating Environment Architecture – Embedded
⊲ Book VLE Power ISA Operating Enviroment Architecture – Variable Length Encoding (VLE) Environment
Kolejność bajtów i bitów
 .
⊲ Procesor uruchamia się w trybie big-endian.
⊲ Większość modeli obsługuje też tryb little-endian.
⊲ Kolejność bajtów określa odpowiedni bit w MSR (machine state register), osobno dla trybu użytkownika i nadzorcy.
⊲ Niektóre wersje procesorów dla systemów wbudowanych posiadają
osobny bit kolejności bajtów dla każdej strony pamięci.
⊲ Bity numerowane są od najbardziej do najmniej znaczącego. MSB
ma numer 0.
Rejestry widziane przez użytkownika (1)
.
⊲ R0-R31 – 64-bitowe rejestry ogólnego przeznaczenia
⋄ R0 w wielu instrukcjach oznacza 0.
⋄ R1 jest często używany jako wskaźnik stosu.
⊲ CR – 32-bitowy rejestr warunków (znaczników, predykatów)
⊲ CTR – 64-bitowy licznik sterujący pętlą lub adres rozgałęzienia warunkowego
⊲ LR – 64-bitowy rejestr powiązania, adres powrotu z procedury
⊲ XER – 32-bitowy rejestr wyjątków operacji stałopozycyjnych, bity
nadmiaru, bit przeniesienia CA, licznik dla operacji łańcuchowych
Rejestry widziane przez użytkownika (2)
.
⊲ FPR0-FPR31 – 64-bitowe rejestry zmiennopozycyjne
⊲ FPSCR – 32-bitowy rejestr stanu i sterowania jednostki zmiennopozycyjnej
⊲ VR0-VR31 – 128-bitowe rejestry wektorowe
⊲ VSCR – 32-bitowy rejestr stanu i sterowania jednostki wektorowej
⊲ VRSAVE – 32-bitowy rejestr opisujący używane przez aplikację rejestry wektorowe
Tryby adresowania (1)
⊲ Instrukcje przesłania z i do pamięci (EA
rej. pośredni z przesunięciem
EA :=
rej. pośr. z preink./predekr.
EA :=
indeksowy
EA :=
indeksowy z preinkrementacją
EA :=
– effective address)
RA + signext(D)
RA := RA + signext(D)
RA + RB
RA := RA + RB
⊲ Instrukcje rozgałęziania (PC – program counter)
bezwzględny
PC := adres
względny
PC := PC + signext(D)
rejestrowy pośredni
PC := LR / PC := CTR
⊲ Operacje stałoprzecinkowe
rejestrowy
natychmiastowy
RA
stała
.
Tryby adresowania (2)
⊲ Operacje zmiennoprzecinkowe
rejestrowy
FPRA
⊲ Operacje wektorowe
rejestrowy
VRA
.
Instrukcje
.
⊲ Bogaty zestaw instrukcji, ale dobrze przemyślany.
⊲ Zbiór instrukcji podzielony na kategorie – poszczególne modele implementują wybrane kategorie.
⊲ 32-bitowe kody instrukcji, wyrównywane do granicy 4 bajtów
⊲ 20 formatów instrukcji
⊲ Dwuetapowe sterowanie rozgałęzieniami programu
⊲ Wiele instrukcji posiada dwie wersje:
⋄ modyfikująca rejestr CR zgodnie z wynikiem operacji – mnemonik
z kropką,
⋄ niemodyfikująca rejestru CR – mnemonik bez kropki.
Instrukcje sterujące rozgałęzieniami (1)
.
⊲ Rozgałęzienia bezwarunkowe
b
addr
; PC := PC + signext(addr * 4)
ba
addr
; PC := signext(addr * 4)
bl
addr
; LR := PC + 4
; PC := PC + signext(addr * 4)
bla
addr
; LR := PC + 4
; PC := signext(addr * 4)
⊲ Rozgałęzienia
strów CR, CRT
bc
BO,
bca
BO,
bcl
BO,
bcla
BO,
warunkowe; pola BO, BI opisują sposób użycia rejeoraz zawierają wskazówkę dla predykcji skoków.
BI, addr
BI, addr
BI, addr
BI, addr
Instrukcje sterujące rozgałęzieniami (2)
.
⊲ Rozgałęzienia warunkowe; pole BH zawiera wskazówkę co do adresu,
pod który następuje skok.
bclr
BO, BI, BH
; PC := LR and 1...100b
bclrl
BO, BI, BH
; tmp := LR and 1...100b
; LR := PC + 4
; PC := tmp
bcctr
BO, BI, BH
; PC := CTR and 1...100b
bcctrl BO, BI, BH
; LR := PC + 4
; PC := CTR and 1...100b
⊲ Nie ma instrukcji wołania i powrotu z procedury. Czy rzeczywiście?
Instrukcje przesłania z pamięci (1)
⊲ Podwójne słowo (64 bity)
ld
RT, D(RA)
ldu
RT, D(RA)
ldx
ldux
RT, RA, RB
RT, RA, RB
⊲ Słowo (32 bity)
lwz
RT, D(RA)
lwzu
RT, D(RA)
lwzx
RT, RA, RB
lwzux
RT, RA, RB
lwa
RT, D(RA)
lwax
RT, RA, RB
lwaux
RT, RA, RB
;
;
;
;
;
;
RT
RA
RT
RT
RA
RT
:=
:=
:=
:=
:=
:=
.
[RA + signext(D)]
RA + signext(D)
[RA]
[RA + RB]
RA + RB
[RA]
; RT := zeroext([RA + signext(D)])
; RT := signext([RA + signext(D)])
Instrukcje przesłania z pamięci (2)
⊲ Półsłowo
lhz
lhzu
lhzx
lhzux
lha
lhau
lhax
lhaux
(16 bitów)
RT, D(RA)
RT, D(RA)
RT, RA, RB
RT, RA, RB
RT, D(RA)
RT, D(RA)
RT, RA, RB
RT, RA, RB
⊲ Bajt (8 bitów)
lbz
RT, D(RA)
lbzu
RT, D(RA)
lbzx
RT, RA, RB
lbzux
RT, RA, RB
.
Instrukcje przesłania z pamięci (3)
⊲ Ze zmianą kolejności bajtów
lhbrx
RT, RA, RB
lwbrx
RT, RA, RB
⊲ Ciąg słów
lmw
RT, D(RA)
lswi
RT, RA, NB
lswx
RT, RA, RB
.
Instrukcje przesłania do pamięci (1)
⊲ Podwójne słowo (64 bity)
std
RS, D(RA)
stdu
RS, D(RA)
stdx
stdux
RS, RA, RB
RS, RA, RB
⊲ Słowo (32 bity)
stw
RS, D(RA)
stwu
RS, D(RA)
stwx
RS, RA, RB
stwux
RS, RA, RB
;
;
;
;
;
;
[RA + signext(D)] := RS
RA := RA + signext(D)
[RA] := RS
[RA + RB] := RS
RA := RA + RB
[RA] := RS
.
Instrukcje przesłania do pamięci (2)
⊲ Półsłowo
sth
sthu
sthx
sthux
(16 bitów)
RS, D(RA)
RS, D(RA)
RS, RA, RB
RS, RA, RB
⊲ Bajt (8 bitów)
stb
RS, D(RA)
stbu
RS, D(RA)
stbx
RS, RA, RB
stbux
RS, RA, RB
.
Instrukcje przesłania do pamięci (3)
⊲ Ze zmianą kolejności bajtów
sthbrx RS, RA, RB
stwbrx RS, RA, RB
⊲ Ciąg słów
stmw
RS, D(RA)
stswi
RS, RA, NB
stswx
RS, RA, RB
⊲ Nie ma instrukcji stosowych. Czy rzeczywiście?
.
Instrukcje stałopozycyjne (1)
.
⊲ Dodawanie; każda z poniższych instrukcji występuje w czterech wariantach (np. add, add., addo, addo.); o oznacza modyfikowanie
bitu nadmiaru w rejestrze XER.
add
RT, RA, RB ; RT := RA + RB
addc
RT, RA, RB ; CA, RT := RA + RB
adde
RT, RA, RB ; CA, RT := RA + RB + CA
addme
RT, RA
; CA, RT := RA + CA - 1
addze
RT, RA
; CA, RT := RA + CA
⊲ Dodawanie (odejmowanie) stałej
addi
RT, RA, SI ; RT := RA + signext(SI)
addis
RT, RA, SI ; RT := RA + signext(SI << 16)
addic
RT, RA, SI ; CA, RT := RA + signext(SI)
addic. RT, RA, SI ; CA, RT := RA + signext(SI)
Instrukcje stałopozycyjne (2)
.
⊲ Mnożenie
mulld
RT, RA, SI
mulhdu RT, RA, SI
mulhd
RT, RA, SI
; RT := (bits 64:127)(RA * RB)
; RT := (bits 0:63)(unsigned RA * RB)
; RT := (bits 0:63)(signed RA * RB)
⊲ Mnożenie przez stałą
mulli
RT, RA, SI
; RT := (bits 64:127)(RA * signext(SI))
Instrukcje stałopozycyjne (3)
⊲ Pozostałe arytmetyczne
subf
RT, RA, RB
subfc
RT, RA, RB
subfe
RT, RA, RB
subfme RT, RA
subfze RT, RA
neg
RT, RA
mullw
RT, RA, RB
mulhwu RT, RA, RB
mulhw
RT, RA, RB
divw
RT, RA, RB
divwu
RT, RA, RB
divd
RT, RA, RB
divdu
RT, RA, RB
;
;
;
;
;
;
RT := neg
CA, RT :=
CA, RT :=
CA, RT :=
CA, RT :=
RT := neg
RA + RB + 1
neg RA + RB + 1
neg RA + RB + CA
neg RA + CA - 1
neg RA + CA
RA + 1
.
Instrukcje stałopozycyjne (4)
.
⊲ Porównanie liczb ze znakiem; BF określa modyfikowane pole rejestru
CR, L określa rozmiar operacji 32 lub 64 bity.
cmpi
BF, L, RA, SI
cmp
BF, L, RA, RB
⊲ Porównanie liczb bez znaku; BF i L jw.
cmpli
BF, L, RA, UI
cmpl
BF, L, RA, RB
⊲ Pułapki
twi
tw
tdi
td
TO,
TO,
TO,
TO,
RA,
RA,
RA,
RA,
SI
RB
SI
RB
Instrukcje stałopozycyjne (5)
⊲ Operacje
andi.
andis.
ori
oris
xori
xoris
and
or
xor
nand
nor
eqv
andc
orc
logiczne
RA, RS,
RA, RS,
RA, RS,
RA, RS,
RA, RS,
RA, RS,
RA, RS,
RA, RS,
RA, RS,
RA, RS,
RA, RS,
RA, RS,
RA, RS,
RA, RS,
UI
UI
UI
UI
UI
UI
RB
RB
RB
RB
RB
RB
RB
RB
;
;
;
;
;
;
;
;
;
;
;
;
;
;
RA
RA
RA
RA
RA
RA
RA
RA
RA
RA
RA
RA
RA
RA
:=
:=
:=
:=
:=
:=
:=
:=
:=
:=
:=
:=
:=
:=
.
RS and zeroext(UI)
RS and zeroext(UI << 16)
RS or zeroext(UI)
RS or zeroext(UI << 16)
RS xor zeroext(UI)
RS xor zeroext(UI << 16)
RS and RB
RS or RB
RS xor RB
not (RS and RB)
not (RS or RB)
not (RS xor RB)
RS and not RB
RS or not RB
Instrukcje stałopozycyjne (6)
.
⊲ Rozszerzanie bitu znaku
extsb
RA, RS
extsh
RA, RS
extsw
RA, RS
⊲ Przesunięcia i obroty
...
⊲ Przesłania między rejestrem specjalnym (XER, LR, CTR, VRSAVE, . . . ),
a rejestrem ogólnego przeznaczenia
...
⊲ Przypisanie warunkowe
isel
RT, RA, RB, BC
; RT := (bit BC + 32)CR ? RA : RB
Instrukcje stałopozycyjne (7)
.
⊲ Liczba wiodących zer w słowie i podwójnym słowie
cntlzw RA, RS
cntlzd RA, RS
⊲ Liczba jedynek w poszczególnych bajtach
pocntb RA, RS
⊲ Nie ma instrukcji przesłania między rejestrami ogólnego przeznaczenia. Dlaczego?
⊲ Nie ma instrukcji bitowej negacji. Dlaczego?
Instrukcje zmiennopozycyjne (1)
⊲ Tradycyjne
fmr
FRT,
fneg
FRT,
fabs
FRT,
fnabs
FRT,
fadd
FRT,
fsub
FRT,
fmul
FRT,
fdiv
FRT,
fsqrt
FRT,
FRB
FRB
FRB
FRB
FRA,
FRA,
FRA,
FRA,
FRB
FRB
FRB
FRB
FRB
;
;
;
;
;
;
;
;
;
FRT
FRT
FRT
FRT
FRT
FRT
FRT
FRT
FRT
:=
:=
:=
:=
:=
:=
:=
:=
:=
.
FRB
-FRB
abs(FRB)
-abs(FRB)
FRA + FRB
FRA - FRB
FRA * FRB
FRA / FRB
sqrt(FRB)
Większość instrukcji zmiennopozycyjnych ma też wersję pojedynczej
precyzji oraz odpowiednie wersje z kropką.
Instrukcje zmiennopozycyjne (2)
⊲ Mnożenie z akumulacją
fmadd
FRT, FRA, FRC,
fmsub
FRT, FRA, FRC,
fnmadd FRT, FRA, FRC,
fnmsub FRT, FRA, FRC,
FRB
FRB
FRB
FRB
⊲ Przypisanie warunkowe
fsel
FRT, FRA, FRC, FRB
;
;
;
;
FRT
FRT
FRT
FRT
:=
:=
:=
:=
(FRA *
(FRA *
-((FRA
-((FRA
FRC) +
FRC) * FRC)
* FRC)
FRB
FRB
+ FRB)
- FRB)
; FRT := FRA >= 0 ? FRC : FRB
⊲ Konwersje z i do formatów stałopozycyjnych
...
⊲ Zaokrąglanie
...
.
Instrukcje zmiennopozycyjne (3)
.
⊲ Szacowanie odwrotności i odwrotności z pierwiastka kwadratowego
...
⊲ Porównywanie
...
⊲ Przesłania z i do pamięci
...
Skrótowe mnemoniki
⊲ Często używane instrukcje
cmpd
Rx, Ry
sub
Rz, Ry, Rx
li
Rx, value
mr
Rx, Ry
nop
not
Rx, Ry
.
cmp
subf
addi
or
ori
nor
0, 1, Rx, Ry
Rz, Rx, Ry
Rx, 0, value
Rx, Ry, Ry
0, 0, 0
Rx, Ry, Ry
bclr
31, 0, 0
⊲ Wołanie procedury
bl
addr
bla
addr
⊲ Powrót z procedury
blr
Małe podsumowanie
.
⊲ Nie jest to zupełnie czysty RISC. Rozwój technologii pozwolił na
rozwiązania, które są niezgodne z pierwotną filozofią RISC.
⊲ Wydaje się, że jest znacznie więcej instrukcji niż np. w x86, który
jest klasycznym CISC, ale tak naprawdę w x86 wiele instrukcji
ukrywa się pod jednakowym mnemonikiem, a w Power każdy tryb
adresowania ma osobny mnemonik.
⊲ Zestaw instrukcji jest dobrany rozsądnie, bez przesadnej nadmiarowości.
AltiVec, Velocity Engine, VMX (1)
.
⊲ Wektorowe operacje arytmetyczne stałopozycyjne
⋄ 16 elementów typu bajt (8 bitów)
⋄ 8 elementów typu półsłowo (16 bitów)
⋄ 4 elementy typu słowo (32 bity)
⋄ typ pixel
⊲ Wektorowe operacje arytmetyczne zmiennopozycyjne
⋄ 4 elementy pojedynczej precyzji
⋄ brak wsparcia dla podwójnej precyzji
⊲ Bardziej kompletny i lepiej zaprojektowany zestaw instrukcji niż np.
konkurencyjne SSE
AltiVec, Velocity Engine, VMX (2)
⊲ Przesłania z i do pamięci
⊲ Pakowanie i rozpakowywanie wektorów
⊲ Scalanie wektorów
⊲ Rozrzucanie elementów wektora
⊲ Permutowanie elementów wektora
⊲ Wybór (selekcja) elementów wektora
⊲ Przesunięcia
⊲ Operacje z nasyceniem
.
Signal Processing Engine (SPE)
.
⊲ Rozszerzenie wspierające operacje cyfrowego przetwarzania sygnałów (DSP – Digital Signal Processing)
⊲ Rejestry ogólnego przeznaczenia
⊲ Wsparcie dla formatu stałopozycyjnego ułamkowego
⊲ Stałopozycyjne operacje wektorowe
⊲ Operacje z nasyceniem
⊲ Operacja pomnóż i sumuj (MAC – multiply and accumulate)
Embedded Floating-Point
⊲ Rozszerzenie SPE o operacje zmiennoprzecinkowe
⊲ Rejestry ogólnego przeznaczenia
⊲ Skalarne operacje pojedynczej i podwójnej precyzji
⊲ Wektorowe operacje pojedynczej precyzji
.
Translacja adresów (1)
.
Effective Address (EA)
Segment Lookaside Buffer (SLB)
Virtual Address (VA)
Hashed Page Table (HTAB) / Translation Lookaside Buffer (TLB)
Real Address (RA)
Przestrzeń adresowa (1)
.
⊲ 64-bitowy adres efektywny. Efektywna przestrzeń adresowa ma 264
bajtów.
⊲ 78-bitowy adres wirtualny. Wirtualna przestrzeń adresowa ma 2n
bajtów, gdzie 65 ¬ n ¬ 78. Najbardziej znaczące 78 − n bity adresu
wirtualnego muszą być wyzerowane.
⊲ 62-bitowy adres rzeczywisty. Rzeczywista przestrzeń adresowa ma
2m bajtów, gdzie m ¬ 62. Najbardziej znaczące 62 − m bity adresu
rzeczywistego muszą być wyzerowane.
⊲ Rozmiar segmentu wynosi 2s bajtów, gdzie s = 28, 40.
⊲ Rozmiar strony wynosi 2p bajtów, gdzie p ­ 12.
Translacja adresów (2)
⊲ EA
.
64 − s
s−p
p
Effective Segment ID (ESID)
Page
Byte
s−p
p
⊲ SLB zamienia ESID na VSID.
78 − s
⊲ VA
Page
Virtual Segment ID (VSID)
|
{z
Virtual Page Number (VPN)
Byte
}
⊲ HTAB/TLB zamienia VPN na RPN.
⊲ RA
62 − p
p
Real Page Number (RPN)
Byte
Przestrzeń adresowa (2)
.
⊲ Po co taka duża wirtualna przestrzeń adresowa?
⊲ Przypomnijmy, że stronicowanie uwalnia nas od problemu fragmentacji pamięci rzeczywistej, ale nie rozwiązuje problemu fragmentacji
pamięci wirtualnej.
⊲ Duża wirtualna przestrzeń adresowa umożliwia nieprzejmowanie się
problemem fragmentacji pamięci wirtualnej.
⊲ Właściwie nie trzeba jej nawet zwalniać.
⊲ Alokując 1 TB (240 bajtów) na sekundę, 278 bajtów wystarczy na
ponad 8 tysięcy lat.
Wywoływanie usług systemu operacyjnego
⊲ Zgłoszenie przerwania programowego
sc
sc
LEV
⊲ Efektywny adres procedury obsługi
0C00h
⊲ Powrót z obsługi przerwania
rfid
hrfid
.
Variable Length Encoding
.
⊲ Alternatywne kodowanie instrukcji
⊲ 16 lub 32 bitowe kody instrukcji, wyrównywane do granicy 2 bajtów
⊲ Zmniejszenie wielkości kodu i przyspieszenie jego wykonywania
⊲ Oszczędności istotne chyba tylko w systemach wbudowanych
⊲ Miejmy nadzieję, że rozwój architektury Power nie pójdzie w tym
kierunku. :-)
PowerXCell 8i
.
⊲ Następca Cell BE – Cell Broadband Engine Architecture
⊲ Pierwotnie wspólny projekt IBM, Toshiba i Sony – konsole do gier
⊲ PPE – Power Processor Element
⋄ 64-bitowy rdzeń Power
⋄ 512 kiB pamięci podręcznej L2
⊲ 8 koprocesorów wektorowych SPE – Synergistic Processor Element
⋄ RISC SIMD
⋄ 128 rejestrów 128 bitowych
⋄ 256 kiB pamięci lokalnej
⊲ Element interconnect bus
PowerXCell 8i
.
⊲ PPE wykonuje wątki sterujące – maksymalnie dwa równolegle.
⊲ SPE wykonują wątki wymagające masywnych obliczeń – każdy SPE
jeden wątek.
⊲ PPE i SPE mają różne zestawy instrukcji.
⊲ Moduły kodu na PPE i SPE są kompilowane oddzielnie.
⊲ PPE i SPE współdzielą architekturę pamięci wirtualnej i jednostkę
translacji adresów.
SPE (1)
.
⊲ Prosta mikroarchitektura
⊲ Tylko instrukcje wektorowe
⊲ Operacje load/store wyrównane do rozmiaru wektora – 16 bajtów
⊲ Preferowany slot dla argumentów skalarnych
⊲ Operacja rotate wspomagająca obliczenia skalarne
⊲ Paczkowanie instrukcji – statyczny przydział instrukcji do potoków
⊲ Dwa krótkie potoki
⊲ Statyczna predykcja skoków
SPE (2)
.
⊲ Przewidywalny czas wykonania kodu
⊲ Szybka pamięć lokalna
⋄ mniejsza powierzchnia niż pamięci podręcznej o tej samej pojemności
⋄ eliminacja skomplikowanej logiki sterowania pamięcią podręczną
⋄ przewidywalne opóźnienia dostępu
⊲ Decyzja programisty kiedy i które dane ściągać do pamięci lokalnej
⊲ Operacje zmiennoprzecinkowe podwójnej precyzji dwukrotnie wolniejsze niż pojedynczej precyzji
Przykład wektoryzacji
.
⊲ Selekcja bez wektoryzacji wymaga zwykle użycia instrukcji skoków.
for (i = 0; i < VL; i++)
if (a[i] > b[i])
m[i] = a[i] * 5;
else
m[i] = b[i] * 3;
⊲ Selekcja zapisana wektorowo eliminuje skoki kosztem liczenia niepotrzebnych wartości.
for (i = 0; i < VL; i++) {
a_tmp[i] = a[i] * 5;
b_tmp[i] = b[i] * 3;
s[i] = a[i] > b[i];
m[i] = s[i] ? a_tmp[i] : b_tmp[i];
}