Vzpomněl jsem si na jednoho studenta na univerzitě. Nebyl příliš spokojen se známkou z měření (kdo by taky byl, se čtyřkou se nepostupuje). Přičemž zpracování dokumentu bylo ukázkové a grafy perfektně seděly. Cvičící doktorantka mu, a nám všem také, názorně ukázala, proč je to špatně a díky jí za to! Nechala ho spočítat první a druhou derivaci toho jeho polynomu. Pro příklad: první derivace dráhy je rychlost, druhá derivace je potom zrychlení; u některých fyzikálních veličin lze nalézt jasnou fyzikální interpretaci první a druhé derivace a jejich obraz v reálném světě. Potom mu to došlo (a opravil si tak i celkovou známku, tedy spokojenost byla na obou stranách). Ono totiž funkcí, jejichž graf prochází zadanými body, je nekonečně mnoho, ale ne všechny odpovídají měřené realitě. Jinými slovy, ani dokonalá forma nezachrání špatný obsah. A z chyby se lze skvěle poučit.
Proč to píšu. Tohle je bohužel důvod, proč již nečtu žádné IT magazíny a testy HW. Rozhodně tedy ne české. Totiž, pokud se něco měří, je třeba dobře vědět: co se měří; jak se to měří a především: umět interpretovat výsledek. Tranzistor se také dá měřit metrem nebo úhloměrem, ale obvykle nás více zajímají jeho elektrické parametry. Většina českých IT novinářů bohužel o svém oboru neví skoro nic a podle toho také jejich testy vypadají. Nebo je to prostě rovnou „sponzorované“. :-( Čest vyjímkám!
Například testy procesorů. Mnoho testerů má problém správně testovat vícejádrové procesory a bohužel stále nejsou vyjímkou testy vícejádrových CPU na jedné singlethread aplikaci. Dodnes tak můžeme číst nesmysly typu, že nejdůležitější parametr je frekvence a že je lepší vyšší takt a méně jader než naopak.
Ostatně podobně tomu bylo i v případě zavádění 64b CPU. První procesory běžely na nižší frekvenci než jejich 32b předchůdci a tak ve špatně napsaných aplikací vykazovaly o dost nižší výkon. Uvážíme-li, že 64b CPU má garantovanou intrukční sadu SSE (poprvé od vzniku x86 je něco zaručené), mnohem více mnohem širších registrů a také větší cache, je skoro záhadou, jak je možné na tom postavit aplikaci pomalejší, než na 32b.
Frekvence procesoru je pouze jeden z mnoha parametrů. Daleko větší vliv na výkon má instrukční sada. Například jedno jádro procesoru Intel Core2 Quad 9300 umí ušifrovat AESem cca 70MB/s. Přičemž téměř libovolný procesor s instrukční sadou AES-NI zvládá hodně přes 1GB/s. Tohle změnou frekvence jen tak snadno nedosáhnete. Instrukční sada má daleko větší vliv na rychlost výpočtů, než frekvence. Dnes existují procesory s příkonem 1W, které zvládnou dekódovat HD video. Tohle „general purpose cpu“ nikdy nezvládne.
No a co třeba úplně jiný přístup k problému?
Nakonec, ať již máme libovolný procesor, dva (a více) procesory toho zvládnou víc. A více kompletních počítačů toho zvládne ještě víc, než jeden samotný. Jinými slovy, víceprocesorové stroje tady byly, jsou a budou. UNIX na víceprocesorech vyrůstal. Linux dnes pohání většinu TOP500 superpočítačů s tisícovkami procesorů.
Už je to dlouhé, co? :-) Zkusím se tedy dostat k linuxu. Jaký je tedy ideální procesor pro linux? A jaké má vlastně linux nástroje pro využití mnoha procesorů?
Většina programů z projektu GNU a nejen těch se drží staré dobré unixové filozofie: „Dělej jednu věc a dělej ji pořádně“. Máme k disposici mnoho skvělých, odladěných programů, které jsou vesměs singlethread. Zvláštní co, celou dobu tu mluvím o víceprocesorovém a dokonce více počítačích abych to nakonec zabil singlethread programem?
Další UNIXová myšlenka říká „keep it simple and stupid“ (KISS). Dělej to jednoduše, stupidně. Multithreadové programování je extrémně složité. Vážně. Řízení přístupů ke sdíleným prostředkům, řízení synchronizace vláken a podobné šílenosti. Mnohem jednodušší je to prostě naprogramovat nejjednoduššeji jak to jde. A to je, většinou, jednovláknově.
Teď si asi říkáte, že jsem se úplně zbláznil. Jo jo, já si to myslel také. Když jsem se někdy v roce 2000 dostal poprvé na internet a na linuxové fórum, tak jsem tam četl přesně tohle a ťukal si na čelo o čem to ti linuxáři mluví a vůbec jsou sto let za opicema, přece multithread je jediná budoucnost.
Mno. Ne, nezbláznil jsem se. Mě to trvalo (já jsem takový pomalejší) celých 10 let. Nakonec mě nakopla knížka Art Of Unix Programing, kterou považuji za nejlepší návod na Linux a nejlepší návod na programování vůbec. Přestože neobsahuje jedinný řádek kódu a snad ani jedinný příkaz.
Linux má totiž všechny potřebné nástroje na to, aby pomocí singlethread jednoduchých appek utahal libovolný počet jader a libovolný počet strojů.
Nejjednodušší ukázka je klasická roura. Omlouvám se, že to opět bude z oblasti databází, ale když já nic jiného neumím ;-):
pg_dump | gzip > zaloha.sql.gz
Takhle triviálně jsem rozjel hned 4 procesy. Současně. pg_dump a gzip jsou zcela jasné. Ještě tam ovšem jsou dva další. Jsou to ty dvě roury. Mimochodem z této ukázky je patrné ještě i něco jiného. Totiž to, že program vůbec nemusí mít implementovanou podporu souborů. Jak vidíte, tak ani pg_dump, ani gzip se vůbec nemusejí starat o nějaké soubory, zápisy, fsync apod. To vše za ně zařídí OS.
Pokud ani tohle není dostatečně výmluvné, tak co takhle si to poslat na vedlejší server? Jak by se to udělalo?
Na jednom lokálním počítači je přenos DB velmi snadný a přímočarý:
pg_dump source_db | psql target_db
Rouře se říká cat. Cat je ostatně i samostatný příkaz na vypsání obsahu souborů. My bychom ale potřebovali, aby ta roura vedla z jednoho počítače do druhého.
Jo, potřebujeme netcat:
Na zdroji:
pg_dump source_db | nc destination
Na cílové stanici:
nc | psql target_db
Nebudu to zatěžovat parametry, ty si každý najde sám (nebo si přečtěte příklad ze života). Důležité je si uvědomit, že tímto stylem lze každou rouru (cat, |, >, < — ne to není smajlík :-) — tohle jo) roztrhnout na vícero počítačů na síti.
Takže máme programy, které jsou tak jednoduché, že neumějí ani pracovat se soubory, natož se sítí, a najednou mohou mezi sebou síťově komunikovat a ukládat výstupy do souborů! A i když jsou singlethread, náhle máme efektivně využitých více procesorů dokonce i na více strojích. Magie? UNIX!
Způsobů, jak lze efektivně využít libovolný počet procesorů je ještě víc. Tohle byl ten nejzákladnější a také nejpoužívanější. Jakékoliv spojení rourou znamená, že se spustí mnoho procesů a všechny mohou běžet současně. A jakoukoliv rouru můžeme rozseknout na více počítačů.
Další způsob, který používám pro konverzi obrázků, představuje kombinace find a xargs.
Například:
find ... | xargs -P16 convert ...
Opět jsem vynechal hromadu parametrů, nejsou teď podstatné. Důležité je, že convert je singlethread a find, natož pak xargs, neví nic o obrázcích. Přesto se takhle dá využít 16 procesorů (parametr -P).
Dalším a pro tento článek už posledním příkazem je příkaz make. Make pomocí jednoduché definice závislostí v souboru Makefile dokáže spustit sekvenci příkazů. Používá se většinou na kompilování programů, ale lze jej použít na ledacos.
Já jej použil na generování hromady definičních souborů pro gnuplot (snad někdy bude i verze pro povray), z nich vzniklo mnoho obrázků, které se dále zpracovávaly … až po jejich sloučení do jednoho videa (ffmpeg je snad jedinná multithread appka z tohodle článku). Make umí spustit mnoho nezávislých (dle definice závislosti v Makefile) procesů současně, jejich počet lze definovat parametrem -j. Máte-li čtyřjádro, kompilujte příkazem make -j 5, bude to nejrychlejší.
A tak dále. Možností, jak využít libovolný počet procesorů na libovolném počtu strojů je hodně.
A jaký je ideální procesor pro linux nechám na vás. ;-) Zatímco dvojnásobný počet jader lze využít triviálním postupem, tak na dvojnásobnou frekvenci si hodně dlouho počkáme. A dva pomalejší procesory (třeba i na dvou počítačích v síti) jsou obvykle levnější a společně mnohem výkonnější než jeden topspeed.
A úplně nakonec ještě jedno stařší ale stále aktuální videjko k tématu
Napsal jsi to hezky, ta kniha se mi taky moc líbila. Včera jsem si btw koupil Linux – bezpečnost a exploity za 59,- Kč (r. vydání 2002 ale stále aktuální :-)
Holt pipe je základ celého konceptu. Velmi doporučuji podívat se na jazyk Go (golang.org) který roky tajně vyvíjeli v Googlu pánové co stojí za Plan9 i UNIXem. Tento rok vyšla verze 1 a je taky plně podporovaný v GCC. V Google ho používají na věci, kde C/C++ je moc chybové, ale Python/Java příliš pomalé technologie. Koncept takzvaných kanálů přesně zapadá do tohoto konceptu (UNIX pipes), programování je zase radost. Moc se mi ten jazyk líbí a ještě o něm uslyšíme.
Mimochodem při čtení článků o Go si člověk uvědomí jednu věc – kanály (a UNIX pajpy) dělají věci rychlejší i na jednojádrovém jednoprocesorovém systému! Vůbec nepotřebuješ víc jader, a přesto to Go Runtime (v případě UNIX rour pak linuxové jádro) umí přepínat a celkově zrychlit. Největším problémem jsou totiž IO operace. Pokud nerozkládáš nějaké prvočíslo, procesor v podstatě 80 % času jen „čeká“. Díky rourám se tyto „díry“ dají nádherně zaplnit, takže v případě balení adresáře do tarballu bude Linux přepínat tak, že při čekání na disk se bude komprimovat a naopak. Je to fantazie, koncert a nádhera. Je to jedna z věcí, proč miluju UNIX.
Moc se těším na ARM a jejich big.LITTLE platformy, protože to co přijde sešrotuje Intel a Microsoft způsobem, o kterým se nám ani nezdálo. Do tří let tady budou ARM serverové blade sestavy s procesory na 5 GHz, které strčí Xeony se stejnou frekvencí v běžných věcech vyloženě do kapsy při zlomku spotřeby. Je to totiž RISC, a 5 GHz RISCu je úplně jiný kafe, než u CISCu (který možná vyhraje v umělých benchmarcích – třeba ty zmíněné šifrování – ale celkově dostane na prdel :-)
Díky moc za reakci. Go přidávám do svého todo listu. :-)
Se zbytkem nelze než souhlasit. Obecná poučka pro vytížení x CPU je spustit x+1 procesů a to platí i pro jeden procesor. Přesně z těch důvodů neustálého čekání (disk, síť, obečně libovolné zařízení).
Ad ARMy. Opět souhlas a opět bod pro linux. ARM procesorů budou mraky a ty OS a appky to budou muset umět využít. V UNIXech obecně to nebude problém.
Musel jsem si na to zapnout laptop, před chvílí jsem sice přijel z Brna a tohle bych na tabletu nenapsal ;-)
Jojo konsenzus je CPU + 1, ale nebál bych se i přitlačit. Jak říkám, zrychlení je měřitelné i bez více procesorů/jader.
Ve Fedoře se na ARMu těžce maká, plány jsou velké.
U ARMu je IMHO zatím největší problém roztříštěnost. Zatímco na x86 uděláš dva buildy – 32 a 64 bitový a víceméně ti stačí jen jeden z nich, ARM zatím není pořádně kompatibilní ani v rámci jednotlivých verzí, takže člověk skončí u dělání buildů pro prakticky každý typ procesoru. To samozřejmě dělá podporu ARMu u distribucí typu Fedory mnohem složitější.
Díky za článek. Zase jsem o něco chytřejší. A zřejmě i efektivnější :)
Pingback: Nový počítač a vybírací proces | Heronovo
Pingback: Tři způsoby upgrade PostgreSQL | Heronovo
Pingback: Nový pohled na komprimaci v době víceprocesorových systémů | Heronovo
Pingback: FarbFeld vs. PNG | Heronovo