Kompilátor C++ nemá o kódu tolik informací jako kompilátor Rustu, jazyka navrženého pro podchycení různých problémů už v době komplikace. Proto má méně možností k optimalizaci (i nesmyslný záměr v kódu musí být správně proveden).
EDIT: Věřit nemusíte, ale oni mají výsledky svých měření černě na bílém.
26. 4. 2023, 15:46 editováno autorem komentáře
U kernelu bych jim to i věřil. Problém je v tom, že v MS jedna ruka neví, co dělá ta druhá a jakékoliv zlepšení výkonu na nižších úrovních se daří dokonale vykrátit, ne-li obrátit naprostými kopičinami v user space.
Ono je sice hezký, že přepisují window manager v Rustu, ale pokud vzápětí někdo, nejlépe nějaký diversity hire, do shellu hodí widgety v Electronu, tak to nakonec příjde vniveč.
27. 4. 2023, 16:28 editováno autorem komentáře
bez prezdivky ...> Ten nade mnou ti to vysvětlil. Koneckonců kvalita kódu kernelspace/userspace je dost rozdílná i v Linuxu (lowlevel funkce vs. desktopová prostředí a grafické aplikace).
> Ryuzaki: Ono je sice hezký, že přepisují window manager v Rustu, ale pokud vzápětí někdo, nejlépe nějaký diversity hire, do shellu hodí widgety v Electronu, tak to nakonec příjde vniveč.
Proto si lidi vracejí původní Command Prompt, Notepad, Taskbar, Kalkulačku, ... Startují okamžitě a nemají specifické problémy (např. všemu novému ve Windows 11, včetně např Správce úloh, se rozhodí rozměry oken při přecházení mezi různými DPI, např. notebook doma a RDP na PC v práci).
Legendární notepad běží na všem a bez problémů... to samé HxD editor... můžeš klidně napsat číselně v notepadu a on to otevře bez problémů... a napříč rokama nic se nezměnilo, můžeš stále přečíst data..
Teď se podíváme na Word.. Po 10 letech potebuješ otevřít důležitý soubor a zjistit co je v tom uložené.. .A jo ono to nejde... Ale neee, půlka se ztratila, velkou část nelze přečist... Nelze najít font, který byl v minulém Win zcela běžný...
Ve finále zjištíš, že starý word co byl na Vistách a 7-čkách, je dodnes nepřekonatelný ve všem...
Jejich výsledek ale nepotvrzuje váš předpoklad, že je to kvůli kompilátoru/vlastnostem Rustu. Stejně tak to mohli přepsat do moderního C/C++ a možná by to dopadlo stejně. Kdo ví? Každopádně s Rustem mají víc paměťových garancí. Čas ukáže, jestli to byl krok správným směrem.
27. 4. 2023, 09:48 editováno autorem komentáře
Tak já ti to objasním. Spor byl o tom, že přepis do moderního C/C++ by možná přinesl stejnou míru zrychlení a očisty. Že to přepsali do Rustu, je jejich volba a možná zcela správná, ale magické zrychlení kvůli Rustu je dosti sporné tvrzení.
C a C++ jsou dnes zcela odlišné jazyky s nějakou rozumnou mírou spolupráce, kde C je samozřejmě v mnoha ohledech lehčí co se týká syntaxe i sémantiky jazyka. S ohledem na to, že Windows jsou psané spíše v předpotopním C a další věci v předpotopním C++, tak by si mohli vybrat.
" Pojďme se pobavit o užitečných informacích, ale až nějaké přineseš." To tady určuješ ty?
28. 4. 2023, 12:32 editováno autorem komentáře
Já mám pocit, že ty jsi nějak odtržen od reality a diskuze. Původní tvrzení bylo, že Rust může dělat různé optimalizace a jejich zvýšení rychlosti je toho důsledkem. Co jsem psal já ale další je, že tohle se tvrdit nedá. Když něco přepíšeš po 40 letech a přeložíš namísto msvc pomocí llvm, tak zrychlení může být někde jinde než ve volbě jazyka -- čistčí návrh, lepší kompilátor (?). Tak jsi si mohl úplně odpustit to odplivnutí na "moderní C" a nemusel ses tady točit na pětníku.
28. 4. 2023, 15:24 editováno autorem komentáře
Je toho mnohem víc. Pro začátek bych se vyvaroval názvu C/C++ a vůbec spojování C a C++. Moderní C se nijak zvlášť neliší od klasického, kromě toho, že v roce 2011 přibyla do standardní knihovny podpora vláken. Moderní C++ dejme tomu od verze z roku 2017 už toho umí docela dost nějak civilizovaně vyjádřit, ale s Rustem je to naprosto nesrovnatelné.
Rust nemá jen garance neporušení paměti, ale i hromadu dalších garancí, které umožňují další optimalizace. C++ přidává do kódu obrovské množství zcela zbytečných operací, které pak horko těžko při optimalizacích zase vyhazuje. Rust spoustu věcí nemusí díky pečlivě navrženému datovému modelu vůbec řešit.
Z toho lze usuzovat, že Rust se bude v optimalizaci mnohem snadněji i do budoucna zlepšovat. Není s ním tolik práce. Je mnohem víc value-oriented než C++. Tak uvidíme, co z toho ještě vyplyne.
Pavel Šimerda
Ono přepisovat kód (klidně do stejného jazyka ve vyšší verzi) obecně má výhodu, že člověk na to koukne z nové perspektivy a zkušeností. To pravděpodobně mělo větší význam než "jiný kompilátor". Zlí jazykové dokonce říkají, že každý program po úspěšném napsání a otestování, by se měl zahodit, napsat znovu a pak je teprve dobrý.
Rust není v principu rychlejší než C, C++ nebo třeba Go. Rychlost ale ovlivňuje hodně faktorů, i kdyby byl ten přepis 1:1, tak například použitý alokátor apod. Bez podrobnějších informací to nejde posoudit. Navíc po tak dlouhé době bych čekal, že šlo spíše o refaktoring, včetně například použití lepších algoritmů, co my víme.
Rust je v principu rychlejší než C/C++, protože Rust řeší problémy s aliasingem, kterými trpí C/C++. Borrow checker v Rustu zaručuje, že existuje pouze jedna mutable reference na objekt, v C/C++ tato garance není.
Rust překladač nemusí invalidovat žádné proměnné v registrech při zápisu přes referenci (pointer). V Rustu je zaručeno, že mutable reference není aliasem na žádný jiný objekt.
C/C++ překladač musí při zápisu přes pointer invalidovat všechny proměnné stejného typu v registrech a znovu je načíst z paměti. C/C++ se to snaží řešit pomocí strict aliasing rule a restrict keyword, ale to je jen polovičaté řešení, v Rustu je to prostě navržené lépe a funguje to i bez obezliček typu restrict keyword.
To ovšem přinese v typickém program zrychlení nula nula nic, význam to má jen u numerických výpočtů apod. Nehledě na to, že to překladač Rustu ne vždy používá, podle verze překladače a verze LLVM to občas vypínají (protože “miscompiled code”). Takže teorie hezká, ale vesměs na<math>imag(log(-1))</math>kaču.
To je nesmysl, co píšeš, každý program zapisuje do paměti, nejenom při numerických výpočtech.
Oni to mají narozdíl od tvých dojmů změřené, podle typu benchmarku je nárůst výkonu 0 až 5%: https://github.com/rust-lang/rust/issues/54878
To je nárůst výkonu "zadarmo", programátor nemusí nic dělat, nemusí řešit strict aliasing rule (a jestli ho náhodou neporušuje), nemusí nikde psát restrict jako v C/C++. Všechno za něj narozdíl od C/C++ zajistí Rust překladač.
Ano bylo to občas vypnuté, ale problém nebyl v Rustu, ale v LLVM. Tu miskompilaci se vždy podařilo navodit i v ekvivalentním C kódu. V C kódu na to nikdo nepřišel, protože se restrict v C používá minimálně, nikdo to ručně nepíše. Překladač Rustu to automaticky nacpe všude.
Blábolíš. Nárůst o 5% může nastat v "tight loops" (proto je ostatně třeba Fortran ve své doméně rychlejší než C), ale v běžných algoritmech ten noalias vcelku nic nepřináší (nad rámec stat. chyby). Nicméně to je Microsoftu zřejmě ukradené, je zajímá (paměťová) bezpečnost. Případné zrychlení je důsledkem širších změn (refaktoring, lepší algoritmy, lepší návrh architektury apod.).
lol ... jak rekl predecnik, blabolis. C je velice primocary jazyk, a prekladac (vicemene) vygeneruje presne to, co programator napise. Jakykoli slozitejsi jazyk (C++ neni C) ale pochopitele i ten rust, je zakonite pomalejsi.
Opak muze nastat vyhradne v situaci, kdy kod pise prase. A protoze tech prasat je driva vetsina ... tak potrebuji rust, aby za ne resil to, ze neumi napsat kod. Coz samozrejme naprosto jednoznacne vygeneruje prakticky vzdy pomalejsi vysledek, nez to, co napise clovek ktery vi co dela.
Bavit se o vykonu naprosto cehokoli u win nedava vubec zadny smys. Win11 maji zcela jiste (o neco) rychlejsi taskbar ... neni se co divit, kdyz tam 90% funcionality toho z W10 neni.
Ještě jednou pro ty pomalejší. Ve většině případů se nic neinvaliduje, protože nikde v registrech není ukazatel stejného typu. Restrict je v C pro úzkou skupinu konstrukcí (nebo řekněme algoritmů), kde přináší znatelně lepší výkon. Chci počítat nějakou numerickou úlohu z mechaniky tekutin? Pak je noalias super. Ve většině kódu ale o rychlosti rozhoduje efektivita dynamického dispatche (tady Rust zrovna nezáří), alokátoru etc.
To je právě tvůj hluboký omyl a neznalost, když si myslíš, že restrict jen pro úzkou skupinu konstrukcí. Navíc se nejedná o ukazatele v registrech, jak chybně píšeš, ale HODNOTY proměnných po dereferenci v registrech.
Restrict funguje i na tuto jednoduchou konstrukci:
void f(int *a, int *b, int *x)
{
*a += *x;
*b += *x;
}
Co s tím udělá restrict a proč to zrychlí včetně assembleru z gcc najdeš na zde: https://stackoverflow.com/a/30827311
To je ale úplně nezajímavé, ten C/C++ compiler prostě udělá to co mu řekneš, stačí přidat jeden řádek a udělá to jinak...
int value = *x; *a += value; *b += value;
Jo, může tam být aliasing, člověk může použít restrict, atd... ale prostě toto není v 99% případech problém - a tam kde to je problém se to dá řešit. Kde to začíná být zajímavé je autovektorizace a SIMD, připadně automatického použití gather/scatter při kompilaci pro AVX-512 target, atd... ale v tomto případě je lepší to celé napsat pro AVX-512 protože compiler je stejně nechopný a nějaký restrict tomu nepomůže...
Mimochodem, compiler klidně může vygenerovat 2 větvě - jedna se použije při aliasingu a druhá optimalizovaná v opačném případě. Myslím, že zrovna clang to umí, ale nevím jakou na to má heuristiku, protože asi to člověk nechce všude...
Takže si to zrekapitulujme. Abych tosáhli toho, že se výkon C/C++ kódu přiblíží Rustu (jinak bude nižší), tak musíme mít:
Co z toho musím dělat v Rustu? Nic. V Rustu tohle všechno udělá překladač a udělá to správně. V Rustu je úplně všechno restrict automaticky, to je zaručeno borrow checkerem.
Sorry, ale nějak mi z toho nic dobrého pro výkon ani udržovatelnost C/C++ kódu nevychází...
Pamatuju si ze jsem resil bug v ANTLR. Java byla 2x rychlejsi nez Ccko anebo C++. A pritom to C++ pouzivalo brutalni metaprogramovani vcetne inline virtualnich funkci. Nakonec se ukazalo ze:
- Hashovani v Jave je ruchlejsi nez custom hash fce v Cecku
- V obrovskem C++ kodu je tezke uhlidat kolikrat se predava string referenci a kolikrat se kopiruje.
- Nejvetsi problem byl ale v tom, ze jsem musel vymenit podminku: "if(a() && b)" za if(b && a()).
Stacila jedna jedina radka a cely kod v C++ ze zrychlil 5x.
Problém už je v tom původním tvrzení, že kód v rustu je o 15% rychlejší než ekvivalent v C++. Jenže nikdo už nenapsal o jaký konkrétní kód se jedná, jaký compiler byl použitý, a jestli se opravdu jednalo o ekvivalentní kód. Takže spíš by se dalo napsat, že LLVM v tomto konkrétním případě vygeneruje o 15% rychlejší kód než MSVC, kterým určitě kompilujou ten kód v C++. Nějak nevěřím, že na kompilaci Windows komponent používají clang.
To je jak ty benchmarky na Phoronixu, kdy se pro Windows použije MSVC compiler a pro Linux Clang, a pak se dělají závěry, který OS je rychlejší...
Navíc když už někdo něco přepisuje, tak je velká šance udělat to líp, což může znamenat i rychlejší výsledný kód.
27. 4. 2023, 22:00 editováno autorem komentáře
Jde o jejich konkrétní ekvivalentní kód konkrétní aplikace/knihovny. Samozřejmě pokud je kód beze změny, tak není důvod ho překompilovávat, tj. ta procenta obsahují v sobě vylepšení kompilátorů za tu dobu, to ano. Nicméně i tak jde o zlepšení - výhody bezpečí Rustu *a přesto* to není pomalejší (a v rámci příležitosti měli důvod to překompilovat). Jinak Visual Studio nabízí i LLVM/clang, možná dokonce od nějaké verze defaultně?
"Trochu" víc, tohle není Apple. Navíc se sníží výdrž baterie na polovinu, na úroveň strojů s x86 (které zas nabízí kompatibilitu). Emulace ve Windows je totiž nekonečnou smyčkou vytěžující CPU na 100 % (stačí tedy mít trvale spuštěn jeden x86 program). Na Applu (Rosetta 2 pro macOS a Linux) a Alphě (FX!32) se program zkompiluje (Ahead-of-Time) do cílové architektury, takže vlastně spouštíš nativní binárku (ta samozřejmě běží o něco pomaleji než nativní program, protože jsou do kódu generované různé pomocné instrukce). Na Itaniu nevím, jak to funguje.
Dobrý na Windows a Apple je, že systémové knihovny se používají nativní. Aktuální podoba qemu-user na Linuxu emuluje i systémové knihovny (musíš mít nainstalovanou jejich x86 verzi, takže dokonce zabírá víc na disku; řešení je rozpracované a zatím v nedohlednu - nicméně funguje tam Rosetta 2, chybějící přepínač CPU pro strong memory model x86 lze obejít tím, že všechna vlákna aplikace, pokud jich má víc, dáš na stejné jádro). No prostě čím víc tvá aplikace používá kód z knihoven OS, případně GPU, tím víc toho jede nativně na Windows a Macu.
27. 4. 2023, 21:55 editováno autorem komentáře
Vždyť to jsem napsal :-) Rosetta 2 právě využívá toho, že Apple CPU umí x86 strong memory model. Ale i bez něj lidi vesele používají Rosettu 2 na Linuxu (Apple ji oficiálně vydal i pro Linux - primárně pro x86 Docker images na macOS) na Cortex jádrech, které to neumí. Stačí se zamyslet, k čemu strong memory model slouží a obejít to pro aplikace, které běží na více jádrech (pro jednovláknové aplikace bez práce).
28. 4. 2023, 00:07 editováno autorem komentáře
Kdyby to psal v assembleru stejný počet lidí, nemají nic. Kdyby navýšili počet lidí adekvátně tomu, o kolik těžší je psát v assembleru, pravděpodobně by měly pomalejší kód. Protože kompilátory už jsou nějakou dobu v optimalizaci lepší, než i ti lepší programátoři. Samozřejmě že kdyby to psali ti nejlepší z nejlepších, dokázali by to v assembleru občas optimalizovat lépe (protože ti nejlepší z nejlepších by mimo jiné neměli problém nechat si to přeložit kompilátorem a použít jím vygenerované optimalizace) – akorát by to trvalo tisíc let, než by všechen ten kód ručně a ve špičkové kvalitě napsali.
Protoze GPU nema task switch a potrebu odkladat desitky kilobajtu TSS, resp. je tam nejaka hw podpora pro prepinani threadu.
Az bude mit GPU podporu pro MMU, TLB, vyjimky/restart, paging a swapovani, a nabootuje Linux, tak muzeme srovnavat srovnatelne. Do te doby je gpu pouha jednoucelova hracka - resp takove nacancanejsi DSP (jestli si je nekdo pamatuje, at uz od ADI nebo TI)
Já mám zkušenost jinou - pokud se jedná o nějaké distributed věci, které jsou obrovské, je tam nějaký network overhead, atd... tak AVX-512 je jednoznačná volba - programuje se pro to skvěle, debuggovat se to dá taky hezky a jako bonus je to na každém commodity HW co má X86 architekturu (Xeon a nově i Epyc od AMD) - člověk si může rentnout obrovský cluster v podstatě bez limitu. S GPU je to mnohem horší - je to drahé a dostupnost v cloudu je hodně omezená, protože každý chce GPU na ML...
Já jsem se teda setkal s AVX-512 kódem pro kompresi/dekompresi dat, regex engine, JSON parsing, XML parsing, a různé další věci pro big data processing. Když je zrychlení oproti C třeba 10x a problém začne být network bandwidth, tak je práce v podstatě hotová.