Hlavní navigace

Rozšíření instrukční sady AVX-512 na platformě x86–64 (dokončení)

29. 11. 2022
Doba čtení: 65 minut

Sdílet

 Autor: Depositphotos
V závěrečném článku o SIMD operacích podporovaných (i když nepřímo) překladačem GCC C se zaměříme přímo na konkrétní vybrané instrukce, které lze nalézt v jednotlivých rozšířeních instrukčních sad AVX-512.

Obsah

1. Rozšíření instrukční sady AVX-512 na platformě x86–64 (dokončení)

2. Datové typy používané v GCC s podporou AVX-512

3. Intrinsic definované v GCC pro instrukční sady AVX-512

4. Základ AVX-512: AVX-512F (foundation)

5. Maskovací registry k0k7

6. Operace prováděné přímo s maskovacími registry

7. Intrinsic pro operace prováděné přímo s maskovacími registry

8. Instrukce, v nichž se využívají nové maskovací registry

9. Instrinsic pro instrukce vblendmps a addps s maskou

10. Komprese a expanze dat

11. Instrukce pro kompresi a expanzi dat

12. Instrinsic pro instrukce komprese dat

13. Instrukce pro provedení permutace (přerozdělení) prvků vektorů

14. Intrinsic pro provedení permutace

15. Rozšíření AVX-512BW

16. Rozšíření Vector Neural Network Instructions (VNNI)

17. Příloha – soubor Makefile použitý v článcích o SIMD operacích

18. Repositář s demonstračními příklady

19. Seznam všech předchozích částí tohoto seriálu

20. Odkazy na Internetu

1. Rozšíření instrukční sady AVX-512 na platformě x86–64 (dokončení)

Na předchozí článek s úvodními informacemi o AVX-512 na platformě x86–64 dnes navážeme. Víme již, že sada AVX-512 by přinesla do návrhu a výroby čipů tak rozsáhlou změnu, že je celá nová sada instrukcí rozdělena do několika podmnožin, přičemž zdaleka na všechny mikroprocesory musí podporovat všechny podmnožiny. To má zajímavý důsledek – počet (teoretických) možných kombinací podporuje/nepodporuje je obrovský. Podívejme se na názvy jednotlivých podmnožin společně s informacemi o tom, ve kterém jádru byla daná podmnožina AVX-512 poprvé implementována:

Množina instrukcí Plné jméno První procesor s implementací
F AVX-512 Foundation Xeon Phi x200 (Knights Landing), Xeon Gold/Platinum
CD AVX-512 Conflict Detection Instructions Xeon Phi x200 (Knights Landing), Xeon Gold/Platinum
ER AVX-512 Exponential and Reciprocal Instructions Xeon Phi x200 (Knights Landing)
PF AVX-512 Prefetch Instructions Xeon Phi x200 (Knights Landing)
     
VL AVX-512 Vector Length Extensions Skylake X, Cannon Lake
DQ AVX-512 Doubleword and Quadword Instructions Skylake X, Cannon Lake
BW AVX-512 Byte and Word Instructions Skylake X, Cannon Lake
     
IFMA AVX-512 Integer Fused Multiply Add Cannon Lake
VBMI AVX-512 Vector Byte Manipulation Instructions Cannon Lake
     
4VNNIW AVX-512 Vector Neural Network Instructions Word variable precision Knights Mill
4FMAPS AVX-512 Fused Multiply Accumulation Packed Single precision Knights Mill
     
VPOPCNTDQ Vector population count instruction Knights Mill, Ice Lake
     
VNNI AVX-512 Vector Neural Network Instructions Ice Lake
VBMI2 AVX-512 Vector Byte Manipulation Instructions 2 Ice Lake
BITALG AVX-512 Bit Algorithms Ice Lake
     
VP2INTERSECT AVX-512 Vector Pair Intersection to a Pair of Mask Registers Tiger Lake

Z pohledu programátora je nejdůležitější hned první podmnožina nazvaná AVX-512 Foundation, což je zkracováno na AVX-512F. Značná část dnešního článku je věnována právě této podmnožině, protože ta přináší dvě důležité změny: rozšíření počtu i bitové šířky vektorových registrů ZMMx a taktéž zavedení maskovacích registrů k0k7, které lze využít v mnoha nových instrukcích. Taktéž bylo změněno kódování instrukcí, to je však již pro běžného programátora (většinou) poměrně nepodstatná informace.

2. Datové typy používané v GCC s podporou AVX-512

Vzhledem k tomu, že si dnes ukážeme i několik demonstračních příkladů založených na intrinsic nabízených překladačem GCC C, je nutné znát i datové typy, s nimiž se bude pracovat. Jedná se o vektory s šířkou 512 bitů (64 bajtů), které obsahují buď celočíselné prvky (pochopitelně volitelné šířky) nebo prvky s hodnotami reprezentovanými v systému plovoucí řádové čárky. V mnoha demonstračních příkladech konkrétně použijeme typ __v16sf, tedy vektor se šestnácti prvky typu single/float:

# Typ prvku Počet prvků Celkový počet bitů Definice datového typu
1 double 8 512 typedef double __v8df __attribute__ ((__vector_size__ (64)));
2 float 16 512 typedef float __v16sf __attribute__ ((__vector_size__ (64)));
3 long long 8 512 typedef long long __v8di __attribute__ ((__vector_size__ (64)));
4 unsigned long long 8 512 typedef unsigned long long __v8du __attribute__ ((__vector_size__ (64)));
5 int 16 512 typedef int __v16si __attribute__ ((__vector_size__ (64)));
6 unsigned int 16 512 typedef unsigned int __v16su __attribute__ ((__vector_size__ (64)));
7 short 32 512 typedef short __v32hi __attribute__ ((__vector_size__ (64)));
8 unsigned short 32 512 typedef unsigned short __v32hu __attribute__ ((__vector_size__ (64)));
9 char 64 512 typedef char __v64qi __attribute__ ((__vector_size__ (64)));
10 unsigned char 64 512 typedef unsigned char __v64qu __attribute__ ((__vector_size__ (64)));

Dále se ještě poměrně často setkáme s následujícími aliasy:

typedef long long __m512i __attribute__ ((__vector_size__ (64), __may_alias__));
typedef float __m512 __attribute__ ((__vector_size__ (64), __may_alias__));
typedef double __m512d __attribute__ ((__vector_size__ (64), __may_alias__));

3. Intrinsic definované v GCC pro instrukční sady AVX-512

Víme již, že překladač GCC C podporuje přes intrinsic (vestavěné pseudofunkce) všechna dříve popsaná rozšíření instrukční sady x86(-64) se SIMD operacemi. Jedná se o intrinsic pro MMX, SSE, SSE2 i AVX (a vlastně i 3DNow!, které jsme vynechali, protože bylo záhy nahrazeno za SSE). To stejné platí i pro AVX-512; konkrétně jsou nabízeny intrinsic vypsané pod tímto odstavcem (pozor na to, že tato jména nejsou zcela kompatibilní s překladačem firmy Intel!). Taktéž si povšimněte toho, že mnoho instrinsic má v názvu slovo mask, což znamená, že se používají maskovací registry:

__builtin_ia32_addpd512_mask
__builtin_ia32_addps512_mask
__builtin_ia32_addsd_mask_round
__builtin_ia32_addsd_round
__builtin_ia32_addss_mask_round
__builtin_ia32_addss_round
__builtin_ia32_alignd512_mask
__builtin_ia32_alignq512_mask
__builtin_ia32_blendmd_512_mask
__builtin_ia32_blendmpd_512_mask
__builtin_ia32_blendmps_512_mask
__builtin_ia32_blendmq_512_mask
__builtin_ia32_broadcastf32x4_512
__builtin_ia32_broadcastf64x4_512
__builtin_ia32_broadcasti32x4_512
__builtin_ia32_broadcasti64x4_512
__builtin_ia32_broadcastsd512
__builtin_ia32_broadcastss512
__builtin_ia32_cmpd512_mask
__builtin_ia32_cmppd512_mask
__builtin_ia32_cmpps512_mask
__builtin_ia32_cmpq512_mask
__builtin_ia32_cmpsd_mask
__builtin_ia32_cmpss_mask
__builtin_ia32_compressdf512_mask
__builtin_ia32_compressdi512_mask
__builtin_ia32_compresssf512_mask
__builtin_ia32_compresssi512_mask
__builtin_ia32_compressstoredf512_mask
__builtin_ia32_compressstoredi512_mask
__builtin_ia32_compressstoresf512_mask
__builtin_ia32_compressstoresi512_mask
__builtin_ia32_cvtdq2pd512_mask
__builtin_ia32_cvtdq2ps512_mask
__builtin_ia32_cvtpd2dq512_mask
__builtin_ia32_cvtpd2ps512_mask
__builtin_ia32_cvtpd2udq512_mask
__builtin_ia32_cvtps2dq512_mask
__builtin_ia32_cvtps2pd512_mask
__builtin_ia32_cvtps2udq512_mask
__builtin_ia32_cvtsd2ss_round
__builtin_ia32_cvtsi2sd64
__builtin_ia32_cvtsi2ss32
__builtin_ia32_cvtsi2ss64
__builtin_ia32_cvtss2sd_round
__builtin_ia32_cvttpd2dq512_mask
__builtin_ia32_cvttpd2udq512_mask
__builtin_ia32_cvttps2dq512_mask
__builtin_ia32_cvttps2udq512_mask
__builtin_ia32_cvtudq2pd512_mask
__builtin_ia32_cvtudq2ps512_mask
__builtin_ia32_cvtusi2sd32
__builtin_ia32_cvtusi2sd64
__builtin_ia32_cvtusi2ss32
__builtin_ia32_cvtusi2ss64
__builtin_ia32_divpd512_mask
__builtin_ia32_divps512_mask
__builtin_ia32_divsd_mask_round
__builtin_ia32_divsd_round
__builtin_ia32_divss_mask_round
__builtin_ia32_divss_round
__builtin_ia32_expanddf512_mask
__builtin_ia32_expanddf512_maskz
__builtin_ia32_expanddi512_mask
__builtin_ia32_expanddi512_maskz
__builtin_ia32_expandloaddf512_mask
__builtin_ia32_expandloaddf512_maskz
__builtin_ia32_expandloaddi512_mask
__builtin_ia32_expandloaddi512_maskz
__builtin_ia32_expandloadsf512_mask
__builtin_ia32_expandloadsf512_maskz
__builtin_ia32_expandloadsi512_mask
__builtin_ia32_expandloadsi512_maskz
__builtin_ia32_expandsf512_mask
__builtin_ia32_expandsf512_maskz
__builtin_ia32_expandsi512_mask
__builtin_ia32_expandsi512_maskz
__builtin_ia32_extractf32x4_mask
__builtin_ia32_extractf64x4_mask
__builtin_ia32_extracti32x4_mask
__builtin_ia32_extracti64x4_mask
__builtin_ia32_fixupimmpd512_mask
__builtin_ia32_fixupimmpd512_maskz
__builtin_ia32_fixupimmps512_mask
__builtin_ia32_fixupimmps512_maskz
__builtin_ia32_fixupimmsd_mask
__builtin_ia32_fixupimmsd_maskz
__builtin_ia32_fixupimmss_mask
__builtin_ia32_fixupimmss_maskz
__builtin_ia32_gatherdiv16sf
__builtin_ia32_gatherdiv16si
__builtin_ia32_gatherdiv8df
__builtin_ia32_gatherdiv8di
__builtin_ia32_gathersiv16sf
__builtin_ia32_gathersiv16si
__builtin_ia32_gathersiv8df
__builtin_ia32_gathersiv8di
__builtin_ia32_getexppd512_mask
__builtin_ia32_getexpps512_mask
__builtin_ia32_getexpsd128_round
__builtin_ia32_getexpsd_mask_round
__builtin_ia32_getexpss128_round
__builtin_ia32_getexpss_mask_round
__builtin_ia32_getmantpd512_mask
__builtin_ia32_getmantps512_mask
__builtin_ia32_getmantsd_mask_round
__builtin_ia32_getmantsd_round
__builtin_ia32_getmantss_mask_round
__builtin_ia32_getmantss_round
__builtin_ia32_insertf32x4_mask
__builtin_ia32_insertf64x4_mask
__builtin_ia32_inserti32x4_mask
__builtin_ia32_inserti64x4_mask
__builtin_ia32_kandhi
__builtin_ia32_kandnhi
__builtin_ia32_kmovw
__builtin_ia32_knothi
__builtin_ia32_korhi
__builtin_ia32_kortestchi
__builtin_ia32_kortestzhi
__builtin_ia32_kshiftlihi
__builtin_ia32_kshiftrihi
__builtin_ia32_kunpckhi
__builtin_ia32_kxnorhi
__builtin_ia32_kxorhi
__builtin_ia32_loadapd512_mask
__builtin_ia32_loadaps512_mask
__builtin_ia32_loaddqudi512_mask
__builtin_ia32_loaddqusi512_mask
__builtin_ia32_loadsd_mask
__builtin_ia32_loadss_mask
__builtin_ia32_loadupd512_mask
__builtin_ia32_loadups512_mask
__builtin_ia32_maxpd512_mask
__builtin_ia32_maxps512_mask
__builtin_ia32_maxsd_mask_round
__builtin_ia32_maxsd_round
__builtin_ia32_maxss_mask_round
__builtin_ia32_maxss_round
__builtin_ia32_minpd512_mask
__builtin_ia32_minps512_mask
__builtin_ia32_minsd_mask_round
__builtin_ia32_minsd_round
__builtin_ia32_minss_mask_round
__builtin_ia32_minss_round
__builtin_ia32_movapd512_mask
__builtin_ia32_movaps512_mask
__builtin_ia32_movddup512_mask
__builtin_ia32_movdqa32_512_mask
__builtin_ia32_movdqa32load512_mask
__builtin_ia32_movdqa32store512_mask
__builtin_ia32_movdqa64_512_mask
__builtin_ia32_movdqa64load512_mask
__builtin_ia32_movdqa64store512_mask
__builtin_ia32_movesd_mask
__builtin_ia32_movess_mask
__builtin_ia32_movntdq512
__builtin_ia32_movntdqa512
__builtin_ia32_movntpd512
__builtin_ia32_movntps512
__builtin_ia32_movshdup512_mask
__builtin_ia32_movsldup512_mask
__builtin_ia32_mulpd512_mask
__builtin_ia32_mulps512_mask
__builtin_ia32_mulsd_mask_round
__builtin_ia32_mulsd_round
__builtin_ia32_mulss_mask_round
__builtin_ia32_mulss_round
__builtin_ia32_pabsd512_mask
__builtin_ia32_pabsq512_mask
__builtin_ia32_paddd512_mask
__builtin_ia32_paddq512_mask
__builtin_ia32_pandd512_mask
__builtin_ia32_pandnd512_mask
__builtin_ia32_pandnq512_mask
__builtin_ia32_pandq512_mask
__builtin_ia32_pbroadcastd512
__builtin_ia32_pbroadcastd512_gpr_mask
__builtin_ia32_pbroadcastq512
__builtin_ia32_pbroadcastq512_gpr_mask
__builtin_ia32_pcmpeqd512_mask
__builtin_ia32_pcmpeqq512_mask
__builtin_ia32_pcmpgtd512_mask
__builtin_ia32_pcmpgtq512_mask
__builtin_ia32_pd512_256pd
__builtin_ia32_pd512_pd
__builtin_ia32_permdf512_mask
__builtin_ia32_permdi512_mask
__builtin_ia32_permvardf512_mask
__builtin_ia32_permvardi512_mask
__builtin_ia32_permvarsf512_mask
__builtin_ia32_permvarsi512_mask
__builtin_ia32_pmaxsd512_mask
__builtin_ia32_pmaxsq512_mask
__builtin_ia32_pmaxud512_mask
__builtin_ia32_pmaxuq512_mask
__builtin_ia32_pminsd512_mask
__builtin_ia32_pminsq512_mask
__builtin_ia32_pminud512_mask
__builtin_ia32_pminuq512_mask
__builtin_ia32_pmovdb512_mask
__builtin_ia32_pmovdb512mem_mask
__builtin_ia32_pmovdw512_mask
__builtin_ia32_pmovdw512mem_mask
__builtin_ia32_pmovqb512_mask
__builtin_ia32_pmovqb512mem_mask
__builtin_ia32_pmovqd512_mask
__builtin_ia32_pmovqd512mem_mask
__builtin_ia32_pmovqw512_mask
__builtin_ia32_pmovqw512mem_mask
__builtin_ia32_pmovsdb512_mask
__builtin_ia32_pmovsdb512mem_mask
__builtin_ia32_pmovsdw512_mask
__builtin_ia32_pmovsdw512mem_mask
__builtin_ia32_pmovsqb512_mask
__builtin_ia32_pmovsqb512mem_mask
__builtin_ia32_pmovsqd512_mask
__builtin_ia32_pmovsqd512mem_mask
__builtin_ia32_pmovsqw512_mask
__builtin_ia32_pmovsqw512mem_mask
__builtin_ia32_pmovsxbd512_mask
__builtin_ia32_pmovsxbq512_mask
__builtin_ia32_pmovsxdq512_mask
__builtin_ia32_pmovsxwd512_mask
__builtin_ia32_pmovsxwq512_mask
__builtin_ia32_pmovusdb512_mask
__builtin_ia32_pmovusdb512mem_mask
__builtin_ia32_pmovusdw512_mask
__builtin_ia32_pmovusdw512mem_mask
__builtin_ia32_pmovusqb512_mask
__builtin_ia32_pmovusqb512mem_mask
__builtin_ia32_pmovusqd512_mask
__builtin_ia32_pmovusqd512mem_mask
__builtin_ia32_pmovusqw512_mask
__builtin_ia32_pmovusqw512mem_mask
__builtin_ia32_pmovzxbd512_mask
__builtin_ia32_pmovzxbq512_mask
__builtin_ia32_pmovzxdq512_mask
__builtin_ia32_pmovzxwd512_mask
__builtin_ia32_pmovzxwq512_mask
__builtin_ia32_pmuldq512_mask
__builtin_ia32_pmulld512_mask
__builtin_ia32_pmuludq512_mask
__builtin_ia32_pord512_mask
__builtin_ia32_porq512_mask
__builtin_ia32_prold512_mask
__builtin_ia32_prolq512_mask
__builtin_ia32_prolvd512_mask
__builtin_ia32_prolvq512_mask
__builtin_ia32_prord512_mask
__builtin_ia32_prorq512_mask
__builtin_ia32_prorvd512_mask
__builtin_ia32_prorvq512_mask
__builtin_ia32_ps512_256ps
__builtin_ia32_ps512_ps
__builtin_ia32_pshufd512_mask
__builtin_ia32_pslld512_mask
__builtin_ia32_pslldi512_mask
__builtin_ia32_psllq512_mask
__builtin_ia32_psllqi512_mask
__builtin_ia32_psllv16si_mask
__builtin_ia32_psllv8di_mask
__builtin_ia32_psrad512_mask
__builtin_ia32_psradi512_mask
__builtin_ia32_psraq512_mask
__builtin_ia32_psraqi512_mask
__builtin_ia32_psrav16si_mask
__builtin_ia32_psrav8di_mask
__builtin_ia32_psrld512_mask
__builtin_ia32_psrldi512_mask
__builtin_ia32_psrlq512_mask
__builtin_ia32_psrlqi512_mask
__builtin_ia32_psrlv16si_mask
__builtin_ia32_psrlv8di_mask
__builtin_ia32_psubd512_mask
__builtin_ia32_psubq512_mask
__builtin_ia32_pternlogd512_mask
__builtin_ia32_pternlogd512_maskz
__builtin_ia32_pternlogq512_mask
__builtin_ia32_pternlogq512_maskz
__builtin_ia32_ptestmd512
__builtin_ia32_ptestmq512
__builtin_ia32_ptestnmd512
__builtin_ia32_ptestnmq512
__builtin_ia32_punpckhdq512_mask
__builtin_ia32_punpckhqdq512_mask
__builtin_ia32_punpckldq512_mask
__builtin_ia32_punpcklqdq512_mask
__builtin_ia32_pxord512_mask
__builtin_ia32_pxorq512_mask
__builtin_ia32_rcp14pd512_mask
__builtin_ia32_rcp14ps512_mask
__builtin_ia32_rcp14sd
__builtin_ia32_rcp14sd_mask
__builtin_ia32_rcp14ss
__builtin_ia32_rcp14ss_mask
__builtin_ia32_rndscalepd_mask
__builtin_ia32_rndscaleps_mask
__builtin_ia32_rndscalesd_round
__builtin_ia32_rndscaless_round
__builtin_ia32_rsqrt14pd512_mask
__builtin_ia32_rsqrt14ps512_mask
__builtin_ia32_rsqrt14sd
__builtin_ia32_rsqrt14sd_mask
__builtin_ia32_rsqrt14ss
__builtin_ia32_rsqrt14ss_mask
__builtin_ia32_scalefpd512_mask
__builtin_ia32_scalefps512_mask
__builtin_ia32_scalefsd_mask_round
__builtin_ia32_scalefss_mask_round
__builtin_ia32_scatterdiv16sf
__builtin_ia32_scatterdiv16si
__builtin_ia32_scatterdiv8df
__builtin_ia32_scatterdiv8di
__builtin_ia32_scattersiv16sf
__builtin_ia32_scattersiv16si
__builtin_ia32_scattersiv8df
__builtin_ia32_scattersiv8di
__builtin_ia32_shuf_f32x4_mask
__builtin_ia32_shuf_f64x2_mask
__builtin_ia32_shuf_i32x4_mask
__builtin_ia32_shuf_i64x2_mask
__builtin_ia32_shufpd512_mask
__builtin_ia32_shufps512_mask
__builtin_ia32_si512_256si
__builtin_ia32_si512_si
__builtin_ia32_sqrtpd512_mask
__builtin_ia32_sqrtps512_mask
__builtin_ia32_sqrtsd_mask_round
__builtin_ia32_sqrtss_mask_round
__builtin_ia32_storeapd512_mask
__builtin_ia32_storeaps512_mask
__builtin_ia32_storedqudi512_mask
__builtin_ia32_storedqusi512_mask
__builtin_ia32_storesd_mask
__builtin_ia32_storess_mask
__builtin_ia32_storeupd512_mask
__builtin_ia32_storeups512_mask
__builtin_ia32_subpd512_mask
__builtin_ia32_subps512_mask
__builtin_ia32_subsd_mask_round
__builtin_ia32_subsd_round
__builtin_ia32_subss_mask_round
__builtin_ia32_subss_round
__builtin_ia32_ucmpd512_mask
__builtin_ia32_ucmpq512_mask
__builtin_ia32_unpckhpd512_mask
__builtin_ia32_unpckhps512_mask
__builtin_ia32_unpcklpd512_mask
__builtin_ia32_unpcklps512_mask
__builtin_ia32_vcomisd
__builtin_ia32_vcomiss
__builtin_ia32_vcvtph2ps512_mask
__builtin_ia32_vcvtps2ph512_mask
__builtin_ia32_vcvtsd2si32
__builtin_ia32_vcvtsd2si64
__builtin_ia32_vcvtsd2usi32
__builtin_ia32_vcvtsd2usi64
__builtin_ia32_vcvtss2si32
__builtin_ia32_vcvtss2si64
__builtin_ia32_vcvtss2usi32
__builtin_ia32_vcvtss2usi64
__builtin_ia32_vcvttsd2si32
__builtin_ia32_vcvttsd2si64
__builtin_ia32_vcvttsd2usi32
__builtin_ia32_vcvttsd2usi64
__builtin_ia32_vcvttss2si32
__builtin_ia32_vcvttss2si64
__builtin_ia32_vcvttss2usi32
__builtin_ia32_vcvttss2usi64
__builtin_ia32_vfmaddpd512_mask
__builtin_ia32_vfmaddpd512_mask3
__builtin_ia32_vfmaddpd512_maskz
__builtin_ia32_vfmaddps512_mask
__builtin_ia32_vfmaddps512_mask3
__builtin_ia32_vfmaddps512_maskz
__builtin_ia32_vfmaddsd3_mask
__builtin_ia32_vfmaddsd3_mask3
__builtin_ia32_vfmaddsd3_maskz
__builtin_ia32_vfmaddsd3_round
__builtin_ia32_vfmaddss3_mask
__builtin_ia32_vfmaddss3_mask3
__builtin_ia32_vfmaddss3_maskz
__builtin_ia32_vfmaddss3_round
__builtin_ia32_vfmaddsubpd512_mask
__builtin_ia32_vfmaddsubpd512_mask3
__builtin_ia32_vfmaddsubpd512_maskz
__builtin_ia32_vfmaddsubps512_mask
__builtin_ia32_vfmaddsubps512_mask3
__builtin_ia32_vfmaddsubps512_maskz
__builtin_ia32_vfmsubaddpd512_mask3
__builtin_ia32_vfmsubaddps512_mask3
__builtin_ia32_vfmsubpd512_mask
__builtin_ia32_vfmsubpd512_mask3
__builtin_ia32_vfmsubpd512_maskz
__builtin_ia32_vfmsubps512_mask
__builtin_ia32_vfmsubps512_mask3
__builtin_ia32_vfmsubps512_maskz
__builtin_ia32_vfmsubsd3_mask3
__builtin_ia32_vfmsubss3_mask3
__builtin_ia32_vfnmaddpd512_mask
__builtin_ia32_vfnmaddpd512_mask3
__builtin_ia32_vfnmaddpd512_maskz
__builtin_ia32_vfnmaddps512_mask
__builtin_ia32_vfnmaddps512_mask3
__builtin_ia32_vfnmaddps512_maskz
__builtin_ia32_vfnmsubpd512_mask
__builtin_ia32_vfnmsubpd512_mask3
__builtin_ia32_vfnmsubpd512_maskz
__builtin_ia32_vfnmsubps512_mask
__builtin_ia32_vfnmsubps512_mask3
__builtin_ia32_vfnmsubps512_maskz
__builtin_ia32_vpermi2vard512_mask
__builtin_ia32_vpermi2varpd512_mask
__builtin_ia32_vpermi2varps512_mask
__builtin_ia32_vpermi2varq512_mask
__builtin_ia32_vpermilpd512_mask
__builtin_ia32_vpermilps512_mask
__builtin_ia32_vpermilvarpd512_mask
__builtin_ia32_vpermilvarps512_mask
__builtin_ia32_vpermt2vard512_mask
__builtin_ia32_vpermt2vard512_maskz
__builtin_ia32_vpermt2varpd512_mask
__builtin_ia32_vpermt2varpd512_maskz
__builtin_ia32_vpermt2varps512_mask
__builtin_ia32_vpermt2varps512_maskz
__builtin_ia32_vpermt2varq512_mask
__builtin_ia32_vpermt2varq512_maskz

4. Základ AVX-512: AVX-512F (foundation)

Všechny mikroprocesory, které podporují nějaké podmnožiny AVX-512 musí v každém případě podporovat minimálně podmnožinu označovanou AVX-512F, kde F je odvozeno od slova foundation. Jedná se o základní sadu, která rozšiřuje většinu instrukcí z původního AVX takovým způsobem, že se namísto vektorů o délce 256 bitů pracuje s vektory o délce 512 bitů. Taktéž se změnila, resp. rozšířila sémantika mnohých instrukcí díky zavedení maskovacích registrů k0k7, z nichž každý má v AVX-512F šířku šestnácti bitů. Významem těchto registrů se budeme zabývat v páté kapitole i v kapitolách navazujících. A nesmíme zapomenout na to, že se (opět!, pokolikáté už?) změnilo kódování instrukcí. Nové kódování se jmenuje EVEX, což je zkratka z označení Enhanced Vector Extension. Díky EVEX je možné pracovat s 32 SIMD registry, specifikovat již zmíněné maskovací registry, provádět takzvaný broadcasting atd.

5. Maskovací registry k0k7

Novinkou v AVX-512F jsou maskovací registry k0k7. Jedná se o šestnáctibitové registry, teprve později (konkrétně v AVX-512BW) došlo k jejich rozšíření na 64 bitů. Jednotlivé bity v těchto registrech slouží jako maska, například pro operace součtu, nebo tyto bity slouží k rozhodování, zda bude operace provedena s prvkem prvního vstupního vektoru nebo naopak s prvkem získaným z vektoru druhého. Původně mnohdy čistě vektorové operace prováděné se všemi prvky vektorů se tak „rozpadají“ na podmíněné operace, přičemž podmínky jsou zakódovány do bitů zvoleného maskovacího registru. Maskovací registry ovšem mohou sloužit naopak i pro uložení výsledků nějakých operací – například porovnání prvků ze dvou vstupních registrů atd. A konečně, vzhledem k tomu, že se jedná o šestnáctibitové hodnoty, lze s maskovacími registry provádět některé bitové operace, bitové posuny atd.

Poznámka: snadno zjistíme, že 16bitové maskovací registry mohou sloužit pro operace s vektory s prvky typu double, single/float, int32 a int64, ovšem nikoli pro int16 či byte/char.

6. Operace prováděné přímo s maskovacími registry

V případě, že se zaměříme „pouze“ na rozšíření AVX-512F, lze říci, že všechny maskovací registry obsahují šestnáctibitové hodnoty (masky), které lze využít v instrukcích popsaných v navazující kapitole. V instrukční sadě nalezneme i několik instrukcí, které se používají přímo pro manipulaci s obsahem maskovacích registrů, a to prakticky stejně, jakoby se jednalo o běžné šestnáctibitové celočíselné registry. Jedná se o tyto operace:

provedení bitové operace OR se dvěma maskovacími registry
# Instrukce Stručný popis instrukce
1 KMOV načtení konstanty do maskovacího registru nebo převod hodnot mezi dvojicí registrů
     
2 KNOT negace obsahu zvoleného maskovacího registru
3 KAND provedení bitové operace AND se dvěma maskovacími registry
4 KANDN provedení bitové operace AND NOT se dvěma maskovacími registry
5 KOR
6 KXOR provedení bitové operace XOR se dvěma maskovacími registry
7 KXNOR provedení bitové operace XNOR se dvěma maskovacími registry
     
8 KORTEST operace OR s nastavením příznaků Zero (všechny bity nulové) a Carry (všechny bity výsledku jedničkové)
     
9 KSHIFTL bitový posun doleva o n bitů
10 KSHIFTR bitový posun doprava o n bitů
     
11 KUNPCK kombinace spodní poloviny dvou maskovacích registrů do registru cílového

7. Intrinsic pro operace prováděné přímo s maskovacími registry

Vyzkoušejme si nyní ty intrinsic, které lze v GCC použít pro instrukce popsané v rámci předchozí kapitoly. Provedeme několik bitových operací s maskovacími registry:

#include <stdio.h>
#include <immintrin.h>
 
int main(void)
{
    short unsigned int x = 2;
    short unsigned int y = 3;
    short unsigned int z;
 
    z = __builtin_ia32_kandhi(x, y);
    printf("and: %d\n", z);
 
    z = __builtin_ia32_kandnhi(x, y);
    printf("and not: %d\n", z);
 
    z = __builtin_ia32_korhi(x, y);
    printf("or: %d\n", z);
 
    z = __builtin_ia32_kxorhi(x, y);
    printf("xor: %d\n", z);
 
    z = __builtin_ia32_kxnorhi(x, y);
    printf("xnor: %d\n", z);
 
    return 0;
}

Po překladu (s přepínačem -mavx512f) a spuštění by se měla vypsat tato pětice řádků:

and: 2
and not: 1
or: 3
xor: 1
xnor: 65534

Z objektového kódu a disassemblovaného výstupu je patrné, že nové instrukce pro manipulaci s maskovacími registry jsou zakódovány do pouhých čtyř bajtů, což je na platformě x86–64 skoro zázrak:

    z = __builtin_ia32_kandhi(x, y);
  18:   0f b7 45 fc             movzx  eax,WORD PTR [rbp-0x4]
  1c:   0f b7 55 fa             movzx  edx,WORD PTR [rbp-0x6]
  20:   c5 f8 92 ca             kmovw  k1,edx
  24:   c5 f8 92 d0             kmovw  k2,eax
  28:   c5 f4 41 c2             kandw  k0,k1,k2
  2c:   c5 f8 91 45 fe          kmovw  WORD PTR [rbp-0x2],k0
 
    z = __builtin_ia32_kandnhi(x, y);
  48:   0f b7 45 fc             movzx  eax,WORD PTR [rbp-0x4]
  4c:   0f b7 55 fa             movzx  edx,WORD PTR [rbp-0x6]
  50:   c5 f8 92 da             kmovw  k3,edx
  54:   c5 f8 92 e0             kmovw  k4,eax
  58:   c5 e4 42 c4             kandnw k0,k3,k4
  5c:   c5 f8 91 45 fe          kmovw  WORD PTR [rbp-0x2],k0
 
    z = __builtin_ia32_korhi(x, y);
  78:   0f b7 45 fc             movzx  eax,WORD PTR [rbp-0x4]
  7c:   0f b7 55 fa             movzx  edx,WORD PTR [rbp-0x6]
  80:   c5 f8 92 ea             kmovw  k5,edx
  84:   c5 f8 92 f0             kmovw  k6,eax
  88:   c5 d4 45 c6             korw   k0,k5,k6
  8c:   c5 f8 91 45 fe          kmovw  WORD PTR [rbp-0x2],k0
 
    z = __builtin_ia32_kxorhi(x, y);
  a8:   0f b7 45 fc             movzx  eax,WORD PTR [rbp-0x4]
  ac:   0f b7 55 fa             movzx  edx,WORD PTR [rbp-0x6]
  b0:   c5 f8 92 fa             kmovw  k7,edx
  b4:   c5 f8 92 c8             kmovw  k1,eax
  b8:   c5 c4 47 c1             kxorw  k0,k7,k1
  bc:   c5 f8 91 45 fe          kmovw  WORD PTR [rbp-0x2],k0
 
    z = __builtin_ia32_kxnorhi(x, y);
  d8:   0f b7 45 fc             movzx  eax,WORD PTR [rbp-0x4]
  dc:   0f b7 55 fa             movzx  edx,WORD PTR [rbp-0x6]
  e0:   c5 f8 92 d2             kmovw  k2,edx
  e4:   c5 f8 92 d8             kmovw  k3,eax
  e8:   c5 ec 46 c3             kxnorw k0,k2,k3
  ec:   c5 f8 91 45 fe          kmovw  WORD PTR [rbp-0x2],k0

8. Instrukce, v nichž se využívají nové maskovací registry

V instrukční sadě AVX-512F se nachází poměrně velké množství instrukcí, v nichž se využívají nové maskovací registry popsané v rámci předchozích dvou kapitol. Tyto nové či upravené instrukce můžeme rozdělit do několika kategorií.

Smíchání obsahu dvou registrů, tj. výběr, jak se vyberou prvky do cílového registru na základě bitové masky:

Instrukce Stručný popis instrukce
VBLENDMPD smíchání obsahu dvou registrů s prvky typu double
VBLENDMPS smíchání obsahu dvou registrů s prvky typu single/float
VPBLENDMD smíchání obsahu dvou registrů s prvky typu int32
VPBLENDMQ smíchání obsahu dvou registrů s prvky typu int64

Porovnání obsahu dvou registrů vybranou operací (EQ, LT, LE atd.), přičemž výsledek je uložen do maskovacího registru:

Instrukce Stručný popis instrukce
VPCMPD porovnání obsahu dvou registrů s prvky typu int32 s nastavením příznaků v maskovacím registru
VPCMPUD porovnání obsahu dvou registrů s prvky typu uint32 s nastavením příznaků v maskovacím registru
VPCMPQ porovnání obsahu dvou registrů s prvky typu int64 s nastavením příznaků v maskovacím registru
VPCMPUQ porovnání obsahu dvou registrů s prvky typu uint64 s nastavením příznaků v maskovacím registru

Provedení logické operace AND nebo NAND nad registry, výsledek (0 nebo 1) se uloží do zvoleného maskovacího registru:

Instrukce Stručný popis instrukce
VPTESTMD logická operace AND pro vektor s 32bitovými celými čísly
VPTESTMQ logická operace AND pro vektor s 64bitovými celými čísly
VPTESTNMD logická operace NAND pro vektor s 32bitovými celými čísly
VPTESTNMQ logická operace NAND pro vektor s 64bitovými celými čísly

9. Instrinsic pro instrukce vblendmps a addps s maskou

Podívejme se nyní na způsob použití některých instrukcí, v nichž se využívají maskovací registry resp. bitová maska. Nejdříve si ukážeme intrinsic nazvaný __builtin_ia32_blendmps512_mask, která implementuje instrukci typu vblendmps. Připomeňme si, že tato instrukce promíchá prvky dvou vektorů, přičemž každý vektor obsahuje šestnáct hodnot typu single/float. Promíchání se děje na základě obsahu maskovacího registru – pokud n-tý bit tohoto registru obsahuje logickou nulu, bude n-tý prvek výsledného vektoru získán z vektoru prvního, v opačném případě z vektoru druhého:

#include <stdio.h>
#include <immintrin.h>
 
int main(void)
{
    __v16sf x = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 };
    __v16sf y = { 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6 };
    __v16sf z;
    int i;
 
    z = __builtin_ia32_blendmps_512_mask(x, y, 0x0000);
 
    for (i = 0; i < sizeof(x) / sizeof(float); i++) {
        printf("%2d %f %f %f\n", i, x[i], y[i], z[i]);
    }
 
    putchar('\n');
 
    z = __builtin_ia32_blendmps_512_mask(x, y, 0x1111);
 
    for (i = 0; i < sizeof(x) / sizeof(float); i++) {
        printf("%2d %f %f %f\n", i, x[i], y[i], z[i]);
    }
 
    putchar('\n');
 
    z = __builtin_ia32_blendmps_512_mask(x, y, 0x5555);
 
    for (i = 0; i < sizeof(x) / sizeof(float); i++) {
        printf("%2d %f %f %f\n", i, x[i], y[i], z[i]);
    }
 
    putchar('\n');
 
    z = __builtin_ia32_blendmps_512_mask(x, y, 0xffff);
 
    for (i = 0; i < sizeof(x) / sizeof(float); i++) {
        printf("%2d %f %f %f\n", i, x[i], y[i], z[i]);
    }
 
    return 0;
}

Výsledky získané po překladu a spuštění tohoto příkladu ukazují, jak fungují jednotlivé šestnáctibitové masky:

 0 1.000000 0.100000 1.000000
 1 2.000000 0.200000 2.000000
 2 3.000000 0.300000 3.000000
 3 4.000000 0.400000 4.000000
 4 5.000000 0.500000 5.000000
 5 6.000000 0.600000 6.000000
 6 7.000000 0.700000 7.000000
 7 8.000000 0.800000 8.000000
 8 9.000000 0.900000 9.000000
 9 10.000000 1.100000 10.000000
10 11.000000 1.100000 11.000000
11 12.000000 1.200000 12.000000
12 13.000000 1.300000 13.000000
13 14.000000 1.400000 14.000000
14 15.000000 1.500000 15.000000
15 16.000000 1.600000 16.000000
 
 0 1.000000 0.100000 0.100000
 1 2.000000 0.200000 2.000000
 2 3.000000 0.300000 3.000000
 3 4.000000 0.400000 4.000000
 4 5.000000 0.500000 0.500000
 5 6.000000 0.600000 6.000000
 6 7.000000 0.700000 7.000000
 7 8.000000 0.800000 8.000000
 8 9.000000 0.900000 0.900000
 9 10.000000 1.100000 10.000000
10 11.000000 1.100000 11.000000
11 12.000000 1.200000 12.000000
12 13.000000 1.300000 1.300000
13 14.000000 1.400000 14.000000
14 15.000000 1.500000 15.000000
15 16.000000 1.600000 16.000000
 
 0 1.000000 0.100000 0.100000
 1 2.000000 0.200000 2.000000
 2 3.000000 0.300000 0.300000
 3 4.000000 0.400000 4.000000
 4 5.000000 0.500000 0.500000
 5 6.000000 0.600000 6.000000
 6 7.000000 0.700000 0.700000
 7 8.000000 0.800000 8.000000
 8 9.000000 0.900000 0.900000
 9 10.000000 1.100000 10.000000
10 11.000000 1.100000 1.100000
11 12.000000 1.200000 12.000000
12 13.000000 1.300000 1.300000
13 14.000000 1.400000 14.000000
14 15.000000 1.500000 1.500000
15 16.000000 1.600000 16.000000
 
 0 1.000000 0.100000 0.100000
 1 2.000000 0.200000 0.200000
 2 3.000000 0.300000 0.300000
 3 4.000000 0.400000 0.400000
 4 5.000000 0.500000 0.500000
 5 6.000000 0.600000 0.600000
 6 7.000000 0.700000 0.700000
 7 8.000000 0.800000 0.800000
 8 9.000000 0.900000 0.900000
 9 10.000000 1.100000 1.100000
10 11.000000 1.100000 1.100000
11 12.000000 1.200000 1.200000
12 13.000000 1.300000 1.300000
13 14.000000 1.400000 1.400000
14 15.000000 1.500000 1.500000
15 16.000000 1.600000 1.600000

Způsob překladu výše uvedené intrinsic do objektového kódu a do assembleru (nenechte se zmýlit odlišným jménem instrukce v GNU toolchainu):

    z = __builtin_ia32_blendmps_512_mask(x, y, 0x0000);
  55:   62 f1 7c 48 28 8d 10    vmovaps zmm1,ZMMWORD PTR [rbp-0xf0]
  5c:   ff ff ff
  5f:   62 f1 7c 48 28 85 d0    vmovaps zmm0,ZMMWORD PTR [rbp-0x130]
  66:   fe ff ff
  69:   c5 f4 47 c9             kxorw  k1,k1,k1
  6d:   62 f1 7c 49 28 c1       vmovaps zmm0{k1},zmm1
  73:   62 f1 7c 48 29 85 50    vmovaps ZMMWORD PTR [rbp-0xb0],zmm0
  7a:   ff ff ff
 
    z = __builtin_ia32_blendmps_512_mask(x, y, 0x1111);
  fd:   62 f1 7c 48 28 8d 10    vmovaps zmm1,ZMMWORD PTR [rbp-0xf0]
 104:   ff ff ff
 107:   62 f1 7c 48 28 85 d0    vmovaps zmm0,ZMMWORD PTR [rbp-0x130]
 10e:   fe ff ff
 111:   b8 11 11 00 00          mov    eax,0x1111
 116:   c5 f8 92 d0             kmovw  k2,eax
 11a:   62 f1 7c 4a 28 c1       vmovaps zmm0{k2},zmm1
 120:   62 f1 7c 48 29 85 50    vmovaps ZMMWORD PTR [rbp-0xb0],zmm0
 127:   ff ff ff
 
    z = __builtin_ia32_blendmps_512_mask(x, y, 0x5555);
 1aa:   62 f1 7c 48 28 8d 10    vmovaps zmm1,ZMMWORD PTR [rbp-0xf0]
 1b1:   ff ff ff
 1b4:   62 f1 7c 48 28 85 d0    vmovaps zmm0,ZMMWORD PTR [rbp-0x130]
 1bb:   fe ff ff
 1be:   b8 55 55 00 00          mov    eax,0x5555
 1c3:   c5 f8 92 d8             kmovw  k3,eax
 1c7:   62 f1 7c 4b 28 c1       vmovaps zmm0{k3},zmm1
 1cd:   62 f1 7c 48 29 85 50    vmovaps ZMMWORD PTR [rbp-0xb0],zmm0
 1d4:   ff ff ff
 
    z = __builtin_ia32_blendmps_512_mask(x, y, 0xffff);
 257:   62 f1 7c 48 28 8d 10    vmovaps zmm1,ZMMWORD PTR [rbp-0xf0]
 25e:   ff ff ff
 261:   62 f1 7c 48 28 85 d0    vmovaps zmm0,ZMMWORD PTR [rbp-0x130]
 268:   fe ff ff
 26b:   c5 f4 46 c9             kxnorw k1,k1,k1
 26f:   62 f1 7c 49 28 c1       vmovaps zmm0{k1},zmm1
 275:   62 f1 7c 48 29 85 50    vmovaps ZMMWORD PTR [rbp-0xb0],zmm0
 27c:   ff ff ff

V dalším demonstračním příkladu si ukážeme způsob použití intrinsic nazvané __builtin_ia32_addps512_mask. Podle názvu této intrinsic je zřejmé, že provádí vektorový součet, ovšem s využitím masky. Této intrinsic se předává trojice vektorů, maskovací registr (resp. přesněji řečeno hodnota, jenž se do maskovacího registru uloží) a taktéž parametr určující způsob zaokrouhlení. Zajímavé bude zjistit, jak se vlastně chová maska a proč se vůbec této instrukci předává trojice vektorů a nikoli jen dvojice. Podívejme se tedy nejdříve na zdrojový kód demonstračního příkladu:

#include <stdio.h>
#include <immintrin.h>
 
int main(void)
{
    __v16sf x = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 };
    __v16sf y = { 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6 };
    __v16sf z = -x;
    __v16sf w;
    int i;
 
    w = __builtin_ia32_addps512_mask(x, y, z, 0, _MM_FROUND_CUR_DIRECTION);
 
    for (i = 0; i < sizeof(x) / sizeof(float); i++) {
        printf("%2d  %5.1f  %5.1f  %5.1f  %5.1f\n", i, x[i], y[i], z[i], w[i]);
    }
 
    w = __builtin_ia32_addps512_mask(x, y, z, 0xf0f0, _MM_FROUND_CUR_DIRECTION);
 
    for (i = 0; i < sizeof(x) / sizeof(float); i++) {
        printf("%2d  %5.1f  %5.1f  %5.1f  %5.1f\n", i, x[i], y[i], z[i], w[i]);
    }
 
    w = __builtin_ia32_addps512_mask(x, y, z, -1, _MM_FROUND_CUR_DIRECTION);
 
    for (i = 0; i < sizeof(x) / sizeof(float); i++) {
        printf("%2d  %5.1f  %5.1f  %5.1f  %5.1f\n", i, x[i], y[i], z[i], w[i]);
    }
 
    return 0;
}

Výsledek výpočtů ukazuje, jak se vybírá operace součtu (dvou prvních vstupních registrů) nebo pouhého přesunu (ze třetího vstupního registru) na základě obsahu maskovacího registru:

 0    1.0    0.1   -1.0   -1.0
 1    2.0    0.2   -2.0   -2.0
 2    3.0    0.3   -3.0   -3.0
 3    4.0    0.4   -4.0   -4.0
 4    5.0    0.5   -5.0   -5.0
 5    6.0    0.6   -6.0   -6.0
 6    7.0    0.7   -7.0   -7.0
 7    8.0    0.8   -8.0   -8.0
 8    9.0    0.9   -9.0   -9.0
 9   10.0    1.1  -10.0  -10.0
10   11.0    1.1  -11.0  -11.0
11   12.0    1.2  -12.0  -12.0
12   13.0    1.3  -13.0  -13.0
13   14.0    1.4  -14.0  -14.0
14   15.0    1.5  -15.0  -15.0
15   16.0    1.6  -16.0  -16.0
 
 0    1.0    0.1   -1.0   -1.0
 1    2.0    0.2   -2.0   -2.0
 2    3.0    0.3   -3.0   -3.0
 3    4.0    0.4   -4.0   -4.0
 4    5.0    0.5   -5.0    5.5
 5    6.0    0.6   -6.0    6.6
 6    7.0    0.7   -7.0    7.7
 7    8.0    0.8   -8.0    8.8
 8    9.0    0.9   -9.0   -9.0
 9   10.0    1.1  -10.0  -10.0
10   11.0    1.1  -11.0  -11.0
11   12.0    1.2  -12.0  -12.0
12   13.0    1.3  -13.0   14.3
13   14.0    1.4  -14.0   15.4
14   15.0    1.5  -15.0   16.5
15   16.0    1.6  -16.0   17.6
 
 0    1.0    0.1   -1.0    1.1
 1    2.0    0.2   -2.0    2.2
 2    3.0    0.3   -3.0    3.3
 3    4.0    0.4   -4.0    4.4
 4    5.0    0.5   -5.0    5.5
 5    6.0    0.6   -6.0    6.6
 6    7.0    0.7   -7.0    7.7
 7    8.0    0.8   -8.0    8.8
 8    9.0    0.9   -9.0    9.9
 9   10.0    1.1  -10.0   11.1
10   11.0    1.1  -11.0   12.1
11   12.0    1.2  -12.0   13.2
12   13.0    1.3  -13.0   14.3
13   14.0    1.4  -14.0   15.4
14   15.0    1.5  -15.0   16.5
15   16.0    1.6  -16.0   17.6

Způsob překladu výše uvedené intrinsic do objektového kódu a do assembleru:

    w = __builtin_ia32_addps512_mask(x, y, z, 0, _MM_FROUND_CUR_DIRECTION);
  79:   62 f1 7c 48 28 85 10    vmovaps zmm0,ZMMWORD PTR [rbp-0xf0]
  80:   ff ff ff
  83:   62 f1 7c 48 28 8d d0    vmovaps zmm1,ZMMWORD PTR [rbp-0x130]
  8a:   fe ff ff
  8d:   62 f1 7c 48 28 95 90    vmovaps zmm2,ZMMWORD PTR [rbp-0x170]
  94:   fe ff ff
  97:   c5 f4 47 c9             kxorw  k1,k1,k1
  9b:   62 f1 6c 49 58 c1       vaddps zmm0{k1},zmm2,zmm1
  a1:   62 f1 7c 48 29 85 50    vmovaps ZMMWORD PTR [rbp-0xb0],zmm0
  a8:   ff ff ff
 
    w = __builtin_ia32_addps512_mask(x, y, z, 0xf0f0, _MM_FROUND_CUR_DIRECTION);
 136:   62 f1 7c 48 28 85 10    vmovaps zmm0,ZMMWORD PTR [rbp-0xf0]
 13d:   ff ff ff
 140:   62 f1 7c 48 28 8d d0    vmovaps zmm1,ZMMWORD PTR [rbp-0x130]
 147:   fe ff ff
 14a:   62 f1 7c 48 28 95 90    vmovaps zmm2,ZMMWORD PTR [rbp-0x170]
 151:   fe ff ff
 154:   b8 f0 f0 ff ff          mov    eax,0xfffff0f0
 159:   c5 f8 92 d0             kmovw  k2,eax
 15d:   62 f1 6c 4a 58 c1       vaddps zmm0{k2},zmm2,zmm1
 163:   62 f1 7c 48 29 85 50    vmovaps ZMMWORD PTR [rbp-0xb0],zmm0
 16a:   ff ff ff
 
    w = __builtin_ia32_addps512_mask(x, y, z, -1, _MM_FROUND_CUR_DIRECTION);
 1f8:   62 f1 7c 48 28 85 10    vmovaps zmm0,ZMMWORD PTR [rbp-0xf0]
 1ff:   ff ff ff
 202:   62 f1 7c 48 28 8d d0    vmovaps zmm1,ZMMWORD PTR [rbp-0x130]
 209:   fe ff ff
 20c:   62 f1 7c 48 28 95 90    vmovaps zmm2,ZMMWORD PTR [rbp-0x170]
 213:   fe ff ff
 216:   c5 f4 46 c9             kxnorw k1,k1,k1
 21a:   62 f1 6c 49 58 c1       vaddps zmm0{k1},zmm2,zmm1
 220:   62 f1 7c 48 29 85 50    vmovaps ZMMWORD PTR [rbp-0xb0],zmm0
 227:   ff ff ff

10. Komprese a expanze dat

Nyní se dostáváme k zajímavé části AVX-512F. Jedná se o instrukce určené ke „kompresi“ a „expanzi“ dat, resp. přesněji řečeno prvků uložených ve vektorech. Na těchto operacích je zajímavý fakt, že byly poprvé představeny v programovacím jazyku APL. Ovšem ukazuje se, že se jedná o užitečné operace, takže se staly součástí mainstreamu. Jak však tyto operace pracují?

Podívejme se nejdříve na operaci komprese. Ta pracuje s dvojicí vektorů – vektorem libovolných hodnot a bitovým vektorem. Do výsledného vektoru se uloží (za sebou, tedy komprimovaně) pouze ty prvky ze vstupního vektoru, pro které je odpovídající prvek bitového vektoru nastaven na jedničku. Pro desetiprvkové vektory to může vypadat následovně:

compress([1 0 1 0 1 0 1 0 1 0], [1 2 3 4 5 6 7 8 9 10]) = [x x x x x 1 3 5 7 9]
compress([0 0 0 0 0 1 1 1 1 1], [1 2 3 4 5 6 7 8 9 10]) = [x x x x x 6 7 8 9 10]
compress([1 1 1 1 1 0 0 0 0 0], [1 2 3 4 5 6 7 8 9 10]) = [x x x x x 1 2 3 4 5]
Poznámka: ve skutečnosti se v AVX-512F pracuje s dvojicí vstupních vektorů, takže se namísto hodnot x doplní prvky ze druhého vektoru (a nikoli nuly).

Operace expanze naopak na vstupu očekává vektor „komprimovaných“ hodnot a bitový vektor. Výsledkem bude nový vektor, do kterého jsou na příslušná místa přidány nulové prvky i prvky ze vstupního vektoru: pokud je bit v bitovém vektoru jedničkový, je prvek přečten ze vstupního vektoru, jinak je do výsledku přidána nula. Demonstrační příklady ukážou přesně, jaká operace se provádí:

expand([0 0 0 0 0 1 1 1 1 1], [x x x x x 1 2 3 4 5], [0 0 0 0 0 1 2 3 4 5])
expand([1 0 1 0 1 0 1 0 1 0], [x x x x x 1 2 3 4 5], [1 0 2 0 3 0 4 0 5 0])
expand([1 0 0 0 0 0 1 1 1 1], [x x x x x 1 2 3 4 5], [1 0 0 0 0 0 2 3 4 5])

V tomto případě je výhodné zobrazit si bitový vektor a výsledný vektor pod sebou, aby bylo zřejmé, jaká operace se provádí:

0 0 0 0 0 1 1 1 1 1
0 0 0 0 0 1 2 3 4 5
 
1 0 1 0 1 0 1 0 1 0
1 0 2 0 3 0 4 0 5 0
 
1 0 0 0 0 0 1 1 1 1
1 0 0 0 0 0 2 3 4 5
Poznámka: povšimněte si korespondence mezi jedničkami v bitovém vektoru a prvky ve vektoru cílovém.

11. Instrukce pro kompresi a expanzi dat

Výše uvedené instrukce pro kompresi a expanzi dat jsou v AVX-512F pojmenovány takto:

Instrukce Stručný popis instrukce
VCOMPRESSPD komprese dat pro prvky typu double
VCOMPRESSPS komprese dat pro prvky typu single/float
VPCOMPRESSD komprese dat pro prvky typu int32
VPCOMPRESSQ komprese dat pro prvky typu int64
VEXPANDPD expanze dat pro prvky typu double
VEXPANDPS expanze dat pro prvky typu single/float
VPEXPANDD expanze dat pro prvky typu int32
VPEXPANDQ expanze dat pro prvky typu int64
Poznámka: vzhledem k tomu, že nezáleží na kódování hodnot, ale jen na jejich délce, jsou operace pro int32 shodné s operacemi pro single/float a totéž platí pro dvojici int64 a double.

12. Instrinsic pro instrukce komprese dat

Otestujme si nyní intrinsic poskytovanou překladačem GCC C, která slouží pro vygenerování některé z instrukcí pro kompresi dat. Konkrétně použijeme intrinsic nazvanou __builtin_ia32_compresssf512_mask, která na vstupu pracuje se dvěma vektory hodnot typu float/single a taky s celočíselnou šestnáctibitovou maskou. Na základě bitů v masce je potom seskládán výsledný vektor, který bude opět obsahovat šestnáct hodnot typu float/single:

#include <stdio.h>
#include <immintrin.h>
 
int main(void)
{
    __v16sf x = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 };
    __v16sf y = -x;
    __v16sf z;
    int i;
 
    z = __builtin_ia32_compresssf512_mask(x, y, 0b1010101010101010);
 
    for (i = 0; i < sizeof(x) / sizeof(float); i++) {
        printf("%2d %f %f %f\n", i, x[i], y[i], z[i]);
    }
 
    putchar('\n');
 
    z = __builtin_ia32_compresssf512_mask(x, y, 0b0000000011111111);
 
    for (i = 0; i < sizeof(x) / sizeof(float); i++) {
        printf("%2d %f %f %f\n", i, x[i], y[i], z[i]);
    }
 
    putchar('\n');
 
    z = __builtin_ia32_compresssf512_mask(x, y, 0b1111111100000000);
 
    for (i = 0; i < sizeof(x) / sizeof(float); i++) {
        printf("%2d %f %f %f\n", i, x[i], y[i], z[i]);
    }
 
    return 0;
}

Výsledky získané pro trojici bitových masek podle zdrojového kódu demonstračního příkladu:

 0 1.000000 -1.000000 2.000000
 1 2.000000 -2.000000 4.000000
 2 3.000000 -3.000000 6.000000
 3 4.000000 -4.000000 8.000000
 4 5.000000 -5.000000 10.000000
 5 6.000000 -6.000000 12.000000
 6 7.000000 -7.000000 14.000000
 7 8.000000 -8.000000 16.000000
 8 9.000000 -9.000000 -9.000000
 9 10.000000 -10.000000 -10.000000
10 11.000000 -11.000000 -11.000000
11 12.000000 -12.000000 -12.000000
12 13.000000 -13.000000 -13.000000
13 14.000000 -14.000000 -14.000000
14 15.000000 -15.000000 -15.000000
15 16.000000 -16.000000 -16.000000
 
 0 1.000000 -1.000000 1.000000
 1 2.000000 -2.000000 2.000000
 2 3.000000 -3.000000 3.000000
 3 4.000000 -4.000000 4.000000
 4 5.000000 -5.000000 5.000000
 5 6.000000 -6.000000 6.000000
 6 7.000000 -7.000000 7.000000
 7 8.000000 -8.000000 8.000000
 8 9.000000 -9.000000 -9.000000
 9 10.000000 -10.000000 -10.000000
10 11.000000 -11.000000 -11.000000
11 12.000000 -12.000000 -12.000000
12 13.000000 -13.000000 -13.000000
13 14.000000 -14.000000 -14.000000
14 15.000000 -15.000000 -15.000000
15 16.000000 -16.000000 -16.000000
 
 0 1.000000 -1.000000 9.000000
 1 2.000000 -2.000000 10.000000
 2 3.000000 -3.000000 11.000000
 3 4.000000 -4.000000 12.000000
 4 5.000000 -5.000000 13.000000
 5 6.000000 -6.000000 14.000000
 6 7.000000 -7.000000 15.000000
 7 8.000000 -8.000000 16.000000
 8 9.000000 -9.000000 -9.000000
 9 10.000000 -10.000000 -10.000000
10 11.000000 -11.000000 -11.000000
11 12.000000 -12.000000 -12.000000
12 13.000000 -13.000000 -13.000000
13 14.000000 -14.000000 -14.000000
14 15.000000 -15.000000 -15.000000
15 16.000000 -16.000000 -16.000000
Poznámka: povšimněte si, že se skutečně nejdříve provede „komprese“ hodnot z prvního vektoru, ke kterým se přidají hodnoty z vektoru druhého (kolik těchto hodnot bude nelze bez znalosti masky říci).

Překlad intrinsic do objektového kódu (a do assembleru) bude vypadat následovně:

    z = __builtin_ia32_compresssf512_mask(x, y, 0b1010101010101010);
  65:   62 f1 7c 48 28 8d 10    vmovaps zmm1,ZMMWORD PTR [rbp-0xf0]
  6c:   ff ff ff
  6f:   62 f1 7c 48 28 85 d0    vmovaps zmm0,ZMMWORD PTR [rbp-0x130]
  76:   fe ff ff
  79:   b8 aa aa ff ff          mov    eax,0xffffaaaa
  7e:   c5 f8 92 c8             kmovw  k1,eax
  82:   62 f2 7d 49 8a c1       vcompressps zmm1{k1},zmm0
  88:   62 f1 7c 48 28 c1       vmovaps zmm0,zmm1
  8e:   62 f1 7c 48 29 85 50    vmovaps ZMMWORD PTR [rbp-0xb0],zmm0
  95:   ff ff ff
 
    z = __builtin_ia32_compresssf512_mask(x, y, 0b0000000011111111);
 118:   62 f1 7c 48 28 8d 10    vmovaps zmm1,ZMMWORD PTR [rbp-0xf0]
 11f:   ff ff ff
 122:   62 f1 7c 48 28 85 d0    vmovaps zmm0,ZMMWORD PTR [rbp-0x130]
 129:   fe ff ff
 12c:   b8 ff 00 00 00          mov    eax,0xff
 131:   c5 f8 92 d0             kmovw  k2,eax
 135:   62 f2 7d 4a 8a c1       vcompressps zmm1{k2},zmm0
 13b:   62 f1 7c 48 28 c1       vmovaps zmm0,zmm1
 141:   62 f1 7c 48 29 85 50    vmovaps ZMMWORD PTR [rbp-0xb0],zmm0
 148:   ff ff ff
 
    z = __builtin_ia32_compresssf512_mask(x, y, 0b1111111100000000);
 1cb:   62 f1 7c 48 28 8d 10    vmovaps zmm1,ZMMWORD PTR [rbp-0xf0]
 1d2:   ff ff ff
 1d5:   62 f1 7c 48 28 85 d0    vmovaps zmm0,ZMMWORD PTR [rbp-0x130]
 1dc:   fe ff ff
 1df:   b8 00 ff ff ff          mov    eax,0xffffff00
 1e4:   c5 f8 92 d8             kmovw  k3,eax
 1e8:   62 f2 7d 4b 8a c1       vcompressps zmm1{k3},zmm0
 1ee:   62 f1 7c 48 28 c1       vmovaps zmm0,zmm1
 1f4:   62 f1 7c 48 29 85 50    vmovaps ZMMWORD PTR [rbp-0xb0],zmm0
 1fb:   ff ff ff

13. Instrukce pro provedení permutace (přerozdělení) prvků vektorů

Mezi další instrukce přidané do AVX-512F (a tedy podporované všemi typy mikroprocesorů, které mají implementovanou nějakou kombinaci sad AVX-512) patří instrukce provádějící permutaci (tedy přerozdělení) prvků vektorů. Jedná se konkrétně o tyto instrukce:

Instrukce Stručný popis instrukce
VPERMI2PD permutace vektorů s prvky typu double s přepisem indexu
VPERMI2PS permutace vektorů s prvky typu single s přepisem indexu
VPERMI2D permutace vektorů s prvky typu int32 s přepisem indexu
VPERMI2Q permutace vektorů s prvky typu int64 s přepisem indexu
VPERMT2PD permutace vektorů s prvky typu double s přepisem prvního zdrojového registru
VPERMT2PS permutace vektorů s prvky typu single s přepisem prvního zdrojového registru
VPERMT2D permutace vektorů s prvky typu int32 s přepisem prvního zdrojového registru
VPERMT2Q permutace vektorů s prvky typu int64 s přepisem prvního zdrojového registru
VSHUFF32×4 přeskládání čtveřice lanes, z nichž každá má šířku 128 bitů
VSHUFF64×2 přeskládání čtveřice lanes, z nichž každá má šířku 128 bitů
VSHUFI32×4 přeskládání čtveřice lanes, z nichž každá má šířku 128 bitů
VSHUFI64×2 přeskládání čtveřice lanes, z nichž každá má šířku 128 bitů
Poznámka: konkrétní ukázku permutaci si ukážeme v navazující kapitole.

14. Intrinsic pro provedení permutace

Vyzkoušejme si nyní, jak vlastně instrukce pro provedení permutace funguje. Opět se zaměříme na dvojici vstupních vektorů, z nichž každý obsahuje šestnáct hodnot typu single/float. První vektor bude obsahovat kladné hodnoty, druhý vektor hodnoty záporné. S touto dvojicí vektorů provedeme permutaci s využitím indexu (osmibitová celočíselná hodnota) a zápisové masky (šestnáctibitová celočíselná hodnota). Výsledek je vypsán pro různé kombinace indexů a zápisových masek:

#include <stdio.h>
#include <immintrin.h>
 
int main(void)
{
    __v16sf x = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 };
    __v16sf y = -x;
    __v16sf z;
    int i;
 
    z = __builtin_ia32_vpermilps512_mask(x, 0x00, z, 0x0000);
 
    for (i = 0; i < sizeof(x) / sizeof(float); i++) {
        printf("%2d %f %f %f\n", i, x[i], y[i], z[i]);
    }
 
    putchar('\n');
 
    z = __builtin_ia32_vpermilps512_mask(x, 0x00, z, 0xffff);
 
    for (i = 0; i < sizeof(x) / sizeof(float); i++) {
        printf("%2d %f %f %f\n", i, x[i], y[i], z[i]);
    }
 
    putchar('\n');
 
    z = __builtin_ia32_vpermilps512_mask(x, 0x03, z, 0xffff);
 
    for (i = 0; i < sizeof(x) / sizeof(float); i++) {
        printf("%2d %f %f %f\n", i, x[i], y[i], z[i]);
    }
 
    putchar('\n');
 
    z = __builtin_ia32_vpermilps512_mask(x, 0x04, z, 0xffff);
 
    for (i = 0; i < sizeof(x) / sizeof(float); i++) {
        printf("%2d %f %f %f\n", i, x[i], y[i], z[i]);
    }
 
    putchar('\n');
 
    return 0;
}

Výsledky rozdělíme do čtyř skupin.

Index nastavený na 0×00, maska nastavená na 0×0000. Vzhledem k tomu, že všechny bity masky jsou nulové a současně i index je nulový, budou všechny prvky vektoru nastaveny na nulu (nezávisle na obsahu vstupních vektorů):

 0 1.000000 -1.000000 0.000000
 1 2.000000 -2.000000 0.000000
 2 3.000000 -3.000000 0.000000
 3 4.000000 -4.000000 0.000000
 4 5.000000 -5.000000 0.000000
 5 6.000000 -6.000000 0.000000
 6 7.000000 -7.000000 0.000000
 7 8.000000 -8.000000 0.000000
 8 9.000000 -9.000000 0.000000
 9 10.000000 -10.000000 0.000000
10 11.000000 -11.000000 0.000000
11 12.000000 -12.000000 0.000000
12 13.000000 -13.000000 0.000000
13 14.000000 -14.000000 0.000000
14 15.000000 -15.000000 0.000000
15 16.000000 -16.000000 0.000000

Index nastavený na 0×00, maska nastavená na 0×ffff. Maska nyní nebude „blokovat/nulovat“ prvky, takže se projeví vliv indexu. Vstupní vektor je rozdělený do čtyř částí a z každé části je vybrán první prvek (který je následně rozkopírován do čtyř prvků výsledného vektoru):

 0 1.000000 -1.000000 1.000000
 1 2.000000 -2.000000 1.000000
 2 3.000000 -3.000000 1.000000
 3 4.000000 -4.000000 1.000000
 
 4 5.000000 -5.000000 5.000000
 5 6.000000 -6.000000 5.000000
 6 7.000000 -7.000000 5.000000
 7 8.000000 -8.000000 5.000000
 
 8 9.000000 -9.000000 9.000000
 9 10.000000 -10.000000 9.000000
10 11.000000 -11.000000 9.000000
11 12.000000 -12.000000 9.000000
 
12 13.000000 -13.000000 13.000000
13 14.000000 -14.000000 13.000000
14 15.000000 -15.000000 13.000000
15 16.000000 -16.000000 13.000000

Index nastavený na 0×03, maska nastavená na 0×ffff. Opět dojde k rozdělení vstupního vektoru na čtyři části. První prvek každé části výsledného vektoru z každé části bude vybrán ze vstupního vektoru ze stejné části, ovšem s indexem posunutým o trojku:

 0 1.000000 -1.000000 4.000000
 1 2.000000 -2.000000 1.000000
 2 3.000000 -3.000000 1.000000
 3 4.000000 -4.000000 1.000000
 
 4 5.000000 -5.000000 8.000000
 5 6.000000 -6.000000 5.000000
 6 7.000000 -7.000000 5.000000
 7 8.000000 -8.000000 5.000000
 
 8 9.000000 -9.000000 12.000000
 9 10.000000 -10.000000 9.000000
10 11.000000 -11.000000 9.000000
11 12.000000 -12.000000 9.000000
 
12 13.000000 -13.000000 16.000000
13 14.000000 -14.000000 13.000000
14 15.000000 -15.000000 13.000000
15 16.000000 -16.000000 13.000000

Index nastavený na 0×04, maska nastavená na 0×ffff. Opět dojde k rozdělení vstupního vektoru na čtyři části. Tentokrát se ovšem díky konstantě 0×04 (nastavený bit s indexe 5) změní způsob výběru druhého prvku:

 0 1.000000 -1.000000 1.000000
 1 2.000000 -2.000000 2.000000
 2 3.000000 -3.000000 1.000000
 3 4.000000 -4.000000 1.000000
 
 4 5.000000 -5.000000 5.000000
 5 6.000000 -6.000000 6.000000
 6 7.000000 -7.000000 5.000000
 7 8.000000 -8.000000 5.000000
 
 8 9.000000 -9.000000 9.000000
 9 10.000000 -10.000000 10.000000
10 11.000000 -11.000000 9.000000
11 12.000000 -12.000000 9.000000
 
12 13.000000 -13.000000 13.000000
13 14.000000 -14.000000 14.000000
14 15.000000 -15.000000 13.000000
15 16.000000 -16.000000 13.000000

Kombinace předchozích možností: index nastavený na 0×11, maska nastavená na 0×ffff:

 0 1.000000 -1.000000 2.000000
 1 2.000000 -2.000000 1.000000
 2 3.000000 -3.000000 2.000000
 3 4.000000 -4.000000 1.000000
 4 5.000000 -5.000000 6.000000
 5 6.000000 -6.000000 5.000000
 6 7.000000 -7.000000 6.000000
 7 8.000000 -8.000000 5.000000
 8 9.000000 -9.000000 10.000000
 9 10.000000 -10.000000 9.000000
10 11.000000 -11.000000 10.000000
11 12.000000 -12.000000 9.000000
12 13.000000 -13.000000 14.000000
13 14.000000 -14.000000 13.000000
14 15.000000 -15.000000 14.000000
15 16.000000 -16.000000 13.000000

15. Rozšíření AVX-512BW

Zajímavou podmnožinou AVX-512 je AVX-512BW. Tato podmnožina rozšiřuje většinu již existujících instrukcí takovým způsobem, aby je bylo možné použít i pro vektory s datovými typy int8/byte a int16. Zdálo by se, že toto rozšíření je triviální, ovšem je zde jeden háček – vektorové registry o šířce 512 bitů obsahují 64 prvků typu int8/byte a 32 prvků typu int16, takže pro ty instrukce, v nichž se používají maskovací registry, muselo dojít k rozšíření těchto registrů na 32 resp. pro bytové vektory dokonce na 64 bitů. I přes tento problém je rozšíření AVX-512BW potenciálně velmi dobře použitelné například při zpracování audia a videa, stejně jako pro operace s rastrovými obrázky. Všechny nové instrukce popsané v předchozích kapitolách, byly upraveny i pro typy int8 a int16, pouze se změnila koncovka na B, W, UB nebo UW:

Instrukce
VPBLENDMB
VPBLENDMW
VPCMPB
VPCMPUB
VPCMPW
VPCMPUW
VPTESTMB
VPTESTMW
VPTESTNMB
VPTESTNMW
VPERMT2W
VPERMI2W

16. Rozšíření Vector Neural Network Instructions (VNNI)

Potenciálně užitečné (pokud se tedy všechny výpočty nepřesunou na GPU) jsou čtyři instrukce zavedené v rámci podmnožiny VNNI neboli Vector Neural Network Instructions. Tyto instrukce provádí výpočty s vektory, jejichž prvky jsou typu bajt nebo šestnáctibitové celé číslo:

Instrukce Stručný popis
VPDPBUSD vynásobení skupin čtyř dvojic bajtů se součtem výsledků
VPDPBUSDS dtto, ovšem se saturací
VPDPWSSD dtto, jako VPDPBUSD, ovšem pro šestnáctibitové hodnoty
VPDPWSSDS dtto, jako VPDPBUSDS, ovšem pro šestnáctibitové hodnoty

17. Příloha – soubor Makefile použitý v článcích o SIMD operacích

Následující soubor Makefile byl použit pro překlad zdrojových kódů všech výše uvedených demonstračních příkladů do objektového kódu jeho s následným disassemblingem do assembleru (resp. přesněji řečeno do assembleru zkombinovaného s hexadecimálním výpisem obsahu souboru s objektovým kódem). Makefile obsahuje i instrukce pro překlad demonstračních příkladů z předchozích článků o SIMD operacích:

CC=gcc
OBJDUMP=objdump
 
all:    simd04_1.lst simd04_2.lst \
        simd04B_1.lst simd04B_2.lst \
        simd07_1.lst simd07_2.lst \
        simd08_1.lst simd08_2.lst \
        simd12_1.lst simd12_2.lst \
        simd13_1.lst simd13_2.lst simd13_3.lst simd13_4.lst \
        simd14_1.lst simd14_2.lst simd14_3.lst simd14_4.lst \
        simd15_1.lst simd15_2.lst simd15_3.lst simd15_4.lst \
        simd16_1.lst simd16_2.lst simd16_3.lst simd16_4.lst \
        simd17_1.lst simd17_2.lst simd17_3.lst simd17_4.lst \
        simd18_1.lst simd18_2.lst simd18_3.lst simd18_4.lst \
        simd19_sse.lst simd19_avx.lst simd19_avx2.lst \
        simd20_sse.lst simd20_avx.lst simd20_avx2.lst \
        simd21_sse.lst simd21_avx.lst simd21_avx2.lst \
        intrinsic_mmx_1.lst \
        intrinsic_mmx_2.lst \
        intrinsic_mmx_3.lst \
        intrinsic_mmx_4.lst \
        intrinsic_mmx_5.lst \
        intrinsic_sse_1.lst \
        intrinsic_sse_2.lst \
        intrinsic_sse_3.lst \
        intrinsic_sse_4.lst \
        intrinsic_sse_5.lst \
        intrinsic_sse_6.lst \
        intrinsic_sse_7.lst \
        intrinsic_sse_8.lst \
        intrinsic_sse_9.lst \
        intrinsic_sse_A.lst \
        intrinsic_sse_B.lst \
        intrinsic_f16c_1.lst \
        intrinsic_f16c_2.lst \
        intrinsic_f16c_3.lst \
        intrinsic_f16c_4.lst \
        intrinsic_fma3_1.lst \
        intrinsic_fma3_2.lst \
        intrinsic_fma3_3.lst \
        intrinsic_fma3_4.lst \
        intrinsic_fma3_5.lst \
        intrinsic_avx_512_k_registers.lst \
        intrinsic_avx_512_vblendps.c \
        intrinsic_avx_512_addps.c \
        intrinsic_avx_512_compress.c
 
clean:
        rm *.lst
        rm *.o
 
%.lst:  %.o
        objdump -d -M intel -S $< > $@
 
simd04_1.o:     simd04.c
        gcc -c -O0 -mno-sse -g -o $@ $<
 
simd04_2.o:     simd04.c
        gcc -c -O0 -g -o $@ $<
 
simd04B_1.o:    simd04B.c
        gcc -c -O0 -mno-sse -g -o $@ $<
 
simd04B_2.o:    simd04B.c
        gcc -c -O0 -g -o $@ $<
 
simd07_1.o:     simd07.c
        gcc -c -mno-sse -g -o $@ $<
 
simd07_2.o:     simd07.c
        gcc -c -g -o $@ $<
 
simd08_1.o:     simd08.c
        gcc -c -mno-sse -g -o $@ $<
 
simd08_2.o:     simd08.c
        gcc -c -g -o $@ $<
 
simd12_1.o:     simd12.c
        gcc -c -O0 -mno-sse -g -o $@ $<
 
simd12_2.o:     simd12.c
        gcc -c -O0 -g -o $@ $<
 
simd13_1.o:     simd13.c
        gcc -c -O0 -mno-sse -g -o $@ $<
 
simd13_2.o:     simd13.c
        gcc -c -O0 -g -o $@ $<
 
simd13_3.o:     simd13.c
        gcc -c -O3 -mno-sse -g -o $@ $<
 
simd13_4.o:     simd13.c
        gcc -c -O3 -g -o $@ $<
 
simd14_1.o:     simd14.c
        gcc -c -O0 -mno-sse -g -o $@ $<
 
simd14_2.o:     simd14.c
        gcc -c -O0 -g -o $@ $<
 
simd14_3.o:     simd14.c
        gcc -c -O3 -mno-sse -g -o $@ $<
 
simd14_4.o:     simd14.c
        gcc -c -O3 -g -o $@ $<
 
simd15_1.o:     simd15.c
        gcc -c -O0 -mno-sse -g -o $@ $<
 
simd15_2.o:     simd15.c
        gcc -c -O0 -g -o $@ $<
 
simd15_3.o:     simd15.c
        gcc -c -O3 -mno-sse -g -o $@ $<
 
simd15_4.o:     simd15.c
        gcc -c -O3 -g -o $@ $<
 
simd16_1.o:     simd16.c
        gcc -c -O0 -mno-sse -g -o $@ $<
 
simd16_2.o:     simd16.c
        gcc -c -O0 -g -o $@ $<
 
simd16_3.o:     simd16.c
        gcc -c -O3 -mno-sse -g -o $@ $<
 
simd16_4.o:     simd16.c
        gcc -c -O3 -g -o $@ $<
 
simd17_1.o:     simd17.c
        gcc -c -O0 -mno-sse -g -o $@ $<
 
simd17_2.o:     simd17.c
        gcc -c -O0 -g -o $@ $<
 
simd17_3.o:     simd17.c
        gcc -c -O3 -mno-sse -g -o $@ $<
 
simd17_4.o:     simd17.c
        gcc -c -O3 -g -o $@ $<
 
simd18_1.o:     simd18.c
        gcc -c -O0 -mno-sse -g -o $@ $<
 
simd18_2.o:     simd18.c
        gcc -c -O0 -g -o $@ $<
 
simd18_3.o:     simd18.c
        gcc -c -O3 -mno-sse -g -o $@ $<
 
simd18_4.o:     simd18.c
        gcc -c -O3 -g -o $@ $<
 
simd19_sse.o:   simd19.c
        gcc -c -O0 -msse -mno-avx -g -o $@ $<
 
simd19_avx.o:   simd19.c
        gcc -c -O0 -mavx -g -o $@ $<
 
simd19_avx2.o:  simd19.c
        gcc -c -O0 -mavx2 -g -o $@ $<
 
simd20_sse.o:   simd20.c
        gcc -c -O0 -msse -mno-avx -g -o $@ $<
 
simd20_avx.o:   simd20.c
        gcc -c -O0 -mavx -g -o $@ $<
 
simd20_avx2.o:  simd20.c
        gcc -c -O0 -mavx2 -g -o $@ $<
 
simd21_sse.o:   simd21.c
        gcc -c -O0 -msse -mno-avx -g -o $@ $<
 
simd21_avx.o:   simd21.c
        gcc -c -O0 -mavx -g -o $@ $<
 
simd21_avx2.o:  simd21.c
        gcc -c -O0 -mavx2 -g -o $@ $<
 
intrinsic_mmx_1.o:      intrinsic_mmx_1.c
        gcc -c -O0 -g -o $@ $<
 
intrinsic_mmx_2.o:      intrinsic_mmx_2.c
        gcc -c -O0 -g -o $@ $<
 
intrinsic_mmx_3.o:      intrinsic_mmx_3.c
        gcc -c -O0 -g -o $@ $<
 
intrinsic_mmx_4.o:      intrinsic_mmx_4.c
        gcc -c -O0 -g -o $@ $<
 
intrinsic_mmx_5.o:      intrinsic_mmx_5.c
        gcc -c -O0 -g -o $@ $<
 
intrinsic_sse_1.o:      intrinsic_sse_1.c
        gcc -c -O0 -g -o $@ $<
 
intrinsic_sse_2.o:      intrinsic_sse_2.c
        gcc -c -O0 -g -o $@ $<
 
intrinsic_sse_3.o:      intrinsic_sse_3.c
        gcc -c -O0 -g -o $@ $<
 
intrinsic_sse_4.o:      intrinsic_sse_4.c
        gcc -c -O0 -g -o $@ $<
 
intrinsic_sse_5.o:      intrinsic_sse_5.c
        gcc -c -O0 -g -o $@ $<
 
intrinsic_sse_6.o:      intrinsic_sse_6.c
        gcc -c -O0 -g -o $@ $<
 
intrinsic_sse_7.o:      intrinsic_sse_7.c
        gcc -c -O0 -g -o $@ $<
 
intrinsic_sse_8.o:      intrinsic_sse_8.c
        gcc -c -O0 -g -o $@ $<
 
intrinsic_sse_9.o:      intrinsic_sse_9.c
        gcc -c -O0 -g -o $@ $<
 
intrinsic_sse_A.o:      intrinsic_sse_A.c
        gcc -c -O0 -g -o $@ $<
 
intrinsic_sse_B.o:      intrinsic_sse_B.c
        gcc -c -O0 -g -o $@ $<
 
intrinsic_avx_1.o:      intrinsic_avx_1.c
        gcc -c -mavx -O0 -g -o $@ $<
 
intrinsic_avx_2.o:      intrinsic_avx_2.c
        gcc -c -mavx -O0 -g -o $@ $<
 
intrinsic_avx_3.o:      intrinsic_avx_3.c
        gcc -c -mavx -O0 -g -o $@ $<
 
intrinsic_f16c_1.o:     intrinsic_f16c_1.c
        gcc -c -mf16c -O0 -g -o $@ $<
 
intrinsic_f16c_2.o:     intrinsic_f16c_2.c
        gcc -c -mf16c -O0 -g -o $@ $<
 
intrinsic_f16c_3.o:     intrinsic_f16c_3.c
        gcc -c -mf16c -O0 -g -o $@ $<
 
intrinsic_f16c_4.o:     intrinsic_f16c_4.c
        gcc -c -mf16c -O0 -g -o $@ $<
 
intrinsic_fma3_1.o:     intrinsic_fma3_1.c
        gcc -c -mfma -O0 -g -o $@ $<
 
intrinsic_fma3_2.o:     intrinsic_fma3_2.c
        gcc -c -mfma -O0 -g -o $@ $<
 
intrinsic_fma3_3.o:     intrinsic_fma3_3.c
        gcc -c -mfma -O0 -g -o $@ $<
 
intrinsic_fma3_4.o:     intrinsic_fma3_4.c
        gcc -c -mfma -O0 -g -o $@ $<
 
intrinsic_fma3_5.o:     intrinsic_fma3_5.c
        gcc -c -mfma -O0 -g -o $@ $<
 
intrinsic_avx_512_k_registers.o:        intrinsic_avx_512_k_registers.c
        gcc -c -mavx512f -O0 -g -o $@ $<
 
intrinsic_avx_512_vblendps.o:   intrinsic_avx_512_vblendps.c
        gcc -c -mavx512f -O0 -g -o $@ $<
 
intrinsic_avx_512_addps.o:      intrinsic_avx_512_addps.c
        gcc -c -mavx512f -O0 -g -o $@ $<
 
intrinsic_avx_512_compress.o:   intrinsic_avx_512_compress.c
        gcc -c -mavx512f -O0 -g -o $@ $<

18. Repositář s demonstračními příklady

Demonstrační příklady napsané v jazyku C, které jsou určené pro překlad pomocí překladače GCC C, byly uložen do Git repositáře, který je dostupný na adrese https://github.com/tisnik/pre­sentations. Jednotlivé demonstrační příklady si můžete v případě potřeby stáhnout i jednotlivě bez nutnosti klonovat celý (dnes již velmi rozsáhlý) repositář:

# Příklad Stručný popis Adresa
1 simd01.c vektor celých čísel typu short int https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd01.c
2 simd02.c ukázka použití vektorů s celočíselnými typy bez znaménka https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd02.c
3 simd03.c ukázka použití vektorů s celočíselnými typy se znaménkem https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd03.c
4 simd04.c paralelní součet celočíselných prvků vektorů https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd04.c
5 simd04B.c úprava pro další datové typy https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd04B.c
6 simd05.c přístup k jednotlivým prvkům vektorů https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd05.c
7 simd05B.c korektnější výpočet počtu prvků vektoru https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd05B.c
8 simd05C.c definice typu vektoru https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd05C.c
9 simd06.c vektor čísel s plovoucí řádovou čárkou https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd06.c
10 simd07.c paralelní součet prvků vektorů (typ float) https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd07.c
11 simd08.c paralelní součet prvků vektorů (typ double) https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd08.c
12 simd09.c překročení délky vektoru https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd09.c
13 simd10.c přístup k jednotlivým prvkům vektorů https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd10.c
14 simd11.c překročení délky vektoru https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd11.c
15 simd12.c dlouhý vektor s 256 bajty https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd12.c
       
16 simd13.c operace součtu pro vektory s celočíselnými prvky rozličné bitové šířky bez znaménka https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd13.c
17 simd14.c operace součtu pro vektory s celočíselnými prvky rozličné bitové šířky se znaménkem https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd14.c
18 simd15.c operace součtu pro vektory s prvky rozličné bitové šířky s plovoucí řádovou čárkou https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd15.c
19 simd16.c operace součtu pro dlouhé vektory s prvky rozličné bitové šířky s plovoucí řádovou čárkou https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd16.c
20 simd17.c všechny podporované binární operace nad vektory s celočíselnými prvky se znaménkem https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd17.c
21 simd18.c všechny podporované binární operace nad vektory s prvky typu float https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd18.c
       
23 intrinsic_mmx1.c intrinsic pro technologii MMX: instrukce paddb https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_mmx1.c
24 intrinsic_mmx2.c intrinsic pro technologii MMX: instrukce paddw https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_mmx2.c
25 intrinsic_mmx3.c intrinsic pro technologii MMX: instrukce paddb (přetečení) https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_mmx3.c
26 intrinsic_mmx4.c intrinsic pro technologii MMX: instrukce paddsb (saturace) https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_mmx4.c
27 intrinsic_mmx5.c intrinsic pro technologii MMX: instrukce pupckhbw (kombinace dvou vektorů) https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_mmx5.c
       
28 intrinsic_sse1.c součet dvou vektorů s šestnácti prvky typu char instrukcí paddb128 https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_sse1.c
29 intrinsic_sse2.c součet dvou vektorů s osmi prvky typu short instrukcí paddw128 https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_sse2.c
30 intrinsic_sse3.c součet dvou vektorů se čtyřmi prvky typu int instrukcí paddd128 https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_sse3.c
31 intrinsic_sse4.c součet dvou vektorů se dvěma prvky typu long instrukcí paddq128 https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_sse4.c
32 intrinsic_sse5.c součet dvou vektorů se čtyřmi prvky typu float instrukcí addps https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_sse5.c
33 intrinsic_sse6.c součet dvou vektorů se dvěma prvky typu double instrukcí addpd https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_sse6.c
34 intrinsic_sse7.c porovnání celočíselných prvků instrukcemi pcmpeqb128 a pcmpgtb128 https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_sse7.c
35 intrinsic_sse8.c všech šest relačních operací pro vektory s prvky typu float https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_sse8.c
36 intrinsic_sse9.c unární operace pro výpočet převrácené hodnoty, druhé odmocniny a převrácené hodnoty druhé odmocniny https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_sse9.c
37 intrinsic_sse_A.c instrukce shufps a její intrinsic https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_sse_A.c
38 intrinsic_sse_B.c instrukce unpckhps a unpcklps a jejich intrinsics https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_sse_B.c
       
39 simd19.c operace součtu vektorů o délce 256 bitů s celočíselnými prvky bez znaménka https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd19.c
40 simd20.c operace součtu vektorů o délce 256 bitů s celočíselnými prvky se znaménkem https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd20.c
41 simd21.c operace součtu vektorů o délce 256 bitů s prvky typu floatdouble https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd21.c
       
42 test_extensions.c test, které instrukční sady mikroprocesor podporuje https://github.com/tisnik/pre­sentations/blob/master/SIM­D/test_extensions.c
43 test_avx512_extensions.c test, které instrukční sady mikroprocesor podporuje, rozšíření o AVX-512 https://github.com/tisnik/pre­sentations/blob/master/SIM­D/test_avx512_extensions
       
44 intrinsic_f16c1.c převod 128bitového vektoru s prvky typu float na half a zpět https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_f16c1.c
45 intrinsic_f16c2.c převod 128bitového vektoru s prvky typu float na half a zpět, zpracování velkých hodnot https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_f16c2.c
46 intrinsic_f16c3.c převod 128bitového vektoru s prvky typu float na half s volbou režimu zaokrouhlení https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_f16c3.c
47 intrinsic_f16c4.c převod 256bitového vektoru s prvky typu float na half a zpět https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_f16c4.c
48 intrinsic_fma3_1.c využití instrukce pro provedení vektorové operace x = a*b+c https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_fma3_1.c
49 intrinsic_fma3_2.c dtto, ale pro odlišné hodnoty https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_fma3_2.c
50 intrinsic_fma3_3.c dtto, ale vynásobení maximálními možnými FP hodnotami https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_fma3_3.c
51 intrinsic_fma3_4.c využití instrukce pro provedení vektorové operace x = -a*b+c https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_fma3_4.c
52 intrinsic_fma3_5.c využití instrukce pro provedení vektorové operace x = a*b-c https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_fma3_5.c
       
53 decode_half_float.c dekódování hodnot s plovoucí řádovou čárkou uložených ve formátu half float https://github.com/tisnik/pre­sentations/blob/master/SIM­D/decode_half_float.c
       
54 intrinsic_avx512_k_registers.c bitové operace s maskovacími registry https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_avx512_k_regis­ters.c
55 intrinsic_avx512_vblendps.c operace typu blend založená na maskovacím registru https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_avx512_vblendps­.c
56 intrinsic_avx512_addps.c operace typu addps s maskováním https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_avx512_addps.c
57 intrinsic_avx512_compress.c operace typu compress s maskováním https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_avx512_compres­s.c
58 intrinsic_avx512_permute.c operace typu permute s maskováním https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_avx512_permute­.c
       
59 Makefile Makefile pro překlad všech výše uvedených demonstračních příkladů https://github.com/tisnik/pre­sentations/blob/master/SIM­D/Makefile

Soubory vzniklé překladem z jazyka C do assembleru procesorů x86–64:

# Příklad Stručný popis Adresa
1 simd04_1.lst překlad zdrojového kódu simd04_1.c s přepínači -O0 -mno-sse -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd04_1.lst
2 simd04_2.lst překlad zdrojového kódu simd04_2.c s přepínači -O0 -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd04_2.lst
3 simd04B1.lst překlad zdrojového kódu simd04B1.c s přepínači -O0 -mno-sse -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd04B1.lst
4 simd04B2.lst překlad zdrojového kódu simd04B2.c s přepínači -O0 -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd04B2.lst
5 simd07_1.lst překlad zdrojového kódu simd07_1.c s přepínači -mno-sse -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd07_1.lst
6 simd07_2.lst překlad zdrojového kódu simd07_2.c s přepínači -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd07_2.lst
7 simd08_1.lst překlad zdrojového kódu simd08_1.c s přepínači -mno-sse -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd08_1.lst
8 simd08_2.lst překlad zdrojového kódu simd08_2.c s přepínači -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd08_2.lst
9 simd12_1.lst překlad zdrojového kódu simd12_1.c s přepínači -O0 -mno-sse -g  https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd12_1.lst
10 simd12_2.lst překlad zdrojového kódu simd12_2.c s přepínači -O0 -g  https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd12_2.lst
11 simd13_1.lst překlad zdrojového kódu simd13_1.c s přepínači -O0 -mno-sse -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd13_1.lst
12 simd13_2.lst překlad zdrojového kódu simd13_2.c s přepínači -O0 -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd13_2.lst
13 simd13_3.lst překlad zdrojového kódu simd13_3.c s přepínači -O3 -mno-sse -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd13_3.lst
14 simd13_4.lst překlad zdrojového kódu simd13_4.c s přepínači -O3 -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd13_4.lst
15 simd14_1.lst překlad zdrojového kódu simd14_1.c s přepínači -O0 -mno-sse -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd14_1.lst
16 simd14_2.lst překlad zdrojového kódu simd14_2.c s přepínači -O0 -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd14_2.lst
17 simd14_3.lst překlad zdrojového kódu simd14_3.c s přepínači -O3 -mno-sse -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd14_3.lst
18 simd14_4.lst překlad zdrojového kódu simd14_4.c s přepínači -O3 -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd14_4.lst
19 simd15_1.lst překlad zdrojového kódu simd15_1.c s přepínači -O0 -mno-sse -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd15_1.lst
20 simd15_2.lst překlad zdrojového kódu simd15_2.c s přepínači -O0 -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd15_2.lst
21 simd15_3.lst překlad zdrojového kódu simd15_3.c s přepínači -O3 -mno-sse -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd15_3.lst
22 simd15_4.lst překlad zdrojového kódu simd15_4.c s přepínači -O3 -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd15_4.lst
23 simd16_1.lst překlad zdrojového kódu simd16_1.c s přepínači -O0 -mno-sse -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd16_1.lst
24 simd16_2.lst překlad zdrojového kódu simd16_2.c s přepínači -O0 -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd16_2.lst
25 simd16_3.lst překlad zdrojového kódu simd16_3.c s přepínači -O3 -mno-sse -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd16_3.lst
26 simd16_4.lst překlad zdrojového kódu simd16_4.c s přepínači -O3 -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd16_4.lst
27 simd17_1.lst překlad zdrojového kódu simd17_1.c s přepínači -O0 -mno-sse -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd17_1.lst
28 simd17_2.lst překlad zdrojového kódu simd17_2.c s přepínači -O0 -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd17_2.lst
29 simd17_3.lst překlad zdrojového kódu simd17_3.c s přepínači -O3 -mno-sse -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd17_3.lst
30 simd17_4.lst překlad zdrojového kódu simd17_4.c s přepínači -O3 -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd17_4.lst
31 simd18_1.lst překlad zdrojového kódu simd18_1.c s přepínači -O0 -mno-sse -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd18_1.lst
32 simd18_2.lst překlad zdrojového kódu simd18_2.c s přepínači -O0 -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd18_2.lst
33 simd18_3.lst překlad zdrojového kódu simd18_3.c s přepínači -O3 -mno-sse -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd18_3.lst
34 simd18_4.lst překlad zdrojového kódu simd18_4.c s přepínači -O3 -g https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd18_4.lst
       
35 intrinsic_mmx1.lst překlad zdrojového kódu intrinsic_mmx1.c https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_mmx1.lst
36 intrinsic_mmx2.lst překlad zdrojového kódu intrinsic_mmx2.c https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_mmx2.lst
37 intrinsic_mmx3.lst překlad zdrojového kódu intrinsic_mmx3.c https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_mmx3.lst
39 intrinsic_mmx5.lst překlad zdrojového kódu intrinsic_mmx5.c https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_mmx5.lst
       
40 intrinsic_sse1.lst překlad zdrojového kódu intrinsic_sse1.c https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_sse1.lst
41 intrinsic_sse2.lst překlad zdrojového kódu intrinsic_sse2.c https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_sse2.lst
42 intrinsic_sse3.lst překlad zdrojového kódu intrinsic_sse3.c https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_sse3.lst
43 intrinsic_sse4.lst překlad zdrojového kódu intrinsic_sse4.c https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_sse4.lst
44 intrinsic_sse5.lst překlad zdrojového kódu intrinsic_sse5.c https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_sse5.lst
45 intrinsic_sse6.lst překlad zdrojového kódu intrinsic_sse6.c https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_sse6.lst
46 intrinsic_sse7.lst překlad zdrojového kódu intrinsic_sse7.c https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_sse7.lst
47 intrinsic_sse8.lst překlad zdrojového kódu intrinsic_sse8.c https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_sse8.lst
48 intrinsic_sse9.lst překlad zdrojového kódu intrinsic_sse9.c https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_sse9.lst
49 intrinsic_sse_A.lst překlad zdrojového kódu intrinsic_sse_A.c https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_sse_A.lst
50 intrinsic_sse_B.lst překlad zdrojového kódu intrinsic_sse_B.c https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_sse_B.lst
       
51 simd19_sse.lst překlad zdrojového kódu simd19.c s přepínačem -msse -mno-avx https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd19_sse.lst
52 simd19_avx.lst překlad zdrojového kódu simd19.c s přepínačem -mavx https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd19_avx.lst
53 simd19_avx2.lst překlad zdrojového kódu simd19.c s přepínačem -mavx2 https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd19_avx2.lst
54 simd20_sse.lst překlad zdrojového kódu simd20.c s přepínačem -msse -mno-avx https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd20_sse.lst
55 simd20_avx.lst překlad zdrojového kódu simd20.c s přepínačem -mavx https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd20_avx.lst
56 simd20_avx2.lst překlad zdrojového kódu simd20.c s přepínačem -mavx2 https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd20_avx2.lst
57 simd21_sse.lst překlad zdrojového kódu simd21.c s přepínačem -msse -mno-avx https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd21_sse.lst
58 simd21_avx.lst překlad zdrojového kódu simd21.c s přepínačem -mavx https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd21_avx.lst
59 simd21_avx2.lst překlad zdrojového kódu simd21.c s přepínačem -mavx3 https://github.com/tisnik/pre­sentations/blob/master/SIM­D/simd21_avx2.lst
       
60 intrinsic_f16c1.lst překlad zdrojového kódu intrinsic_f16c1.c s přepínačem -mf16c https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_f16c1.lst
61 intrinsic_f16c2.lst překlad zdrojového kódu intrinsic_f16c2.c s přepínačem -mf16c https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_f16c2.lst
62 intrinsic_f16c3.lst překlad zdrojového kódu intrinsic_f16c3.c s přepínačem -mf16c https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_f16c3.lst
63 intrinsic_f16c4.lst překlad zdrojového kódu intrinsic_f16c4.c s přepínačem -mf16c https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_f16c4.lst
64 intrinsic_fma3_1.lst překlad zdrojového kódu intrinsic_fma3_1.c s přepínačem -mfma https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_fma3_1.lst
65 intrinsic_fma3_2.lst překlad zdrojového kódu intrinsic_fma3_2.c s přepínačem -mfma https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_fma3_2.lst
66 intrinsic_fma3_3.lst překlad zdrojového kódu intrinsic_fma3_3.c s přepínačem -mfma https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_fma3_3.lst
67 intrinsic_fma3_4.lst překlad zdrojového kódu intrinsic_fma3_4.c s přepínačem -mfma https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_fma3_4.lst
68 intrinsic_fma3_5.lst překlad zdrojového kódu intrinsic_fma3_5.c s přepínačem -mfma https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_fma3_5.lst
       
69 intrinsic_avx512_k_registers.lst překlad zdrojového kódu intrinsic_avx512_k_registers.c s přepínačem -mavx512 https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_avx512_k_regis­ters.lst
70 intrinsic_avx512_vblendps.lst překlad zdrojového kódu intrinsic_avx512_vblendps.c s přepínačem -mavx512 https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_avx512_vblendps­.lst
71 intrinsic_avx512_addps.lst překlad zdrojového kódu intrinsic_avx512_addps.c s přepínačem -mavx512 https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_avx512_addps.lst
72 intrinsic_avx512_compress.lst překlad zdrojového kódu intrinsic_avx512_compress.c s přepínačem -mavx512 https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_avx512_compres­s.lst
73 intrinsic_avx512_permute.lst překlad zdrojového kódu intrinsic_avx512_permute.c s přepínačem -mavx512 https://github.com/tisnik/pre­sentations/blob/master/SIM­D/intrinsic_avx512_permute­.lst

19. Seznam všech předchozích částí tohoto seriálu

  1. Užitečné rozšíření GCC: podpora SIMD (vektorových) instrukcí
    https://www.root.cz/clanky/uzitecne-rozsireni-gcc-podpora-simd-vektorovych-instrukci/
  2. Užitečné rozšíření GCC – podpora SIMD (vektorových) instrukcí: nedostatky technologie
    https://www.root.cz/clanky/uzitecne-rozsireni-gcc-podpora-simd-vektorovych-instrukci-nedostatky-technologie/
  3. Podpora SIMD (vektorových) instrukcí na RISCových procesorech
    https://www.root.cz/clanky/podpora-simd-vektorovych-instrukci-na-riscovych-procesorech/
  4. Podpora SIMD operací v GCC s využitím intrinsic pro nízkoúrovňové optimalizace
    https://www.root.cz/clanky/podpora-simd-operaci-v-gcc-s-vyuzitim-intrinsic-pro-nizkourovnove-optimalizace/
  5. Podpora SIMD operací v GCC s využitím intrinsic: technologie SSE
    https://www.root.cz/clanky/podpora-simd-operaci-v-gcc-s-vyuzitim-intrinsic-technologie-sse/
  6. Rozšíření instrukční sady „Advanced Vector Extensions“ na platformě x86–64
    https://www.root.cz/clanky/rozsireni-instrukcni-sady-advanced-vector-extensions-na-platforme-x86–64/
  7. Rozšíření instrukční sady F16C, FMA a AVX-512 na platformě x86–64
    https://www.root.cz/clanky/rozsireni-instrukcni-sady-f16c-fma-a-avx-512-na-platforme-x86–64/

20. Odkazy na Internetu

  1. GCC documentation: Extensions to the C Language Family
    https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html#C-Extensions
  2. GCC documentation: Using Vector Instructions through Built-in Functions
    https://gcc.gnu.org/online­docs/gcc/Vector-Extensions.html
  3. SSE (Streaming SIMD Extentions)
    http://www.songho.ca/misc/sse/sse­.html
  4. Timothy A. Chagnon: SSE and SSE2
    http://www.cs.drexel.edu/~tc365/mpi-wht/sse.pdf
  5. Intel corporation: Extending the Worldr's Most Popular Processor Architecture
    http://download.intel.com/techno­logy/architecture/new-instructions-paper.pdf
  6. SIMD architectures:
    http://arstechnica.com/ol­d/content/2000/03/simd.ar­s/
  7. Tour of the Black Holes of Computing!: Floating Point
    http://www.cs.hmc.edu/~ge­off/classes/hmc.cs105…/sli­des/class02_floats.ppt
  8. 3Dnow! Technology Manual
    AMD Inc., 2000
  9. Intel MMXTM Technology Overview
    Intel corporation, 1996
  10. MultiMedia eXtensions
    http://softpixel.com/~cwrig­ht/programming/simd/mmx.phpi
  11. AMD K5 („K5“ / „5k86“)
    http://www.pcguide.com/ref/cpu/fam/g5K5-c.html
  12. Sixth Generation Processors
    http://www.pcguide.com/ref/cpu/fam/g6­.htm
  13. Great Microprocessors of the Past and Present
    http://www.cpushack.com/CPU/cpu1.html
  14. Very long instruction word (Wikipedia)
    http://en.wikipedia.org/wi­ki/Very_long_instruction_word
  15. CPU design (Wikipedia)
    http://en.wikipedia.org/wi­ki/CPU_design
  16. Bulldozer (microarchitecture)
    https://en.wikipedia.org/wi­ki/Bulldozer_(microarchitec­ture)
  17. SIMD Instructions Considered Harmful
    https://www.sigarch.org/simd-instructions-considered-harmful/
  18. GCC Compiler Intrinsics
    https://iq.opengenus.org/gcc-compiler-intrinsics/
  19. Scalable_Vector_Extension_(SVE)
    https://en.wikipedia.org/wi­ki/AArch64#Scalable_Vector_Ex­tension_(SVE)
  20. FADD/FADDP/FIADD — Add
    https://www.felixcloutier­.com/x86/fadd:faddp:fiadd
  21. ADDPS — Add Packed Single-Precision Floating-Point Values
    https://www.felixcloutier­.com/x86/addps
  22. ADDPD — Add Packed Double-Precision Floating-Point Values
    https://www.felixcloutier­.com/x86/addpd
  23. FDIV/FDIVP/FIDIV — Divide
    https://www.felixcloutier­.com/x86/fdiv:fdivp:fidiv
  24. IDIV — Signed Divide
    https://www.felixcloutier­.com/x86/idiv
  25. PADDB/PADDW/PADDD/PADDQ — Add Packed Integers
    https://www.felixcloutier­.com/x86/paddb:paddw:paddd:pad­dq
  26. PSUBB/PSUBW/PSUBD — Subtract Packed Integers
    https://www.felixcloutier­.com/x86/psubb:psubw:psubd
  27. PMULLW — Multiply Packed Signed Integers and Store Low Result
    https://www.felixcloutier­.com/x86/pmullw
  28. PUNPCKLBW/PUNPCKLWD/PUNPCKLDQ/PUN­PCKLQDQ — Unpack Low Data
    https://www.felixcloutier­.com/x86/punpcklbw:punpcklwd:pun­pckldq:punpcklqdq
  29. PUNPCKHBW/PUNPCKHWD/PUNPCKHDQ/PUN­PCKHQDQ — Unpack High Data
    https://www.felixcloutier­.com/x86/punpckhbw:punpckhwd:pun­pckhdq:punpckhqdq
  30. PACKUSWB — Pack with Unsigned Saturation
    https://www.felixcloutier­.com/x86/packuswb
  31. ADDPS — Add Packed Single-Precision Floating-Point Values
    https://www.felixcloutier­.com/x86/addps
  32. SUBPS — Subtract Packed Single-Precision Floating-Point Values
    https://www.felixcloutier­.com/x86/subps
  33. MULPS — Multiply Packed Single-Precision Floating-Point Values
    https://www.felixcloutier­.com/x86/mulps
  34. DIVPS — Divide Packed Single-Precision Floating-Point Values
    https://www.felixcloutier­.com/x86/divps
  35. CBW/CWDE/CDQE — Convert Byte to Word/Convert Word to Doubleword/Convert Doubleword to Quadword
    https://www.felixcloutier­.com/x86/cbw:cwde:cdqe
  36. PAND — Logical AND
    https://www.felixcloutier­.com/x86/pand
  37. POR — Bitwise Logical OR
    https://www.felixcloutier.com/x86/por
  38. PXOR — Logical Exclusive OR
    https://www.felixcloutier­.com/x86/pxor
  39. Improve the Multimedia User Experience
    https://www.arm.com/technologies/neon
  40. NEON Technology (stránky ARM)
    https://developer.arm.com/techno­logies/neon
  41. SIMD Assembly Tutorial: ARM NEON – Xiph.org
    https://people.xiph.org/~tte­rribe/daala/neon_tutorial­.pdf
  42. Ne10
    http://projectne10.github.io/Ne10/
  43. NEON and Floating-Point architecture
    http://infocenter.arm.com/hel­p/index.jsp?topic=/com.ar­m.doc.den0024a/BABIGHEB.html
  44. An Introduction to ARM NEON
    http://peterdn.com/post/an-introduction-to-ARM-NEON.aspx
  45. ARM NEON Intrinsics Reference
    http://infocenter.arm.com/hel­p/topic/com.arm.doc.ihi0073a/I­HI0073A_arm_neon_intrinsic­s_ref.pdf
  46. Arm Neon Intrinsics vs hand assembly
    https://stackoverflow.com/qu­estions/9828567/arm-neon-intrinsics-vs-hand-assembly
  47. ARM NEON Optimization. An Example
    http://hilbert-space.de/?p=22
  48. AArch64 NEON instruction format
    https://developer.arm.com/doc­s/den0024/latest/7-aarch64-floating-point-and-neon/73-aarch64-neon-instruction-format
  49. ARM SIMD instructions
    https://developer.arm.com/do­cumentation/dht0002/a/Intro­ducing-NEON/What-is-SIMD-/ARM-SIMD-instructions
  50. Learn the architecture – Migrate Neon to SVE Version 1.0
    https://developer.arm.com/do­cumentation/102131/0100/?lan­g=en
  51. 1.2.2. Comparison between NEON technology and other SIMD solutions
    https://developer.arm.com/do­cumentation/den0018/a/Intro­duction/Comparison-between-ARM-NEON-technology-and-other-implementations/Comparison-between-NEON-technology-and-other-SIMD-solutions?lang=en
  52. NEON Programmer’s Guide
    https://documentation-service.arm.com/static/63299276e68c6809a6b4­1308
  53. Brain Floating Point – nový formát uložení čísel pro strojové učení a chytrá čidla
    https://www.root.cz/clanky/brain-floating-point-ndash-novy-format-ulozeni-cisel-pro-strojove-uceni-a-chytra-cidla/
  54. Other Built-in Functions Provided by GCC
    https://gcc.gnu.org/online­docs/gcc/Other-Builtins.html
  55. GCC: 6.60 Built-in Functions Specific to Particular Target Machines
    https://gcc.gnu.org/online­docs/gcc/Target-Builtins.html#Target-Builtins
  56. Advanced Vector Extensions
    https://en.wikipedia.org/wi­ki/Advanced_Vector_Extensi­ons
  57. AVX-512
    https://en.wikipedia.org/wiki/AVX-512
  58. AVX-512
    https://iq.opengenus.org/avx512/
  59. Downclocking pro AVX-512
    https://en.wikipedia.org/wi­ki/Advanced_Vector_Extensi­ons#Downclocking
  60. BLENDPS — Blend Packed Single Precision Floating-Point Values
    https://www.felixcloutier­.com/x86/blendps
  61. BLENDPD — Blend Packed Double Precision Floating-Point Values
    https://www.felixcloutier­.com/x86/blendpd
  62. Why Intel is betting on BFLOAT16 to be a game changer for deep learning training? Hint: Range trumps Precision
    https://hub.packtpub.com/why-intel-is-betting-on-bfloat16-to-be-a-game-changer-for-deep-learning-training-hint-range-trumps-precision/
  63. half-rs (pro Rust)
    https://github.com/starkat99/half-rs
  64. float16 (pro Go)
    https://github.com/x448/float16
  65. bfloat16 – Hardware Numerics Definition
    https://software.intel.com/en-us/download/bfloat16-hardware-numerics-definition
  66. Intel Prepares To Graft Google’s Bfloat16 Onto Processors
    https://www.nextplatform.com/2019/07/15/in­tel-prepares-to-graft-googles-bfloat16-onto-processors/
  67. A Study of BFLOAT16 for Deep Learning Training
    https://arxiv.org/pdf/1905.12322.pdf
  68. BFloat16s.jl
    https://github.com/JuliaCom­puting/BFloat16s.jl
  69. Half Precision Arithmetic: fp16 Versus bfloat16
    https://nhigham.com/2018/12/03/half-precision-arithmetic-fp16-versus-bfloat16/
  70. bfloat16 floating-point format (Wikipedia)
    https://en.wikipedia.org/wi­ki/Bfloat16_floating-point_format
  71. Unum (number format)
    https://en.wikipedia.org/wi­ki/Unum_(number_format)#Po­sit
  72. Performance Benefits of Half Precision Floats
    https://software.intel.com/en-us/articles/performance-benefits-of-half-precision-floats
  73. Norma IEEE 754 a příbuzní: formáty plovoucí řádové tečky
    https://www.root.cz/clanky/norma-ieee-754-a-pribuzni-formaty-plovouci-radove-tecky/
  74. IEEE-754 Floating-Point Conversion
    http://babbage.cs.qc.cuny.edu/IEEE-754.old/32bit.html
  75. Small Float Formats
    https://www.khronos.org/o­pengl/wiki/Small_Float_For­mats
  76. Binary-coded decimal
    https://en.wikipedia.org/wiki/Binary-coded_decimal
  77. Floating-Point Formats
    http://www.quadibloc.com/com­p/cp0201.htm
  78. Data types (SciPy)
    https://docs.scipy.org/doc/numpy-1.13.0/user/basics.types.html
  79. New 16-bit floating point type – NumPy 1.6.0 Release Notes
    https://github.com/numpy/num­py/blob/7cfec2403486456b52b525ec­cf7541e1562d9ab3/doc/rele­ase/1.6.0-notes.rst#new-16-bit-floating-point-type
  80. RFC pro Rust
    https://github.com/joshtri­plett/rfcs/blob/f16b/text/0000-f16b.md
  81. IEEE-754 Floating Point Converter
    https://www.h-schmidt.net/FloatConverter/I­EEE754.html
  82. Mediump float calculator
    https://oletus.github.io/float16-simulator.js/
  83. IEEE 754 Calculator
    http://weitz.de/ieee/
  84. BFloat16 (Swift for TensorFlow)
    https://www.tensorflow.or­g/swift/api_docs/Structs/BFlo­at16
  85. Using bfloat16 with TensorFlow models
    https://cloud.google.com/tpu/doc­s/bfloat16
  86. What is tf.bfloat16 “truncated 16-bit floating point”?
    https://stackoverflow.com/qu­estions/44873802/what-is-tf-bfloat16-truncated-16-bit-floating-point
  87. BFloat16 processing for Neural Networks on Armv8-A
    https://community.arm.com/developer/ip-products/processors/b/ml-ip-blog/posts/bfloat16-processing-for-neural-networks-on-armv8_2d00_a
  88. Mixed precision training
    https://arxiv.org/pdf/1710.03740.pdf
  89. [R] Mixed Precision Training
    https://www.reddit.com/r/Machi­neLearning/comments/75phd2/r_mi­xed_precision_training/
  90. Floating Point Numbers
    https://floating-point-gui.de/formats/fp/
  91. Float exposed
    https://float.exposed/0×40490000
  92. Float Toy
    http://evanw.github.io/float-toy/
  93. IEEE-754 visualization
    https://bartaz.github.io/ieee754-visualization/
  94. Advantages Of BFloat16 For AI Inference
    https://semiengineering.com/advantages-of-bfloat16-for-ai-inference/
  95. ARMv8-A bude podporovat nový formát čísel BFloat16
    https://www.root.cz/zpravicky/armv8-a-bude-podporovat-novy-format-cisle-bfloat16/
  96. Intel oznámil nový formát BFloat16 pro budoucí procesory
    https://www.root.cz/zpravicky/intel-oznamil-novy-format-bfloat16-pro-budouci-procesory/
  97. Nový formát čísel Intelu BFloat16 bude v GCC 10 a Clang 9
    https://www.root.cz/zpravicky/novy-format-cisel-intelu-bfloat16-bude-v-gcc-10-a-clang-9/
  98. Mixed precision
    https://www.tensorflow.or­g/guide/keras/mixed_preci­sion
  99. Training Performance: A user’s guide to converge faster (TensorFlow Dev Summit 2018)
    https://www.youtube.com/wat­ch?v=SxOsJPaxHME
  100. Programování GPU na Raspberry Pi: použití Quad Processor Unit(s)
    https://www.root.cz/clanky/pro­gramovani-gpu-na-raspberry-pi-pouziti-quad-processor-unit-s/
  101. “Half Precision” 16-bit Floating Point Arithmetic
    https://blogs.mathworks.com/cle­ve/2017/05/08/half-precision-16-bit-floating-point-arithmetic/
  102. Half Precision Arithmetic in Numerical Linear Algebra
    https://nla-group.org/2018/10/03/half-precision-arithmetic-in-numerical-linear-algebra/
  103. Enable BF16 support
    https://gcc.gnu.org/ml/gcc-patches/2019–04/msg00477.html
  104. Survey of Floating-Point Formats
    https://mrob.com/pub/math/flo­atformats.html
  105. VCVTPS2PH — Convert Single-Precision FP value to 16-bit FP value
    https://www.felixcloutier­.com/x86/vcvtps2ph
  106. VCVTPH2PS — Convert 16-bit FP values to Single-Precision FP values
    https://www.felixcloutier­.com/x86/vcvtph2ps
  107. KMOV
    https://www.felixcloutier­.com/x86/kmovw:kmovb:kmov­q:kmovd
  108. KNOT
    https://www.felixcloutier­.com/x86/knotw:knotb:knot­q:knotd
  109. KAND
    https://www.felixcloutier­.com/x86/kandw:kandb:kandq:kan­dd
  110. KANDN
    https://www.felixcloutier­.com/x86/kandnw:kandnb:kan­dnq:kandnd
  111. KOR
    https://www.felixcloutier­.com/x86/korw:korb:korq:kord
  112. KXOR
    https://www.felixcloutier­.com/x86/kxorw:kxorb:kxor­q:kxord
  113. KXNOR
    https://www.felixcloutier­.com/x86/kxnorw:kxnorb:kxnor­q:kxnord
  114. KORTEST
    https://www.felixcloutier­.com/x86/kortestw:kortestb:kor­testq:kortestd
  115. KSHIFTL
    https://www.felixcloutier­.com/x86/kshiftlw:kshiftlb:kshif­tlq:kshiftld
  116. KSHIFTR
    https://www.felixcloutier­.com/x86/kshiftrw:kshiftrb:kshif­trq:kshiftrd
  117. KUNPCK
    https://www.felixcloutier­.com/x86/kunpckbw:kunpckwd:kun­pckdq
  118. VBLENDMPD
    https://www.felixcloutier­.com/x86/vblendmpd:vblendmps
  119. VBLENDMPS
    https://www.felixcloutier­.com/x86/vblendmpd:vblendmps
  120. VPBLENDMD
    https://www.felixcloutier­.com/x86/vpblendmd:vpblen­dmq
  121. VPBLENDMQ
    https://www.felixcloutier­.com/x86/vpblendmd:vpblen­dmq
  122. VPTESTMB/VPTESTMW/VPTESTMD/VPTESTMQ
    https://www.felixcloutier­.com/x86/vptestmb:vptestmw:vptes­tmd:vptestmq
  123. VPCMPD/VPCMPUD
    https://www.felixcloutier­.com/x86/vpcmpd:vpcmpud
  124. VPCMPQ/VPCMPUQ
    https://www.felixcloutier­.com/x86/vpcmpq:vpcmpuq
  125. VCOMPRESSPD
    https://www.felixcloutier­.com/x86/vcompresspd
  126. VCOMPRESSPS
    https://www.felixcloutier­.com/x86/vcompressps
  127. VPCOMPRESSQ
    https://www.felixcloutier­.com/x86/vpcompressq
  128. VPCOMPRESSD
    https://www.felixcloutier­.com/x86/vpcompressd
  129. VEXPANDPD
    https://www.felixcloutier­.com/x86/vexpandpd
  130. VEXPANDPS
    https://www.felixcloutier­.com/x86/vexpandps
  131. VPEXPANDD
    https://www.felixcloutier­.com/x86/vpexpandd
  132. VPEXPANDQ
    https://www.felixcloutier­.com/x86/vpexpandq
  133. VPERMI2PD
    https://www.felixcloutier­.com/x86/vpermi2w:vpermi2d:vper­mi2q:vpermi2ps:vpermi2pd
  134. VPERMI2PS
    https://www.felixcloutier­.com/x86/vpermi2w:vpermi2d:vper­mi2q:vpermi2ps:vpermi2pd
  135. VPERMI2D
    https://www.felixcloutier­.com/x86/vpermi2w:vpermi2d:vper­mi2q:vpermi2ps:vpermi2pd
  136. VPERMI2Q
    https://www.felixcloutier­.com/x86/vpermi2w:vpermi2d:vper­mi2q:vpermi2ps:vpermi2pd
  137. VPERMT2PD
    https://www.felixcloutier­.com/x86/vpermt2w:vpermt2d:vper­mt2q:vpermt2ps:vpermt2pd
  138. VPERMT2PS
    https://www.felixcloutier­.com/x86/vpermt2w:vpermt2d:vper­mt2q:vpermt2ps:vpermt2pd
  139. VPERMT2D
    https://www.felixcloutier­.com/x86/vpermt2w:vpermt2d:vper­mt2q:vpermt2ps:vpermt2pd
  140. VPERMT2Q
    https://www.felixcloutier­.com/x86/vpermt2w:vpermt2d:vper­mt2q:vpermt2ps:vpermt2pd
  141. VSHUFF32×4
    https://www.felixcloutier­.com/x86/vshuff32×4:vshuf­f64×2:vshufi32×4:vshufi64×2
  142. VSHUFF64×2
    https://www.felixcloutier­.com/x86/vshuff32×4:vshuf­f64×2:vshufi32×4:vshufi64×2
  143. VSHUFI32×4
    https://www.felixcloutier­.com/x86/vshuff32×4:vshuf­f64×2:vshufi32×4:vshufi64×2
  144. VSHUFI64×2
    https://www.felixcloutier­.com/x86/vshuff32×4:vshuf­f64×2:vshufi32×4:vshufi64×2
  145. VPDPBUSD
    https://www.felixcloutier­.com/x86/vpdpbusd
  146. VPDPBUSDS
    https://www.felixcloutier­.com/x86/vpdpbusds
  147. VPDPWSSD
    https://www.felixcloutier­.com/x86/vpdpwssd
  148. VPDPWSSDS
    https://www.felixcloutier­.com/x86/vpdpwssds

Byl pro vás článek přínosný?