• úvod
  • témata
  • události
  • tržiště
  • diskuze
  • nástěnka
  • přihlásit
    registrace
    ztracené heslo?
    XCHAOSANSI C/C99 (specifikace), GNU C (gcc, glibc), Tiny C (tcc) a POSIX - ne nutně C++,g++,libstdc++ nebo Win32 API
    REDGUY
    REDGUY --- ---
    XCHAOS: a kromě toho... myslel jsem, že operátor ++ je atomický a převede se naprávě jednu instrukci CPU - tak to sis myslel blbe. Za prve, standard o atomicnosti nic nerika. Za druhe, ++ se na jednu instrukce prevest muze ale nemusi. A za treti, ani ta instrukce (by default a na x86) neni atomicka. Wow, tendlecten multithreading je cim dal tim slozitejsi, co? Muzes prosim odpovedet na moji otazku? Kolik nejak vyrazne multithreadovyho kodu uz jsi napsal?

    ale featury jako semafory tam můžou samozřejmě bejt taky 8)))) Ty ses fakt designer jazyku. "Proste tydlecty featury, ty tam muzou bejt taky, no" 8))))

    podstatný je, že spoustu věcí můžeš dělat paralelně bez velkýho přemýšlení (typicky ti třeba z jedné zpracovávané položky vznikne jiná položka - No, zjevne nemuzes. Resp, prave nazorne demonstrujes, ze to sice muzes udelat bez velkyho premysleni, ale je pak slusna sance, ze to udelas blbe. Prekvapko 8))))


    třeba insert do databáze je atomický tak nějak z principu, i když se o něj pokusí víc vláken současně - aaaaaargh. Vis co znamena slovo "atomicky"? Slysel jsi nekdy o transakcich a k cemu slouzi?
    XCHAOS
    XCHAOS --- ---
    REDGUY: ale featury jako semafory tam můžou samozřejmě bejt taky (a kromě toho... myslel jsem, že operátor ++ je atomický a převede se naprávě jednu instrukci CPU?)

    podstatný je, že spoustu věcí můžeš dělat paralelně bez velkýho přemýšlení (typicky ti třeba z jedné zpracovávané položky vznikne jiná položka... a třeba insert do databáze je atomický tak nějak z principu, i když se o něj pokusí víc vláken současně... i když zrovna s libmysql jsem zatím pokusy s multithreadingem pravda nedělal)

    (částečně je to i o tom, že já všechny tyhle pokusy chci dělat, ale potřebuju mít nějakou záminku, proč je dělat - směřovat někam, dělat to v rámci něčeho...)
    REDGUY
    REDGUY --- ---
    XCHAOS: můj způsob alokace byl natolik geniální, že ty si ho vůbec nepochopil - LOOOOL. No urcite. Uplne stejne jako jsem nechopil genialni zpusob, kterym jsi chtel diky technologickemu naskoku vyhrat SunTrip. Prosim, pripomen mi, jak to nakonec dopadlo? 8)))
    REDGUY
    REDGUY --- ---
    XCHAOS: ehm, serverový aplikace běžně sahají na sdílené prvky, že ... třeba když čtou výsledek databázového dotazu, který sahá na databázový cluster? nebo když sahají na diskové pole? - jezismarja. Ty proste fakt vubec netusis. Vubec se nemusime bavit o nejakejch databazich. Co kdyz chces spocitat, kolik prvku nejakyho pole splnuje nejakou podminku? Mas nejakej spolecnej counter, spustis n threadu, ty zacnou koukat na jednotlivy prvky pole a pokud prvek splnuje podminku, tak inkrementes counter. Akorat ze ten inkrement musis delat atomicky, takze co? Aha, semafory, zamykani ktery udajne nejsou potreba. Ten sdilenej zdroj nemusi bejt nejakej server, ale ciste jen ta jedna spolecna promena. Plus samozrejme takovy detaily, ze na moderni architekture muze bejt jeden thread, co frci skrz pole, mnohonasobne rychlejsi nez x threadu, ktery si to pole mezi sebe nejakej rozebiraji (protoze rezie threadu a hlavne kouzla na urovni procesoru a pristupu k pameti).

    A btw, co jsi prosim chtel rict tou citovanou veci? Ze serverovy aplikace NESAHAJI na sdileny prvky jako databaze? To jako vazne?

    Proste zase: tvoje predstava ze "kdyz se omezim na paralelni zpracovani prvku pole, nepotrebuju zamykani a semafory" je neuveritelne naivni.
    XCHAOS
    XCHAOS --- ---
    (btw, myslím jsem jeden čas směřoval k triku, že jsem forcnul aby parametr makra v C, aby to musela být LValue :-) čímž se zabránilo double evaluation. ale uznávám, že to asi není way to go :-)
    XCHAOS
    XCHAOS --- ---
    REDGUY: popravdě, můj způsob alokace byl natolik geniální, že ty si ho vůbec nepochopil, podle mě. (ale připouštím, že si mě zastavil v jiných zajímavých bodech, např. problém s double-evaluation parametrů makra, apod.)
    XCHAOS
    XCHAOS --- ---
    no, vlastně si nejsem jistý, jestli je víc bambilion nebo bazilion
    XCHAOS
    XCHAOS --- ---
    BTW navrhované SI označení jednotek četnosti v případě kvadratické a vyšší složitosti algoritmů:

    bambilion
    bambiliarda
    bazilion
    baziliarda
    XCHAOS
    XCHAOS --- ---
    REDGUY: ehm, serverový aplikace běžně sahají na sdílené prvky, že ... třeba když čtou výsledek databázového dotazu, který sahá na databázový cluster? nebo když sahají na diskové pole?

    podívej, já prostě občas počítám nějaká "big data" (tedy typicky, bambilion příliš často logovaných nesmyslů za X let provozu něčeho) a s každým jednotlivým prvkem dělám něco. zažil jsem ale data mining, kdy skripty běžely celou noc a přepisovaly se kvůli tomu do céčka (tedy, ne v mojí firmě).

    dnes jsou sice počítače zase o něco rychlejší, ale zase se shromažďuje ještě více dat, za ještě více let... a nástroje, které se používají, jsou také zase o něco více bloated.

    každopádně, představa, že chci něco spočítat přes bazilion databázových záznamů, a každý ten výpočet pro jeden záznam kupodivu chvíli trvá, a mě se na počítači fláká 8 jader, a jediná alternativa, kterou mí nabídne python, je pustit 8 procesů současně ručně na ručně vymezené intervaly dat... tako jako říkej si co chceš, ale mě můj požadavek přijde příčetný

    ad to, že jsem přišel na to, jak se něco dělá - no, takže když na něco nepřijdu, tak jsem idiot, a když na to přijdu, tak je to facepalm? že já se vůbec snažím... podstatné je, že dneska je multithreading zbytečně složitý, některé platformy se mu důsledně vyhýbají.. a já přitom myslím, že by to mělo být tak průzračně jasné, jako bylo programování v Basicu na ZX spectru :-)

    jak říkají lidi co objevili Python.. že je programování najednou zase začalo bavit...
    REDGUY
    REDGUY --- ---
    doporučeným pattern-designem bude právě pouštět je pro více prvky nějaké datové struktury, protože pak nemusíš řešit žádné zamykání, protože je jasně dané, že na jeden prvek si pustil jedno vlákno. dokonce si myslím, že tenhle design patter by mohl slušně řešit většinu věcí typu zamykání - max. pokud následně budeš chtít s prvky dělat něco jiného, dáš si na konci toho rozvětvení něco jako "wait all", což počká na doběhnutí všech spuštěných threadů... a nemusíš řešit semafory, zamykání, nic. - HAHAHAHAHAHAHA. Ach boze. Za prve, pitomost, protoze v okamziku, kdy funkce, zpracovajici jeden prvek sahne na nejakej sdilenej zdroj, tak samozrejme ty "semafory, zamykani" musis resit. Za druhe, tvuj jazyk, kterej explicitne vymejslis za ucelem lepsiho vyuziti vicejadrovejch systemu, bude v multithreadingu poradne podporovat ciste jen paralelni zpracovani prvku nejakyho pole? BUAHAHAHAHAHA 8))

    představ si to tak, že můj code generátor nebude proměnné mateřského jazyka implementovat jako lokální C proměnné, ale vždy pro každý scope vygeneruje strukturu místních proměnných, která vždy půjde předat jakékoliv funkci - /facepalm. Jo, to je opravdu uzasnej trik a zcela originalni napad. Teda, akorat ze to je normalni zpusob, jak se to dela, zejmena v situaci, kdy potrebujes closure, takze alokovat lokalni promeny na stacku neprichazi v uvahu.

    Jak rikam, _PRECTI_ _SI_ _O_ _TOM_ _NECO_.
    XCHAOS
    XCHAOS --- ---
    REDGUY: určitě nejde o to, jak se jmenuje jaká podstatná věc. moje cíle nejsou tak vysoké, jaké má Go a Rust - naopak, sázím na to, že C nepřestane existovat, a že zpětná kompatibilita s C mi zajistí existenci (ostatní cílové platformy pak jsou určeny spíše než co jiného "na hraní" - benchmarkování, flamewary spříznivci těchto cílových platforem, a taky přenositelnost na místa, kde nemůžu přeložit nebo i jen deploynout binárku,...taková místa pokud vím stále existují...)

    nicméně, tím že z toho půjde vygenerovat binárka, a že to bude mít nějakou podporu i pro uvažování z hlediska threadů, tím skutečně cílím _trochu_ tam, kam cílí Go a Rust. jenomže nemám tak velké ambice a na příkladu, který jsem uvedl, je vidět, že za nejobvyklejší využití threadů pokládám prostě paralení zpracování prvků nějaké sbírky/kontejneru.... naopak, kdybych tam měl strukturu, která _garantuje_ paralelní spuštění kódu, tak si tím znemožním využití třeba webového PHP jako cílové plaformy!

    ačkoliv ty thready u mě půjde odstartovat za jakýmkoliv účelem, tak doporučeným pattern-designem bude právě pouštět je pro více prvky nějaké datové struktury, protože pak nemusíš řešit žádné zamykání, protože je jasně dané, že na jeden prvek si pustil jedno vlákno. dokonce si myslím, že tenhle design patter by mohl slušně řešit většinu věcí typu zamykání - max. pokud následně budeš chtít s prvky dělat něco jiného, dáš si na konci toho rozvětvení něco jako "wait all", což počká na doběhnutí všech spuštěných threadů... a nemusíš řešit semafory, zamykání, nic.

    je to vlastně moje typický uvažování o těhle složitých věcech, kdy často univerzální nástroje jsou moc lowlevel a postrádají úplně základní intuitivní infrastrukturu (typicky "pusť tohle jako nový thread, pokud jich ale teda už neběží moc současně")

    nicméně je třeba připustit, že část své několikaleté debaty si vyhrál, protože některé z těhle věcí si už fakt nedovedu představit, že bych jednoduše zapouzdřit do C knihovních funkcí a maker, aby to bylo fakt user friendly.

    je dokonce možný, že abych z mnou požadovaných konstrukcí mohl jednoduše generovat C kód, tak budu muset všechny místní proměnné deklarovat uvnitř nějakých struktur, a to, co u mě budou anonymní funkce, bude v mezikódu definované jako funkce a budu tam muset předávat pointery na strukturu s proměnnými nadřazeného scope... tahle věc mi mimochodem vyřeší nejen thready, ale taky by mi docela elegantně vyřešila otázku dealokace paměti alokované uvnitř scope.

    představ si to tak, že můj code generátor nebude proměnné mateřského jazyka implementovat jako lokální C proměnné, ale vždy pro každý scope vygeneruje strukturu místních proměnných, která vždy půjde předat jakékoliv funkci (protože mi všechny funkce faky vygeneruje code generátor, tak můžu pustit z hlavy délku zápisu). je to něco jako objektové programování, ale každý scope se takhle vlastně stává scope, do kterého můžou nahlížet funkce, které z něj zavoláš (trochu jako vypadalo programování v Pascalu, takže mi to umožní definice "lokálních funkcí", které uvidí do proměnných scope uvnitř kterého funkci defunuješ, ale hlavně mi to umožní generovat v mezikódu C funkci pro všechno,co bude v nadřazeném jazyce anonymní funkce (viz deklarace function() v Javascriptu), současně mi to umožní generovat mezikód bez globálních proměnných...

    (asi už jsem tu kdysi psal psal o tom, že mi vzdáleně podobný trik kdysi v 90kách ukazovali v jedné francouzské firmě, která licencovala Arachne browser, s tím, že tam nepoužívání globálních používali jako trik nejen k "thread k safety", ale i možnosti poslepovat jakékoliv fragmenty kódu do jediné programu... každám main() funkce pak má strukturu s vlastními globálními proměnnými... oni ale pouze trvali na tom, aby se místo globálních proměnných používala prostě struktura, na kterou jde předat pointer. tuším stejně to řeší i transcompilery z C do C++...)

    trik, kdy proměnné každé funkce se automaticky stávají objektem, na který jde předat pointer, se mi popravdě líbí, akorát znamená overhead tam, kde to není potřeba... a zase: od toho máme generátor kódu, který se může podívat, jestli to bude někde v překládaném zdrojáku potřeba a může tuhle feature zapnout jen pro ty scopes, ve ktrerých se vyskytne potřeba, aby to tak bylo! dtto alokace paměti - když překladač uvidí, že na alokovanou paměť žádná reference vůbec nemá šanci vzniknout, použije daleko tupější alokační strategii, než pro složitější kód, nebo stejně tak může v nadřazeném jazyce být zápis operací pro pole fixní délky a pro pole proměnné délky stejný - ale v mezikódu se můžou použít naprosto struktury...
    REDGUY
    REDGUY --- ---
    Hele, jen tak pro kontrolu, at si neco overim: kolik kodu, ktery vyrazne pouzival multithreading, jsi napsal?
    REDGUY
    REDGUY --- ---
    XCHAOS: " to musíš uznat"? Ale prdlajs. Tu debatu o tvech "alokacnich strategiich" si velmi dobre pamatuju, zejmena tu cast, kdy jsi vymyslel nejakej genialni zpusob alokace, kterej jsem ti pak bud ja nebo nekdo jinej komplet rozbil trivialnim prikladem, pro kterej to nefungovalo. A kdyz si to dam dohromady s tim, ze si ten prekladac zjevne predstavujes jako hromadku nejakej jednoduchej sablon... no, dost legracni predstava 8)))

    jinak ten "referenční cyklus" nevím, jak si představuješ - myslim, ze zcela zjevne nevis o cem mluvis. Hele, fakt, precti si neco o garbage collectorech. Zacni treba wikipedii. A tentokrat vic, nez jen prvni odstavec 8)))
    XCHAOS
    XCHAOS --- ---
    REDGUY: no já mám už léta registrovanou doménu memoryleaks.net a použiju jí nejspíš právě na tenhle projekt, po zralé úvaze :-) (protože to vtipný přijde právě jen programátorům)

    minimálně: jakákoliv alokační strategie, kterou jsem vymýšlel pro svůj způsob používání Céčka, se dá použít i v code-generátoru produkujícím C mezikód, to musíš uznat. A navíc ještě s touhle strategií nemusím obtěžovat programátora - protože ten napíše jednoduchý zdrojový kód, ve kterém se akceleračními strategiemi sám může, ale nemusí zabývat...

    jinak ten "referenční cyklus" nevím, jak si představuješ, protože z hlediska správce paměti je nový reference counter vytvářen uvnitř náhrady za malloc() a u všech následných přiřazení referencí se koukáš na tuhle paměť, která sama už nikam neukazuje. takže zvyšování reference counteru se musí dít někde, než si to představuješ... kdybych se na to chtěl koukat optikou dědičnosti objektů, tak úplně všechny alokovatelné objekty - pointery ale nejsou objekty! - musí být potomkem nějakého základního objektu "memory" a při předávání referencí se pracuje s reference counterem... zacyklit sice můžeš pointery (reference), ale samotný objekt ne, protože ten už na nic dalšího neukazuje... tvoje představa zacyklení se týká toho, že vlastní reference counter by u sebe měl i každý pointer (každá reference), ale tak to není.

    jedna z možností, jak to dělat, je že bych předával všechny pointery nějakým stylem (velmi zhruba řečeno)

    a=let(b)

    kde ta funkce "let()" by byla doplňující k "memu" malloc()/free() a hlídala by, kolik referencí na daný kus paměti existuje (jiný vhodný název by byl taky prostě třeba "ref()"). nebylo by to ale extra rychlé, pokaždé procházet databázi alokací a asi se mi nelíbí takhle dělat... jiná možnost je používat nějaké složitě strukturované pointery, které by hlídaly, kde je uložný reference counter daného bloku paměti, na který pointer ukazuje. tím pádem by si při sebevětším zacyklení těchle "chytrých pointerů" vždycky odkazoval jen na jeden jediný reference counter.

    v zásadě nemám pocit, že se tímhle směrem vydám. ale generování mezikódu mi dává daleko lepší možnost, že všechny hlídací mechanismy, které kvůli správě paměti bude nutné z mezikódu volat, budou skutečně zavolány všude a že programátor nebude mít možnost zapomenout nějaké volání tak, jako by na něj mohl zapomenout v kódu napsaném ručně (pro začátek třeba jenom nebude možné zapomenout na volání free(), pokud si v prvních verzích vystačím s malloc() a free().

    minimálně se mi teď uvažování dělí na dva hlavní směry:
    1) jak umožnit programátorovi napsat to jednoduše
    2) jaký C mezikód generovat, aby to fungovalo (přičemž čímž složitější bude, tím menší náskok vůči jiným cílovým platformám, které si to budou řešit samy, získám)

    uznávám, že 1) je v tomhle klubu offtopic a asi si na to založím nějaké jiné diskuzní fórum, časem....
    REDGUY
    REDGUY --- ---
    XCHAOS: přidat nějaké reference countery. - aha. Takze referencni cykly budou znamenat memory leaky? Coool! 8))) Plus samozrejme dopad na spotrebu pameti a vykon. Coz se u jazyka, kterej chces kompilovat do C kvuli vykonu fakt hodi 8)))

    programátoři prostě o uvolňování paměti nebudou muset přemýšlet, když nebudou chtít. - no a proto by me _fakt_ zajimalo, jak to zaridis u jazyka, kterej chces pomoci "jednoradkovej templat" prekladat do C, kde zadnej automatickej memory management neni. Nebo ze by se nam to nejak zacalo komplikovat? A pomalu si zacinas uvedomovat, ze je to krapet slozitejsi, nez sis myslel?
    XCHAOS
    XCHAOS --- ---
    REDGUY: no hele, popravdě nevím :-) výhodou je, že code generator může např. všude, kde se jakkoliv přistupuje k referencím na odkazovanou paměť a stejně tak i na konce scope, kde zaniká existence proměnných, přidat nějaké reference countery.

    v podstatě právě to, že jsem se vzdal myšlenky, aby generovaný kód byl za každou činu nějak snadno a cool čitelný, mi umožní použít některou ze strategií, které bych při ručním programování použít nechtěl. možné je i ruční generování "free" na objekty, na které po dobu jejich existence další odkaz zaručeně nevznikl a nějaký mechanismus předávání počítadla reference counterů ve všech ostatních případech.

    pochopitelně to musí být stejně blbuvzdorné, jako je to třeba v tom Pythonu, programátoři prostě o uvolňování paměti nebudou muset přemýšlet, když nebudou chtít. mým úkolem bude pořešit toto v tom generovaném mezikódu... na druhou stranu, ten překladač bude o generovaném kódu vědět všechno, co by o něm věděl dobrý programátor - takže vlastně píšu program, který bude v C programovat za mě :-)

    každopádně, jakákoliv snaha říct, že nějaké objekty vzniklé v nějakém úseku jsou dočasné a už se mají dealkovat, se bude programátorovi na tomhle levelu vyjadřovat daleko snažším způsobem (asi jako v C můžeš přidat scope kamkoliv a skrz něj pár proměnných na stack, které se zahodí jakmile nejsou potřeba). ovšem na rozdíl od mé předchozí vize nadstavby nad C budou takováhle akcelerace kódu či úspora paměti zcela dobrovolná a programátoři se tím nebudou muset zabývat povinně.
    REDGUY
    REDGUY --- ---
    Hele, XChaosi, jak bude fungovat treba sprava pameti? Kdyz budes prekladat jak do gargbage-collected jazyku, tak do C, jakpak to bude fungovat v xJazyku?
    REDGUY
    REDGUY --- ---
    XCHAOS: o se nových platforem go a rust týče, tak start nového vlákna (nebo taky ne - přesné chování není definováno, může a nemusí se to spustit v novém vlákně...) pomocí klíčového slova "go" je tam příjemně intuitivní a dost možná to do svého projektu převezmu - v rustu se thready spousteji pres "go"? To jsou mi novinky... Kazdopadne, zjevne nechapes, ze nejde o to, jaky "klicovy slovo" pouzijes. Golang ma celou koncepci postavenou na gorutinach (ktery jsou neco jinyho nez klasicky thready), vcetne celyho runtime a knihoven. Zase neco, co zcela ignorujes. Obdobne v rustu mas celej model ochrany pameti, integorvanej s multithreadinngem. To jsou ty podstatny veci, ne jak se jmenuje nejaky klicovy slovo. Zkus aspon trochu premejslet, neco si o tom nastudovat a neztracet cas povrchnostma.
    REDGUY
    REDGUY --- ---
    XCHAOS: že programátor ví, co dělá, a které objekty jsou na sobě nezávislé a které ne, to by minimálně _měla_ být pravda, - blbost nebyla to, ze by programator vedel co dela, ale to, ze obecne jen programator vi, jestli lze paralelizovat.

    že chci jazyk s blbuvzdornou a inutitivní syntaxi pro vícevláknový během, . - HAHAHAHAHAHAHAHAHAHAHAHAHAHA. Hele, bezpecny paralelni zpracovani dat je hodne, hodne slozitej problem. Spousta hodne chytrej lidi na nem pracuje v podstate desitky let, vymejsleji metodologie, abstrakce, kompletni programovaci jazyky a v podstate to porad neni poradne vyreseny, porad je tam spousta prilezitosti, jak si rozbit hubu. A ty si myslis, ze proste jen tak prijdes, vyfrknes nejakou zhruba Python-like syntaxi do ktery zvejkackou prilepis extra klicovy slovo "go" a tim to vyresis? Navic prenositelne mezi C/PHP a kdovi cim jeste? LOOOOL. Ne. Ani omylem. To je zase klasickej priklad xchasovoskyho Dunning-Kruger efektu: o problemu mas nejaky zakladni vedomosti, ale mnohem, mnohem vic toho proste ani nahodou netusis. Vysledek? Predstavujes si, jak to vyresis nejakejma trivialnima hackama, ktery ale ignorujou jak obrovsky komplexni problem to je.

    Co komunikace mezi threadama? Synchronizace pristupu k datum? Race conditions? CPU-bound vs IO-bound tasky? Exceptiony v threadech? Spravnej pocet threadu? Priorita? A tak dale, a tak dale...

    taky by znal - minimálně po prvním průchodu cyklu - dobu - HAHAHAHA. Wrong on so many levels.

    by asi vlákna zvládaly targety C a nodejs - node.js zvlada thready? Jako jo, ted je tam pridali jako experimentali featuru, ale spis mi prijde, ze proste jen zase kecas o necem, cemu nerozumis a nahodou ses trefil. Protoze jestli je node.js necim specifickej, tak prave tou absenci threadu (az teda to te soucasne experimentalni verze)

    A tak dale, a tak dale. Proste zjevne jen motas buzzwordy dohromady. Zjevne z toho nic nebude a pokud ano, dopadne to stejne jako SunTrip. Bolest, utrpeni, spousta duct-tape a prekrocenej casovej limit 8)))
    XCHAOS
    XCHAOS --- ---
    REDGUY: podívej, to, že programátor ví, co dělá, a které objekty jsou na sobě nezávislé a které ne, to by minimálně _měla_ být pravda, i když samozřejmě předpokládá to, že programátor rozumí prostředí, ve kterém pracuje.

    i kdybych nevyhlásil jiný cíl, než že chci jazyk s blbuvzdornou a inutitivní syntaxi pro vícevláknový během, který bude schopen generovat ze zdrojáku mezikód pro platformy, které to jednoduše neumožňují, i pro ty, které to umožňují, tak je to dostatečné zdůvodnění, proč ten projekt rozjíždět (víš, že jsem o tom mluvil už dřív...)

    co se nových platforem go a rust týče, tak start nového vlákna (nebo taky ne - přesné chování není definováno, může a nemusí se to spustit v novém vlákně...) pomocí klíčového slova "go" je tam příjemně intuitivní a dost možná to do svého projektu převezmu (jako název mám regnutou jednu doménu, už léta...ale zatím tomu říkejme třeba "xCh Basic", po vzoru ZX Basic :-) i když to s Basicem historickým ani microsoftím teda nebude mít společného celkem nic)

    Problém je, že já bych chtěl doplnit nějakou logiku, která sama rozhodne, jestli se nová vlákna mají startovat, nebo jestli zůstáváme v hlavním vlákně (to se dá doplnit čítačem počtu volání toho "go", a v případě smyčky se známým počtem iterací, což je tak nějak pointa, by runtime znal režii, kterou má start vlákna a taky by znal - minimálně po prvním průchodu cyklu - dobu, kterou trval poslední podobný segment - takže by runtime sám vyhodnotil, jak moc má smysl to paralelizovat - což zase řekněme, že ví programátor líp, nebo to může záviset na vstupních datech...)

    aby bylo jasné, jak to myslím:

    Klasické sekvenční procházení (jo - dvojtečka pravděpodobně bude volitelná nebo možná nebude dovolená vůbec - nebude to Python, byl by to jen syntaktický cukr, protože jednořádkové if a for jsou ošklivé :-))

    
    for prvek in seznam 
     zpracuj prvek
     print prvek, "zpracovan"
    


    A tohle by bylo procházení v předem nedefinovaném počtu threadů, podle toho, jaké parametry nastavíme runtimu (nebo jak runtime sám vyhodnotí momentální možnosti systému)

    
    for prvek in seznam 
     go
      zpracuj prvek
      print prvek, "zpracovan"
     print "jedeme dal..."
    


    Takhle by se mohlo zapisovat čekání na ukončení vlákna (moje inspirace, možná by se vyplatilo se podívat, jak to píšou v tom Go :-) zatím je to inspirované spíš Python konstrukcí try ~ except
    
    for prvek in seznam 
     go
      zpracuj prvek
      print "vlakno zpracovalo", prvek
     wait
      print "hlavni proces ma k dispozici zpracovany", prvek
     print "jedeme dal..."
    


    (volání fukcí bez úvozovek je převzaté z Basicu - opět, o syntaxi teprve začínám přemýšlet a nechci nikoho mást tím, že to bude vypadat hned od začátku jako Python, který to není :-) současně bude go bude řešit takové věci, aby se dal použít intuitivní zápis a hodnotu proměnné "prvek" v daném scope mi nepřepsalo jiné vlákno, což bude docela úlet, ale podle mě nejjednodušší bude, aby si o přístup k neduplikované verzi proměnné z nadřazeného scope bylo nutné v "go" scope explicitně zažádat (globální proměnné uvnitř volaných funkcí budou ovšem už zase globální - to je pro změnu inspirace v C)

    Prostě si stanovím, že tam, kde odbočuju do vlákna pomocí "go", bych dal prostě counter dosud neukončených vláken (počítadlo běžících threadů by mělo být celkem nekontroverzně implementovatelné), no a v kombinaci s nějakým monitoringem, kolik třeba thready alokují paměti, by se každý další průchod křižovatkou rozhodoval, jestli startovat thread, nebo ne (důvodem by mohlo být jak moc threadů, tak moc paměti alokované neukončenými thready).

    jakýkoliv paralelizovatelný kód přitom z principu musí být možné provozovat sekvenčně na "hloupých" platformách (v tomhle případě by asi vlákna zvládaly targety C a nodejs... Python to rozumně umí až od trojky, PHP to zase snad prý neumí v režimu skriptů pro webserver, což je tedy zrovna asi platforma, na kterou budu cílit).

    Přitom si jen vezmi hlídání toho, že ve vlákně by se měly používat reentrantní verze funkcí ze standardní knihovny, zatímco mimovlákno to potřeba není, by v ručně psaném vícevláknovém kódu zkrátka byly k zbláznění. Takhle mi code generátor sám pořeší, aby každé odstartované vlákno mělo vlastní kopii proměnných ve scope (podtýkám, že typicky půjde o kopie refererencí/pointerů na objekt - ne o kopii celého objektu), a hloupější cílové platformy se o "zvláknovatelnosti" nedozví vůbec - a je to.

    Už jen to, abych z jediného zdrojáku mohl vygenerovat paralelně obyčejnou i thread-safe verzi kódu, aniž bych nad tím musel dál přemýšlet, je dostatečná motivace začít nad něčím takovým přemejšlet :-) (tedy v podstatě - přemýšlím nad tím, jak to udělat, abych už nemusel přemýšlet :-)

    Všechna CPU jsou už řadu let vícejádrová a já v podstatě pořád programuju tak, jako se programovalo před 20 lety, když ta jádra byla v nejlepším případě tak 2 a jedno trvale žral systém. A přemýšlet nad tím, kolik vlastně těch threadů mám pustit, se mi fakt nechce a chci aby o tom za mě přemýšlel počítač, který to ví líp (zatímc to, jestli se o to vůbec můžeš pokusit, naopak zase JÁ vím líp...)
    Kliknutím sem můžete změnit nastavení reklam