Intel vydal 41 upozornění na bezpečnostní chyby ve svých produktech. Současně vydal verzi 20240514 mikrokódů pro své procesory řešící INTEL-SA-01051, INTEL-SA-01052 a INTEL-SA-01036.
Společnost Raspberry Pi patřící nadaci Raspberry Pi chystá IPO a vstup na Londýnskou burzu.
Google na své vývojářské konferenci Google I/O 2024 představil řadu novinek. Keynote byl věnován umělé inteligenci (DeepMind, Gemini, Responsible AI).
V Gitu bylo nalezeno 5 zranitelností. Opraveny jsou ve verzích 2.45.1, 2.44.1, 2.43.4, 2.42.2, 2.41.1, 2.40.2 a 2.39.4. Útočník může připravit repozitář tak, že při jeho klonování (git clone) může dojít ke spuštění libovolného kódu.
Virtualizační softwary VMware Workstation Pro a VMware Fusion Pro jsou nově pro osobní použití zdarma. Softwary VMware Workstation Player a VMware Fusion Player končí.
Linuxová distribuce Endless OS (Wikipedie) byla vydána ve verzi 6.0.0. Přehled novinek i s náhledy v příspěvku na blogu, poznámkách k vydání a také na YouTube.
Byl vydán Mozilla Firefox 126.0. Přehled novinek v poznámkách k vydání, poznámkách k vydání pro firmy a na stránce věnované vývojářům. Vylepšena byla funkce "Zkopírovat odkaz bez sledovacích prvků". Přidána byla podpora zstd (Zstandard). Řešeny jsou rovněž bezpečnostní chyby. Nový Firefox 126 je již k dispozici také na Flathubu a Snapcraftu.
Grafana (Wikipedie), tj. open source nástroj pro vizualizaci různých metrik a s ní související dotazování, upozorňování a lepší porozumění, byla vydána ve verzi 11.0. Přehled novinek v aktualizované dokumentaci.
Byla vydána nová verze 24.0 linuxové distribuce Manjaro (Wikipedie). Její kódové jméno je Wynsdey. Ke stažení je v edicích GNOME, KDE PLASMA a XFCE.
Byla představena oficiální rozšiřující deska Raspberry Pi M.2 HAT+ pro připojování M.2 periferii jako jsou NVMe disky a AI akcelerátory k Raspberry Pi 5. Cena je 12 dolarů.
o tomto som tiez pisal blog pred 3 rokmi, ked som sa k tomu dostal niekde cez reddit.Občas se vracím k tématům, o kterých jsme už v Receptáři hovořili. Není divu, každý se nemůže dívat na všechny pořady. Tak třeba paní Emilie Bezoušková...
implementovane to je v tree-tailcall.cDiky za info, presne tohle jsem chtel vedet. Cekal jsem, ze to bude sofistikovanejsi a vychazet primo z vnitrni SSA reprezentace.
ale podla standardu sa na to neda spoliehat (a to prekvapivo ani v common lispe)V CommonLispu se podle standardu neda spolehat ani na ty tail cally.
a v jiných jazycích to tolik nevadí, protože se o to postarají prostředky samotného jazyka i bez optimalizace.V některých jazycích to jde vypnout – zejména kvůli ladění (např. v F#, k němuž se vztahovala původní diskuze).
Je sice hezké, že překladač je dost chytrý na to, aby sám převáděl rekurze na cykly, ale když se objeví nějaké chybky, tak skutečnost, že neoptimalizovaný kód, který používá k ladění, se silně liší od optimalizovaného, může být za určitých okolností docela prolbematická...To ano, ovšem v GCC by mělo jít nějakým CFLAG zapnout jednu konkrétní optimalizaci, ne? Případně by mělo jít debugovat optimalizovaný kód apod...
PS: Ty oprefixované NOPy (obvlášť ten v poslední verzi vygenerované přes -O3) mně dostalyKvůli čemu tam je? Zarovnání? Jinak jednoduché NOPy se afaik nevidí už vlastně nikdy (na x86), pokud najdeš v binárce jednoduché NOPy, nejspíš se v ní někdo hrabal
Kvůli čemu tam je? Zarovnání?Jo, kvuli zarovnani. AMD64 ma instrukcni cache o velikosti 16B, takze ma rado, kdyz jsou skoky zarovnane na 16B. Teoreticky by mely jit pouzit slozitejsi NOP i pro prefetch, ale na to mi prijde rozumnejsi pouzit primo instrukce prefetchX z SSE.
AMD64 ma instrukcni cache o velikosti 16BJako velikost jednoho cacheline?
Ty oprefixované NOPy (obvlášť ten v poslední verzi vygenerované přes -O3) mně dostalyOn je zajímavej i ten "repz ret". Tipoval bych to na ten prefetch jak psal deda.jabko. Pro ostatní co neví (): "rep" je prefix cyklu a "ret" je návrat, takže tipuju, že mikrokód si při "rep" myslí, že nastane cyklus a další instrukci po "ret" nenačte, což je výhoda, protože se stejně bude skákat pryč (pro ty co ví: jak moc jsem se seknul? ). Jinak ona je x86 tak šílená, že jí jednak nestačej volný hodnoty pro nový opkód a jednak se používaj různý kombinace i pro další věci. Například instrukce pause, což je vlastně jen sekvence dříve přeložitelná jako "rep nop". V Intelu to dělali už od začátku, schválně kdo bez internetu uhodne, co dělal původně na 80(1)86 opkód 0x0f (od zavedení chráněného módu jako prefix pro nové instrukce)? Jinak podobné legrácky, co používá kompilátor, jsou popsané taky tady.
Jakó... To mi zní dost jako černá magie. Evidentně udělaly optimalizační metody v překladačích kus cesty kupředu od dob, kdy nás o nich nesměle učili, jak jakože umí třeba občas za vhodnej okolností vytáhnout mimo cyklus invariant... :)
Což o to, pokrok jde kupředu, ale todle mi přijde už fakt jako hodně moc. To je skoro jako kdyby ten překladač věděl, že počítáte faktoriál a prostě to celé udělal jinak, lépe a radostněji. Myslím tu poslední verzi. To mi jako někdo vysvětlete, jak todle pozná. Pochopit co dělá cizí zdroják je kolikrát problém pro člověka, ne tak pro stroj... :D
To je skoro jako kdyby ten překladač věděl, že počítáte faktoriál a prostě to celé udělal jinak, lépe a radostněji.A za chvíli ti řekne, aby sis s tou vázou nedělal starosti Ne, váženě, ten překladač neví, že počítáš faktoriál, ale ví, že něco cyklicky děláš pomocí tail callu, a tak to převede to na cyklus. Převádět rekurzi na cyklus a naopak jsme se učili někdy v druháku na střední v Packalu, takže jsem si jist, že pro moderní překladač to není problém....
Ne, váženě, ten překladač neví, že počítáš faktoriál, ale ví, že něco cyklicky děláš pomocí tail callu,Vtip je v tom, ze v tom prikladu neni pouzity tail call, a presto to prekladac dokazal prelozit jako cyklus.
tree-tailcall.c
.
V kostce: on pracuje s tail callem ve tvaru (obecně) return a + m * func(...);
, kde a
ani m
nezávisí na výsledku toho tail volání. Předeve to na cyklus s akumulátory (zvlášť pro aditivní a multiplikativní proměnnou podle potřeby). Klasický tail call (tedy return func(...);
) je pouze specielním případem, kdy a = 0
, m = 1
, tedy bez akumulátoru.
Chytrej trik.
let rec map mapper = function | [] -> [] | x::xs -> mapper x :: (map mapper xs)tento map sa prelozi ako cyklus:
let map mapper list = let rec map mapper acc = function | [] -> acc | x::xs -> xs |> map mapper (mapper x :: acc) list |> map mapper [] |> List.rev
tento map sa prelozi ako rekurzia, pri velkych zoznamoch hrozi stackoverflow:Záleží na sémantice a implementaci. Např. v GHC Haskellu by byla preferována první verze.
tento map sa prelozi ako cyklus:Bohužel toto řešení není příliš efektivní a ani přehledné.
let rec map1 mapper = function | [] -> [] | x::xs -> mapper x :: (map1 mapper xs) let map2 mapper list = let rec map mapper acc = function | [] -> acc | x::xs -> map mapper (mapper x :: acc) xs List.rev (map mapper [] list) let map3 mapper list = let rec map3 cnt mapper = function | [] -> cnt [] | x::xs -> map3 (fun l -> cnt (mapper x :: l)) mapper xs map3 id mapper listPodľa môjho testu:
List.map
. Pro OCaml jsou nějaká měření v článku Optimizing List.map.
00000000 <fact_rec>: 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 83 ec 18 sub $0x18,%esp 6: 83 7d 08 00 cmpl $0x0,0x8(%ebp) a: 75 07 jne 13 <fact_rec+0x13> c: b8 01 00 00 00 mov $0x1,%eax 11: eb 10 jmp 23 <fact_rec+0x23> 13: 8b 45 08 mov 0x8(%ebp),%eax 16: 48 dec %eax 17: 89 04 24 mov %eax,(%esp) 1a: e8 fc ff ff ff call 1b <fact_rec+0x1b> 1f: 0f af 45 08 imul 0x8(%ebp),%eax 23: c9 leave 24: c3 ret-O1
00000000 <fact_rec>: 0: 53 push %ebx 1: 83 ec 18 sub $0x18,%esp 4: 8b 5c 24 20 mov 0x20(%esp),%ebx 8: 85 db test %ebx,%ebx a: 74 10 je 1c <fact_rec+0x1c> c: 8d 43 ff lea -0x1(%ebx),%eax f: 89 04 24 mov %eax,(%esp) 12: e8 fc ff ff ff call 13 <fact_rec+0x13> 17: 0f af c3 imul %ebx,%eax 1a: eb 05 jmp 21 <fact_rec+0x21> 1c: b8 01 00 00 00 mov $0x1,%eax 21: 83 c4 18 add $0x18,%esp 24: 5b pop %ebx 25: c3 ret-O2
00000000 <fact_rec>: 0: 8b 54 24 04 mov 0x4(%esp),%edx 4: b8 01 00 00 00 mov $0x1,%eax 9: 85 d2 test %edx,%edx b: 74 0a je 17 <fact_rec+0x17> d: 8d 76 00 lea 0x0(%esi),%esi 10: 0f af c2 imul %edx,%eax 13: 4a dec %edx 14: 75 fa jne 10 <fact_rec+0x10> 16: c3 ret 17: c3 ret-O3 == -O2 -Os
00000000 <fact_rec>: 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 8b 55 08 mov 0x8(%ebp),%edx 6: b8 01 00 00 00 mov $0x1,%eax b: 85 d2 test %edx,%edx d: 74 06 je 15 <fact_rec+0x15> f: 0f af c2 imul %edx,%eax 12: 4a dec %edx 13: eb f6 jmp b <fact_rec+0xb> 15: 5d pop %ebp 16: c3 ret
00000000 <fact_rec>: 0: 8b 54 24 04 mov 0x4(%esp),%edx 4: b8 01 00 00 00 mov $0x1,%eax 9: 85 d2 test %edx,%edx b: 74 0d je 1a <fact_rec+0x1a> d: 8d 76 00 lea 0x0(%esi),%esi 10: 0f af c2 imul %edx,%eax 13: 83 ea 01 sub $0x1,%edx 16: 75 f8 jne 10 <fact_rec+0x10> 18: f3 c3 repz ret 1a: f3 c3 repz retKromě přidání těch repz (slackware default je i486) se změnil "dec" na "sub" (zajímavý, sub má delší opkód). Ještě zajímavější je ten "lea", což je jestli se nepletu taky jen "nop".
Tiskni Sdílej: