otázka zní, kdo a do jaké míry SSE a třeba i AVX využije. Třeba Gočko vůbec SIMD neumí, i když Go používá skalární SSE instrukce. Dtto většina interpetrů. A céčko snad jen přes intrinsiky. (Rust netuším, ale tam věřím, že nějak SIMD dokážou utilizovat)
Takže co nám zbývá? Asi Fortran, možná Julia? Nebo specializované knihovny jako Numpy.
Říká se tomu autovektorizace.
Můžete také použít překladač, aby ve vhodných případech tyto instrukce použil. Myslel jsem, že se tu později objeví info o tom, jak třeba psát smyčky v C/C++, aby je překladač rozpoznal a použil na ně SIMD instrukce. Třeba se dočkáme :)
dočkáme :) jak intrinsic (to už se probíralo a je to trošku low level), tak i optimalizace překladači.
FYI rychlý test:
typedef struct vector4d { float v[4]; } vector4d;
void vectorAdd(vector4d *out, vector4d *s1, vector4d *s2)
{
for (int i = 0; i < 4; ++i) {
out->v[i] = s1->v[i] + s2->v[i];
}
}
x86_64:
vectorAdd(vector4d*, vector4d*, vector4d*):
movups xmm0, XMMWORD PTR [rsi]
movups xmm1, XMMWORD PTR [rdx]
addps xmm0, xmm1
movups XMMWORD PTR [rdi], xmm0
ret
aarch64:
vectorAdd(vector4d*, vector4d*, vector4d*):
ldr q31, [x1]
ldr q30, [x2]
fadd v30.4s, v31.4s, v30.4s
str q30, [x0]
ret
A moderní (už dlouho) kompilátory zvládají i maticové násobení docela slušně.
Moc sa nevyznam, som skor z c# sveta, ale tipujem, ze aspon `memcpy` a pod z glibc vyuzivaju tieto instrukcie. Tj, nic svetoborne, asi len vyuzivaju viac bitovost registrov?
Podobne vykonavanie c# - myslim ze kopirovanie casti pamate ale aj vyhladavanie v retazcoch
Blbý dotaz: proč byly vždycky přidávány jednotky registrů a.ne třeba desítky/stovky? Je to náročné na tranzistory? Nebo to podle autorů procesorů není potřeba? Vím že moderní CPU už jsou jinde ale nevím proč to.nebylo v historii?
Protože Intel a CISC :-), RISCy měly ty desítky registrů (typicky 32, ale AMD 29K mělo 128 a Itanium tuším taky 128 v registrových oknech). Ale popravdě, ono to natahuje i instrukční slova a navíc každé přerušení nebo context switch může znamenat nutnost to celé někam odložit (takové ty snahy o PUSHA a POPA) nebo mít možnost odložit registry podle bitového pole (původní ARMy).
U některých RISCů se to snažili vyřešit "oknem" registrů; to se mi osobně dost líbilo, ale nějak to umřelo s tím, jak to všechno válcoval Intel. Ale jak píšeš, dneska už máme registrů spíš víc než míň (jak běžných skalárních, tak i pro AVX).
Tak každý bit každého registru musíte naroutovat a často to máte každý registr s každým. Ono to pak roste exponenciálně. Kdyby to byly jen dráty, ale to je multiplexorů jak máku.
Tak, ono by to tudíž nesměly být jednotlivé univerzální registry. Nevím, co bylo to "okno" zmiňované panem Tišnovským, ale možná podobné mému nápadu: část registrů přístupná jenom nějak podobně jako zásobník plus instrukce "načti celý zásobník naráz z RAM". Pak by to šlo použít podobně jako program v PostScriptu, tj. spustí se výpočet mnoha kroků s minimální režií a bere se až sada výsledků na konci. Navíc, krom už tak výrazně snížené režie, celou dobu toho výpočtu je všechen ostatní HW volný a může jet paralelně, např. chystat v RAM data pro další kolo výpočtu: sběrnice na RAM, CPU... - protože SIMD je celou dobu výpočtu soběstačný (má kód, data i úložný prostor pro výsledky).
Ono je to trošku podobné. Popsáno je to ve třetí kapitole v https://www.root.cz/clanky/procesory-risc-v-pracovnich-stanicich-a-serverech-architektura-sparc-v8-a-v9/#k03 (doskoky na kapitoly u starších článků přestaly fungovat, tak je nutné doskrolovat).
Dostupných je například 32 registrů z 256 (to je +- to samé, co máme dneska k dispozici). Při volání subrutiny se okno nad všemi registry posune, řekněme tak, že 8 registrů už nebude dostupných (tam si původní kód nechává hodnoty, které chceme zachovat) a dalších 16 registrů bude vidět i subrutina (s jinými indexy). Tak je možné předávat argumenty a návratové hodnoty. A posledních 8 registrů je zcela "nových", tam si subrutina dává lokální proměnné. A při RETURN se to okno zase vrátí zpátky.
program přeložený s podporou SSE nebude na procesoru bez této technologie pracovat korektně, i když by pravděpodobně bylo možné SSE emulovat s využitím podprogramů spouštěných při zavolání neplatného operačního kódu (tj. operačního kódu SSE instrukce, která je samozřejmě pro ne-SSE procesor neznámým kódem).
Když jsem se snažil (úspěšně) rozběhat Furmark na 486, tak jsem narazil na informaci, že některé generace CPU některé neznámé SSE instrukce ignorují.