» »

niti (threads)

niti (threads)

«
1
2

cewapcic ::

irc.freenode.net
#python
enga modela neki zanima od niti
ga čist potolčejo, da so niti ničvredne v pythonu
pol jst lepo vprašam ja kaj pa v javi k maš animacije pa take fore...
jim nč ni jasn...
dam pol recmo dva primera
if animation is doing something the buttons are unresponsive in java?
or if u have some calculations in the background the gui is unresponsive?
No, that doesn't really make any sense. I don't think using a thread just for playing an animation is recommended even in java, though.
Using a thread to play an animation is recommended absolutely nowhere.
most gui libraries should come with an event loop, you should run all expensive computations with the idle callback of the gui event loop.

pol tko men nč jasn sj to smo se ja v šoli učil, delal animacije s pomočjo niti
pol me pa zabije, da se nej poberem v java channel
kaj nas pol na FRI-ju brezvezne stvari učijo al kaj?

http://www.mediafire.com/?onn2wmymgzw
primer animacije
  • spremenil: cewapcic ()

Senitel ::

Da in ne. Samo za eno animacijo rolat in se ukvarjat s threadi zaradi tega, da bo gui odziven je rahlo brezveze... Po drugi strani pa če hočeš imet kakšno resno korist od današnjih multicore CPU-jev (ali GPU-jev) moraš stvari razparcelirat na threade. Ampak je treba vso stvar premislit, da se jo naredi tako kot treba.

cewapcic ::

http://www.eecs.berkeley.edu/Pubs/TechR...
pa še tale članek so mi porinl...
zna bit zanimiv, k je lihk z berkeley-a :)

Zgodovina sprememb…

  • spremenil: cewapcic ()

kopernik ::

Čist odvisno, če tisto nekaj, kar počneš v ozadju, blokira execution flow, potem je razmislek o threadih na mestu. Če pa je non-blocking (oz. da lahko vsaj prekinjaš razmeroma pogosto), potem jih verjetno ne rabiš.

BlueRunner ::

Niti imajo svoje prednosti in svojee lastnosti. Poročilo, ki so ti ga porinili, ima že brado in njegov za nekatere primere pravilen zaključek, da so niti napačna abstrakcija, je tudi starejši (gl. reference v poročilu).

Samo z roko pa se v tem poročilu odmahne z primeri, kjer so niti zelo elegantna rešitev za problemsko domeno (nrp na str. 10, zadnji odstavek).

To pa je tudi odgovor na tvoje začetno vprašanje: uporaba niti je lahko dobra izbira ali pa slaba izbira. Za vsak primer, kjer so niti dobra izbira, ti lahko dam nasproten primer, kjer niti niso dobra izbira. Kategorično zavračanje niti ali pa kategorično ignoriranje alternativ je enako škodljivo, saj s tem izbiraš orodje, ne da bi upošteval lastnosti problema in/ali okolja, ki ga uporabljaš.

Niti so močno orodje, vendar pa niso vedno pravilen odgovor. Ravno tako pa ostajajo tudi alternative, ki pa ravno tako niso vedno pravilen odgovor. Pravilen odgovor je pač še vedno odvisen od problema, ki ga imaš pred seboj.

Dejstvo, da si opazil dve nasprotujoči si različni mnenji in te sedaj zanima kaj je sedaj res in kdo ima prav, pa je najboljši znak, da se razvijaš v dobrega inženirja. Na FRI-ju ali pa FERI-ju ne učijo brezveznih stvari, ne morejo pa naučiti vsega kar obstaja. Večino stvari boš lahko odkril šele tako kot to počneš sedaj. Vprašaš, prebereš, poskusiš.

Lahko pa si vzameš to luknjo v obravnavani snovi na FRI-ju kot izhodišče za lastno diplomsko delo in iz tega razviješ še nekaj več.

BigWhale ::

> most gui libraries should come with an event loop, you should run all expensive
> computations with the idle callback of the gui event loop.

Ja, Amish paradise!

Takoj, ko imas dva neodvisna eventa, ki eden drugega ne motita in trajata dalj casa kot traja ustvarjanje in zakljucevanje novega threada, stvar premaknes v svojo nit. Dandanes, ko so vsi procesorji ze multicore se ti to takoj splaca.

Potrebno je biti pazljiv pri stvareh, ki morajo med seboj komunicirati.

fiction ::

IMHO je problem niti to, da context switch tipicno ni najbolj hiter. Preden se zacne izvajati druga nit, se mora najprej shraniti stanje stare (registri itd.) in potem obnoviti stanje druge. To lahko vzame nekaj koristnega procesorskega casa. Vse skupaj sicer ni tako dolgo, ampak zanemarljiv pa ta cas glede na to, da se vse skupaj dogaja precej pogosto vseeno ni. Seveda je drugace, ce imas moznost, da niti res tecejo na vecih "procesorjih" istocasno (kakorkoli ze, npr. vecjedrniki so kar precej razsirjeni).

Niti za to, da je nekaj bolj odzivno, so pomoje brezveze. Ce delas X in Y (npr. zahteven izracun in prikaz GUI-ja) lahko vedno naredis, da eden da drugemu dovolj casa za najbolj osnovne stvari tj. ni treba da je X in Y svoja nit. Ce GUI prikazuje potek izracuna, lahko celo pride do tega, da se niti med seboj "ovirata". Seveda pa moras paziti na to, da stvari delas non-blocking. Torej namesto da cakas (branje z diska, cakanje na podatke z mreze) takrat delas nekaj drugega. V tem primeru je torej malo bolj komplicirano za programerja. Pa se ni nujno, da bo od tega kaksna korist.

Ce sta X in Y dva locena izracuna je seveda dobro oboje delati hkrati, v kolikor se to da. Ali pa ce imas nek problem, ki ga lahko dobro paraleliziras. To je pomoje tipicen primer za niti.

Binji ::

Ce delas X in Y (npr. zahteven izracun in prikaz GUI-ja) lahko vedno naredis, da eden da drugemu dovolj casa za najbolj osnovne stvari tj. ni treba da je X in Y svoja nit.

Lahko malo bolj podrobno razložiš, kako bi se lotil tega? Recimo, da vem, da ko poženem nek izračun, bo ta za vsaj nekaj minut čisto obremenil procesor. Kako bi dosegel, da se GUI vseeno osvežuje, brez da je v svojem threadu?
Kdor ne navija ni Slovenc, hej, hej, hej!

BlueRunner ::

IMHO je problem niti to, da context switch tipicno ni najbolj hiter.


Privzemaš, da je ta aplikacija edina, ki v danem trenutku teče na sistemu. Kar je danes, razen na RT sistemih, nemogoče.

Ctx.sw. boš imel v vsakem primeru, saj ti ga bo kadarkoli naredilo jedro, ki izvaja predkupno večopravilnost (preemtive mtasking). Če bi vsi programi gonili svojo "idle" zanko, potem bi bilo delovanje takšnega sistema obremenjeno še z več preklopi konteksta, kot bi bilo nujno.

Če pa sporočilno zanko prepustiš sistemu (uporabiš semaforje, mutex-e, ...) potem pa jedro natančno ve katere niti opravljajo koristno delo, katere niti pa čakajo (so blokirane) na nek dogodek zunaj njih. S tem vedenjem pa potem jedro preprosto ne dela preklopa v tiste niti, ki v katere ne rabi preklapljati. Celotno delovanje sistema tako postane bolj optimalno.

Vse navedeno velja za sistemske niti. Uporabniške niti imajo svojo logiko delovanja, ki je neodvisna od sistema, hkrati pa je njihov izkoristek večopravilnostnih funkicj v jedru omejen. Je pa res, da delujejo brez ctx.sw., kar jih za določene naloge naredi izredno učinkovite. Še posebej, če abstrakcija problema napeljuje na vzporedno procesiranje (scatter - gather).

Seveda pa še vedno velja, da niti niso vedno pravi odgovor ali edini odgovor za vse tegobe tega sveta. Obstajajo tudi alternative, ki so za druge vrste problemov bolj uporabne in učinkovite. Tisti trenutek pa, ko začenja tvoj "message loop" postajati glavna procedura programa v kateri sam opravljaš svoj lasten "task scheduling", pa je to že razlog, da še enkrat oceniš pristop in se morebiti odločiš za niti.

Zgodovina sprememb…

BlueRunner ::

Ce delas X in Y (npr. zahteven izracun in prikaz GUI-ja) lahko vedno naredis, da eden da drugemu dovolj casa za najbolj osnovne stvari tj. ni treba da je X in Y svoja nit.

Lahko malo bolj podrobno razložiš, kako bi se lotil tega? Recimo, da vem, da ko poženem nek izračun, bo ta za vsaj nekaj minut čisto obremenil procesor. Kako bi dosegel, da se GUI vseeno osvežuje, brez da je v svojem threadu?


Dva načina:

  1. Tako kot se je včasih delalo cooperative multitasking, v glavni funkciji, kjer se procesirajo GUI sporočila za vsak IDLE klic, ki ti ga pošlje sistem, narediš en dovolj kratek korak izračuna, preden greš naprej. Tako narediš prekrivanje GUI procesiranja in lastnega v eni niti.

  2. Tako, da v svojo funkcijo v vsaki ponovitvi zanke, ali pa vsakih toliko operacij dodaš ekspliciten klic glavne funkcije v kateri se od sistema prevzame GUI sporočila, ki čakajo v vrsti in se jih obravnava. To je bil tudi edini možen vzorec v VB do verzije 6.0 (.NET je drugačna zver), kjer si odzivnost GUI-ja med računanjem zagotovil s stavkom "DoEvents", ki je sprocesiral nabrana GUI sporočila.

Zgodovina sprememb…

BigWhale ::

IMHO je problem niti to, da context switch tipicno ni najbolj hiter. Preden se zacne izvajati druga nit, se mora najprej shraniti stanje stare (registri itd.) in potem obnoviti stanje druge. To lahko vzame nekaj koristnega procesorskega casa. Vse skupaj sicer ni tako dolgo, ampak zanemarljiv pa ta cas glede na to, da se vse skupaj dogaja precej pogosto vseeno ni. Seveda je drugace, ce imas moznost, da niti res tecejo na vecih "procesorjih" istocasno (kakorkoli ze, npr. vecjedrniki so kar precej razsirjeni).


A danes obstaja se kak mainstream CPU, za osebne racunalnike, ki ne bi bil multicore? Pustimo embedded zadeve in podobne specializirane stvari. Pa tudi ze zaradi tega, ker imas multitasking OS je context-switch bolj tko-tko argument, ker do tega itak prihaja.

Takoj, ko imas vec jeder in je operacija, ki jo izvajas, daljsa od ustvarjanja in unicenja niti, se ti multithreading splaca. Sploh ce v vsaki niti asinhrono vleces neke podatke iz diska ali pa iz mreze.

Neko asinhrono-non-blocking telovadenje v istem threadu je potem bolj tko no. So 80's. ;) Poleg tega je vecina stvari dandanes taksnih, da jih je tezko kar tako narediti v non-blocking nacinu in vmes poceti kaj drugega je precej ceneje in hitreje, ce ustvaris thread, ki prebere jpg file iz diska in ga potem pokaze na ustreznem mestu v GUIju, takrat ko je stvar nalozena.

BlueRunner ::

Context switch ni zastonj in več kot jih je, bolj se to pozna na delovanju celotnega sistema. Tako da pretiravanje z nitmi tudi ni ravno smotrno. Zaradi preveč preklopov začneš izgubljati performance. Največja posledica vsakega preklopa na jedru pa je izpraznitev cevovoda, dodatno pa zaradi neuniformnosti dostopa do pomnilnika velikokrat dobiš tudi cache-miss, zaradi česar mora CPE čakati na relativno počasen glavni pomnilnik.

Zato se niti uporablja s pametjo, asinhrono non-blocking telovadenje v primeru I/O procesiranja pa je IMHO še vedno znak visoko performančne I/O arhitekture, pa četudi je to so 80's. Java je začela brez njega, pa so ga dodali. Apache je začel brez njega, pa so ga dodali. Pa mislim, da sta ta dva projekta kar relevantna.

Dodatek pa je, da lahko razen GUI niti za daljše mletje po disku še vedno ustvariti eno "worker" nit v kateri lahko potem delaš non-blocking I/O. Pa še to samo zato, ker je včasih klic sistemske I/O funkcije dolgotrajen, potem ti pa celoten GUI blokira, potem pa je lepo in pregledno, da I/O kodo umakneš v ločen modul in nit izvajanja. Tako se ti ne more zgoditi, da ti bo GUI kar nenadoma zmrznil, ker se npr. DNS strežnik ne odziva in čakaš omrežni timeout.

Po drugi strani pa mislim, da je skoraj kakršno koli dolgotrajno računanje, kjer je I/O minimalen ali ga pa ni (torej pred seboj nimam tipične strežniške aplikacije) praktično vedno sodi v ločeno nit. Še posebej, če se ga realizira kot eno operacijo.

Naj ljudje pluvajo kolikor hočejo po proceduralnem pristopu, vendar pa so računski postopki največkrat preprosto ena procedura, ki se jo mora izvršiti v eni potezi od začetka do konca, da je rezultat uporaben.

Zgodovina sprememb…

Brane2 ::

Mogoče sem kaj spregledal, ampak ne vidim nobene bistvene alternative nitim.

Pravzaprav se vse vrti okrog niti na tak ali drugačen način.

Kar se overheada tiče, je to relativno. Ko poskušaš razdeliti neko breme na več coreov, to breme najbbrž ni ravno majhno in valjda moraš računati z nekimi stroški režije. Če pa si trapast in kreiraš niti za vsak prdec, to je druga stvar, ampak takrat niti ni problem v samem nitenju...
On the journey of life, I chose the psycho path.

BlueRunner ::

No, Java je v v mladih letih zahtevala, da ustvariš nit za vsako bedarijo. Sicer so bile v JVM to user niti, vendar vseeno. Stvar je bila že neokusna.

Več jeder pa dejansko pomeni nižjo režijo in ne višjo, saj imaš efektivno manj menjav konteksta, manj izpraznjenj cevovoda in manj kiksov v predpomnilniku. Idealno v Von Neumannovi arhitekturi pa je, če imaš NUMA sistem, kjer so CPE-ji na ločenih vodilih povezani s pomnilnikom, ki je neposredno "priklenjen" na določen CPE. Potem podatke za procesiranje prestaviš v pravi del pomnilnika in na pravem CPE izvajaš nit za njihovo obdelavo, s čemer olajšaš delo predpomnilniku, razbremeniš vodilo in zmanjšaš število menjav konteksta na posamičen CPE.

Skoraj že zelo integrirana gruča znotraj računalnika... IBM xSeries so včasih uporabljali ta pristop, danes pa verjetno tudi še marsikdo drug.

V sivem območju med "en prdec" in "delo, ki je idealno za vzporedno procesiranje" pa je potrebno uproabljati razmislek, kaj predstavlja manj dela pri postavitvi in manj dela pri kasnejšem vzdrževanje. Pa to območje mislim, da ni tako zelo majhno.

noraguta ::

Naj ljudje pluvajo kolikor hočejo po proceduralnem pristopu, vendar pa so računski postopki največkrat preprosto ena procedura, ki se jo mora izvršiti v eni potezi od začetka do konca, da je rezultat uporaben.


v funkcijskih jezikih kritične sekcije niso prav nič manjše čudo , kot v proceduralnih ali objektnih. itak pa vsaj zame objektno ni prav nič drugega kot kontekstno vezanje procedure na neko strukturo.

@brane je ker so niti primitivi razširjenih operaciskih sistemov. so pa alternative.
Pust' ot pobyedy k pobyedye vyedyot!

Zgodovina sprememb…

  • spremenilo: noraguta ()

Brane2 ::

Več jeder pa dejansko pomeni nižjo režijo in ne višjo, saj imaš efektivno manj menjav konteksta, manj izpraznjenj cevovoda in manj kiksov v predpomnilniku.


Po drugi strani pa rabiš semaforje, spinlocke in whatnote za sihronizacijo kritičnih opravil.
Stvar je na SMP sistemih lahko še zabavnejša, ko je treba sinhronizirati sockete, na NUMA sistemih pa še za stopnjo zabavnejša, ko prideš v situacijo, da ti en socket intenzivno šari po RAMu drugega skozi tretjega...



Idealno v Von Neumannovi arhitekturi pa je, če imaš NUMA sistem, kjer so CPE-ji na ločenih vodilih povezani s pomnilnikom, ki je neposredno "priklenjen" na določen CPE. Potem podatke za procesiranje prestaviš v pravi del pomnilnika in na pravem CPE izvajaš nit za njihovo obdelavo, s čemer olajšaš delo predpomnilniku, razbremeniš vodilo in zmanjšaš število menjav konteksta na posamičen CPE.


Po drugi strani pa, če ti za ta task ni dovolj en socket ( torej pripadajoči QC ), bodisi dupliraš ta ram na drugih socketih, bodisi zagiftaš HT kanale, lahko pa seveda tudi oboje...


V sivem območju med "en prdec" in "delo, ki je idealno za vzporedno procesiranje" pa je potrebno uproabljati razmislek, kaj predstavlja manj dela pri postavitvi in manj dela pri kasnejšem vzdrževanje. Pa to območje mislim, da ni tako zelo majhno.


O.K. Ampak kaj pa je alternativa, ki bi zahtevala bistveno manj režije ? Težko si zamisliš kaj bolj low-fat od threada.
Kontekst switch za thread je poleg registrov CPUja mogoče še kazalec na thread-specific stuff.
Karkoli boš počel z več corei, bo zahtevalo praktično vsaj to...
On the journey of life, I chose the psycho path.

BlueRunner ::

v funkcijskih jezikih kritične sekcije niso prav nič manjše čudo , kot v proceduralnih ali objektnih. itak pa vsaj zame objektno ni prav nič drugega kot kontekstno vezanje procedure na neko strukturo.


Nisem ciljal na kritične sekcije ampak na atomarnost računskih postopkov, kjer so delni rezultati nepomembni, šteje samo končen rezultat. Npr. kompresija ali pa enkripcija. Dokler nit ne opravi svojega, toliko časa tudi z njenimi vmesnimi podatki mima kaj za početi, sinhronizacija pa je prisotna samo na začetku (create) in na koncu (join).

Zabava pa se začne tisti trenutek, ko imaš en blok pomnilnika po katerem želi šariti več ločenih niti/jeder/socketov/sistemov/whatnot. Ko pa prideš do takšnih težav, pa se začneš ozirati po alternativah, ki to olajšajo delo in zagotavljanje pravilnosti, ne pa nujno optimalnosti rešitve.

To pa je bilo tudi izhodišče tistega na začetku polinkanega poročila: ko prideš to takšnih programskih zahtev, je samo z osnovnimi gradniki težko narediti rešitev za katero si upaš reči, da je vodoodporna. Edina "tolažba" pa je, da tudi enonitno procesiranje v takšnih primerih odpade kot zrela hruška. Kar pomeni, da boš imel tako ali drugače več niti, samo z njimi ne želiš delati neposredno temveč preko nekih abstrakcij.

noraguta ::

O.K. Ampak kaj pa je alternativa, ki bi zahtevala bistveno manj režije ? Težko si zamisliš kaj bolj low-fat od threada.
Kontekst switch za thread je poleg registrov CPUja mogoče še kazalec na thread-specific stuff.
Karkoli boš počel z več corei, bo zahtevalo praktično vsaj to...


poenoten naslovni prostor. kjer te sprehajanje pojnterja res praktično ne stane nič. skenslaš shared memory ter za sinhronizacijo uvedeš kanale(ti imajo nadalje tudi svoj ekvivalen v meži). ampak to je že izven dometa "običajnih" OSev.
Pust' ot pobyedy k pobyedye vyedyot!

noraguta ::

Zabava pa se začne tisti trenutek, ko imaš en blok pomnilnika po katerem želi šariti več ločenih niti/jeder/socketov/sistemov/whatnot. Ko pa prideš do takšnih težav, pa se začneš ozirati po alternativah, ki to olajšajo delo in zagotavljanje pravilnosti, ne pa nujno optimalnosti rešitve.


hja proceesne algebre , actorji , etc... kar dosti bolje globalno rešujejo omenjene probleme kot , če pacaš svoj state machine. sicer locki , semaforji mutexi etc itak ni nič drugega kot simpl state machine nad CS. razen če res ne veš kaj počneš.

sicer pa predd cajtom sem mislim , da na lambdi našel članek kateri se je poglobil v sam HW, ter predlagal nekatere spremembe v obstoječih arhitekturah, ukvarjal pa se je predvsem z transakcijskim pomnilnikom. reference pa dajle žal ne najdem bom pobrskal , če je kje na disku.
Pust' ot pobyedy k pobyedye vyedyot!

jype ::

No, glede na to da sem bil tudi sam vpleten v ta flame na #python na freenode moram povedat, da sem večino (razen uporabnika lvh, ki je očitno znalec in s katerim se nisem želel prerekati, ker je konec koncev tvoja priljubljena paradigma vedno stvar osebne preference) na koncu prepričal, da threading model ni kar za v smeti.

Smo si bili pa precej složni glede dejstva, da python nima ustrezne infrastrukturne podlage za učinkovito delo z nitmi in da so niti v Javi rešene dovolj dobro, da je večnitno programiranje v Javi vsaj znosno.

Sam se tudi strinjam, da programiranje s threadi pri začetnikih povzroča več težav, kot jih rešuje, ker zahteva precej poglobljeno znanje, hkrati pa seveda ne morem reči, da non-threading infrastruktura vzporednega izvajanja (asyncore, forking, ipc, shared mem, semaforji) ni totalno konfuzna (spet, ko govorimo o začetnikih).

Zgodovina sprememb…

  • spremenilo: jype ()

darkolord ::

Smo si bili pa precej složni glede dejstva, da python nima ustrezne infrastrukturne podlage za učinkovito delo z nitmi in da so niti v Javi rešene dovolj dobro, da je večnitno programiranje v Javi vsaj znosno.

Sam se tudi strinjam, da programiranje s threadi pri začetnikih povzroča več težav, kot jih rešuje, ker zahteva precej poglobljeno znanje, hkrati pa seveda ne morem reči, da non-threading infrastruktura vzporednega izvajanja (asyncore, forking, ipc, shared mem, semaforji) ni totalno konfuzna (spet, ko govorimo o začetnikih).
Mimogrede, .NET Framework 4 ima/bo imel vključen Parallel Extensions, ki na izjemno enostaven (npr Parallel.For in Parallel.ForEach) in zanesljiv način (samodejno kreiranje/terminiranje niti, skaliranje glede na število procesorjev itd) omogoča paralelizacijo določenih nalog. Kratek opis iz Wikipedije

Zgodovina sprememb…

noraguta ::

Sam se tudi strinjam, da programiranje s threadi pri začetnikih povzroča več težav, kot jih rešuje, ker zahteva precej poglobljeno znanje, hkrati pa seveda ne morem reči, da non-threading infrastruktura vzporednega izvajanja (asyncore, forking, ipc, shared mem, semaforji) ni totalno konfuzna (spet, ko govorimo o začetnikih).

men se še zdaj zdi težko, sploh pa debugiranje, ali buljenje v loge ali debuger kje sem zadevo zajebal.
Pust' ot pobyedy k pobyedye vyedyot!

noraguta ::

Smo si bili pa precej složni glede dejstva, da python nima ustrezne infrastrukturne podlage za učinkovito delo z nitmi in da so niti v Javi rešene dovolj dobro, da je večnitno programiranje v Javi vsaj znosno.

Sam se tudi strinjam, da programiranje s threadi pri začetnikih povzroča več težav, kot jih rešuje, ker zahteva precej poglobljeno znanje, hkrati pa seveda ne morem reči, da non-threading infrastruktura vzporednega izvajanja (asyncore, forking, ipc, shared mem, semaforji) ni totalno konfuzna (spet, ko govorimo o začetnikih).
Mimogrede, .NET Framework 4 ima/bo imel vključen Parallel Extensions, ki na izjemno enostaven (npr Parallel.For in Parallel.ForEach) in zanesljiv način (samodejno kreiranje/terminiranje niti, skaliranje glede na število procesorjev itd) omogoča paralelizacijo določenih nalog. Kratek opis iz Wikipedije

kar v praksi pomeni le , hitrejše kodiranje(nekaj več scenarijev obdelanih). ne rešuje pa kaj bistveno osnovnih problemov paralelizacije. je pa joe duffy z ekipo pri razvoju odkril nekaj pomankljivosti na relaciji .NET - win katere so vključili v clr.
Pust' ot pobyedy k pobyedye vyedyot!

jype ::

darkolord> Mimogrede, .NET Framework 4 ima/bo imel vključen Parallel Extensions, ki na izjemno enostaven (npr Parallel.For in Parallel.ForEach) in zanesljiv način (samodejno kreiranje/terminiranje niti, skaliranje glede na število procesorjev itd) omogoča paralelizacijo določenih nalog.

Ja, to je eden najimenitnejših dosežkov .NET okolja. Od dejanske implementacije bo sicer odvisno, če bo reč uporabna v večini primerov (tako pri cpu bound kot pri i/o bound threadih, kako bo dejansko rešen lock contention v prvem primeru in kako dober bo scheduler pri posamezni arhitekturi pri razbijanju takih konstruktov na več jeder oz. procesorjev) ali bo le konstrukt, ki magično zagotavlja stabilno, a podpovprečno zmogljivost (tako, kot jo v Javi dosežeš, če je kar vsaka reč "synchronized").

Bomo pogledali source od monota, ko bo prišel do različice 4 :)

noraguta> men se še zdaj zdi težko, sploh pa debugiranje, ali buljenje v loge ali debuger kje sem zadevo zajebal.

Ja, ne rečem, da ni, ampak k temu precej pripomore predvsem nepremišljena platforma. Tudi ostale paralelizacijske paradigme glede tega niso nič boljše, jih pa taki in drugačni jezikovni konstrukti lahko naredijo razumljivejše in bistveno olajšajo vse, kar si naštel.

Zgodovina sprememb…

  • spremenilo: jype ()

noraguta ::

Od dejanske implementacije bo sicer odvisno, če bo reč uporabna v večini primerov (tako pri cpu bound kot pri i/o bound threadih, kako bo dejansko rešen lock contention v prvem primeru in kako dober bo scheduler pri posamezni arhitekturi pri razbijanju takih konstruktov na več jeder oz. procesorjev) ali bo le konstrukt, ki magično zagotavlja stabilno, a podpovprečno zmogljivost (tako, kot jo v Javi dosežeš, če je kar vsaka reč "synchronized").

šeduler je pri javi ali .net vedno stvar operacijskega sistema(ja uporabljata primitive osa, erlang je recimo svoja žvau , ki se ne gre te zgodbe). async za javo nisem ziher za .net pa sem pa ni problem. async se na ravni jezika reši precej trivialno.
Pust' ot pobyedy k pobyedye vyedyot!

Zgodovina sprememb…

  • spremenilo: noraguta ()

jype ::

noraguta> šeduler je pri javi ali .net vedno stvar operacijskega sistema

Ja, jasno. Na platformah, kjer jaz delam, je praviloma reč bodisi odlična (Linux, OpenSolaris) ali porazna (npr. OpenBSD, VMS).

Brane2 ::

poenoten naslovni prostor. kjer te sprehajanje pojnterja res praktično ne stane nič. skenslaš shared memory ter za sinhronizacijo uvedeš kanale(ti imajo nadalje tudi svoj ekvivalen v meži). ampak to je že izven dometa "običajnih" OSev.


Ne vidim, kako je to alternativa threadom, kvečjemu dopolnitev.
Poleg tega, threadi imajo enoten naslovni prostor. Prehod z enega threada na drugi in nazaj te ne stane veliko.

Prehod med procesi je druga pesem, ampak ne vidim kako bi tu kaj spremenil. Mislim, ti lahko patchaš kernel in to uštimaš zelo hitro, ampak obstoječe programje pričakuje izolacijo.

Tudi če urediš, da se recimo vsak program naloži na svoj naslov in ravno tako shared lib ( hardened kernel to itak počne, vendar iz drugih vzrokov), še vedno najbrž ne bo vsak program lahko imel dostop do vseh shareanih lib-ov, ki so trenutno zlinkani, torej bodo potrebne spremembe TLB tabele ali kar kazalca nanjo, to pa pomeni TLB flush.

Kakorkoli že, tudi če ti rata, to ne bo nadomestilo niti, kvečjemu ponekod potrimalo nekaj maščobe...
On the journey of life, I chose the psycho path.

Brane2 ::

Mi pa manjka druga stvar- recimo temu sonitenje.

Tu mislim na recimo 4 niti, ki se izvajajo paralelno in za katere programer lahko ve, da ko bo nek core začel s sonitjo, bodo na preostale sonitke skočili vsi preostali prosti corei in vsak core bo vedel, katero vlogo igra v tej skupini on koliko jih je v skupini.

To bi bilo fajn imeti zaradi modernih QC mašin, kjer lahko coeri preko L3 učinkovito sodelujejo med seboj. Tako lahko vsi štrije naenkrat obdelujejo paketke nekega streama, ki ga je treba skomprimirati in si med seboj podajajo podatke.

Prednost za uporašbnika je v tem, da podatki ne zapustijo cachea in da opravilo, poleg tega, da vzame manj CPU ciklov vsega skupaj, se tudi dejansjko hitreje izvede.


Tega sedaj nimaš. Ti lahko odpreš threade, ne moreš pa vedeti ničesar o tem, kdaj se bodo izvajali...
On the journey of life, I chose the psycho path.

BlueRunner ::

Thread affinity... Kdor želi iztisniti vse do zadnje kapljice in ima namenski strežnik za samo eno samo aplikacijo, lahko sam dopove sistemu kaj paše na katero jedro in tako posamezne naloge konsolidira glede na skupen L3 predpomnilnik na socketu. OS brez pomoči aplikacije bo le težko "uganil" kaj sodi skupaj in kaj ne.

Tukaj pa nastopijo napredne knjižnice s pomočjo katerih se lahko lotiš tudi tega problema.

Ampak to je počasi že področje HPC. Realno verjetno ni šans, da bi kaj takšnega srečali v "navadnih" centrih. Razen morda pri naštudirani in zelo agresivni virtualizaciji, kjer VM-je vežeš na en socket ravno zato, da ni preveč zgrešitev v L3.

Brane2 ::

Poglej si AMDjev User Manual v delu, ki govori o sodelu vseh coreov na Phenomu in premetavanju podatkov med njimi.

Tam ti ni zadosti samo affinity, pravzaprav ti je boljkone neuporaben, sploh če imaš itak samo en socket.

Ti tam rabiš vpliv na to, _kdaj_ se nek thread požene bolj kot to kje lahko teče.
On the journey of life, I chose the psycho path.

BlueRunner ::

Spinlock, hallowed be thy name. >:D

Affinity ga pripne na jedro, spinlock pa držiš nad lokacijo, ki bi morala ostati v L3. Če zagotoviš, da na jedru ni drugih niti (HPC okolje), potem bi moralo delovati.

Seveda pa so predpogoji za kaj takšnega pri GP computing popolna bedarija. To je bolj akademsko razmišljanje...

Zgodovina sprememb…

Brane2 ::

Deadly tool in a hand of a fool...
On the journey of life, I chose the psycho path.

BlueRunner ::

Eh, sorry. Vmes sem še pripisal.

Ampak da: a deadly tool indeed.

Brane2 ::

Spinlock je fajn, če misliš čakat pardeset nanosekund in če je možnost čakanja relativno majhna.

Ne moreš pa zdaj it v spinlock in čakat da scheduler nakloni pozornost še ostalim sothreadom in jih poči na ostale core.

Efekt čakanja bi totalka ubil vse pričakovane koristi.

Za dosego cilja rabiš ne samo da se željeni threadi izvedejo na skupini coreov, ampak da štartajo _sočasno_ .
On the journey of life, I chose the psycho path.

BlueRunner ::

Staggered je bolj realno. Latenca trpi, vendar pa pridobiš na propustnosti.

darkolord ::

kar v praksi pomeni le , hitrejše kodiranje(nekaj več scenarijev obdelanih). ne rešuje pa kaj bistveno osnovnih problemov paralelizacije
Absolutno. Ampak to, da ponavadi samo kodiranje (in debugganje) ni čisto trivialno, je glavni vzrok, da se multithreading tako malo uporablja, tudi tam, kjer je problem čisto preprost in bi na relativno enostaven način pridobil ogromno - tega pa je precej.

Brane2 ::

Staggered je bolj realno. Latenca trpi, vendar pa pridobiš na propustnosti.


Staggered je v ta namen neuporaben. Rabiš komunikacijo posameznih threadov, kisi po tekočem traku podajajo podatke, preden ti zapustijo L3.
On the journey of life, I chose the psycho path.

noraguta ::

poenoten naslovni prostor. kjer te sprehajanje pojnterja res praktično ne stane nič. skenslaš shared memory ter za sinhronizacijo uvedeš kanale(ti imajo nadalje tudi svoj ekvivalen v meži). ampak to je že izven dometa "običajnih" OSev.


Ne vidim, kako je to alternativa threadom, kvečjemu dopolnitev.
Poleg tega, threadi imajo enoten naslovni prostor. Prehod z enega threada na drugi in nazaj te ne stane veliko.

Prehod med procesi je druga pesem, ampak ne vidim kako bi tu kaj spremenil. Mislim, ti lahko patchaš kernel in to uštimaš zelo hitro, ampak obstoječe programje pričakuje izolacijo.

Tudi če urediš, da se recimo vsak program naloži na svoj naslov in ravno tako shared lib ( hardened kernel to itak počne, vendar iz drugih vzrokov), še vedno najbrž ne bo vsak program lahko imel dostop do vseh shareanih lib-ov, ki so trenutno zlinkani, torej bodo potrebne spremembe TLB tabele ali kar kazalca nanjo, to pa pomeni TLB flush.

Kakorkoli že, tudi če ti rata, to ne bo nadomestilo niti, kvečjemu ponekod potrimalo nekaj maščobe...

Singularity (operating system) @ Wikipedia

je v tej smeri kot razmišljaš. edino niti v tem kontekstu dobijo drugačno konotacijo. sicer pa nit ali proces nista tako različni zveri. shared memory ter slabo definiran kontekst funkcije pa sta rak rana "dobrega" programiranja. "shared funkcije" še vedno lahko obstajajo, ne morejo pa več šarit po memoryu odjemalca. saj na koncu se sliši nepomembno, ampak na koncu kolikor sem se pouspel poigrat je podobna exceptionom. v lispu so to zaradi koncepta poceni stvari v .net , javi , c++ pa relativno drage. in če je v lispu zadeva praktično in general sprejemliva za control flow je v omenjenih imperativcih odsvetovana zaradi performančnih razlogov.
Pust' ot pobyedy k pobyedye vyedyot!

Brane2 ::

Nisem ciljal na kritične sekcije ampak na atomarnost računskih postopkov, kjer so delni rezultati nepomembni, šteje samo končen rezultat. Npr. kompresija ali pa enkripcija. Dokler nit ne opravi svojega, toliko časa tudi z njenimi vmesnimi podatki mima kaj za početi, sinhronizacija pa je prisotna samo na začetku (create) in na koncu (join).


Ravno sedaj imam pred seboj problem tega tipa. Sem se spravil napisat programček, ki bo na mojem Gentooju pregledal vse fajle v podanih mapah in ugotovil, ali pripadajo inštaliranemu paketu oziroma so nek neznan ostanek oziroma posledica kake ročne inštalacije. Če gre za fajl, ki je del uradno inštailranega paketa pa naj bi preveril še md5hash.

md5sum je programček iz coreutils paketa in tega očitno kliče Gentoo infrastruktura za izračun in preverbo hasha.

Glede na to, da teh datotek ni ravno malo, se mi ni dalo za vsako ročno klicati iz svoje C kode md5sum, mu pripravljati podatke in brati rezultate, ampak sem se spravil napisat rutino.

Najprej sem pogledal v Wikipedijo, nato še ustrezni RFC ( 1231 mislim) in nato sem rabil še 5 minut, da se mi je pogled zbistril in so se oči lahko normalno fokusirale. >:D

NAto sem se spomnil, da je v kernelu enkripcijska sekcija in v njej tudi md5 in sem šel pogledat implementacijo.
NAto sem jo primerjal z implementacijo md5 v md5sum in določene stvari so se razjasnile, ampak pokazalo se je, da je md5 jebeno težak za pospeševanje s paralelnim izračunavanjem.

V prvem trenuktu me je zbodlo to, da stvar implementirana kar v Cju, brez asm vstavka, kar je nenavadno glede na to, da je avtor Ulrich Drepper, ki mu asm sploh ni tuj.

Potem sem dojel zakaj. Spraviti to v paralelno ali kakorkoli pospešeno obliko je vsaj enakovredno waterboardingu.
Moje sanje, da bi stvar razturil s SSE enoto so ostale sanje. Pravzaprav še toliko ne. Md5 jih je pwnal.

Nekje na netu naj bi bila neka implementacija MD5 s SSE-2 ukazi, a linki do nje ne delujejo. Najbrž je internet umrl od smeha ob pogledu nanjo.


Je pa ta koda zanimiv problem. Vsaka pi*arija je odvisna od vsake prejšnje na N ortogonalnih načinov.
Kljub temu vsaj mislim, da vidim njene slabosti ( zakaj so jo razsuli ) in da se jo bo tudi zaradi tega dalo vsaj v neki meri pospešiti.

Zanimiva zadeva. Trdovratna, ampak tudi jaz sem balkanec. Če lahko sparaleliziram to, potem je navadndo programje šala... >:D
On the journey of life, I chose the psycho path.

Zgodovina sprememb…

  • spremenil: Brane2 ()

noraguta ::

ah atomarnost je pri simpl for zanki ravno toliko pomembna kot pri md hashih. in ja da se zjebat for z zanko, to vsi vemo samo včasih pozabimo(vključno z mano).
Pust' ot pobyedy k pobyedye vyedyot!

darkolord ::

Brane2: nameravaš paralelizirat hashanje posameznih fajlov + sam hashing algortim?

Zgodovina sprememb…

Brane2 ::

Brane2: nameravaš paralelizirat hashanje posameznih fajlov + sam hashing algortim?


Glede na prepustnost CPUja paralelno hashanje fajlov nima veliko smisla, ker je stvar bistevno hitrejša od drivea.

Sedaj mislim, das bo standardna izpeljava zadosti dobra ( ne mislim se sedaj zaj* s tem) ampak mislim da so neke bližnjice pri samem hashing algoritmu. Jasno pa je, da bo šele test pokazal, če so to res bližnjice ali daljšnice. >:D

Če ne drugega, je SSE fajn zaradi kojekakvih swap instrukcij, s katerimi lahko hitro premetavaš registre n zaradi veliko dosegljivih bitov ( 16 širokih registrov ). Po drugi strani pa ima samo 2+1 eksekucijske enote...
On the journey of life, I chose the psycho path.

darkolord ::

Glede na prepustnost CPUja paralelno hashanje fajlov nima veliko smisla, ker je stvar bistevno hitrejša od drivea.
Če maš velik manjših fajlov, zlo velik del zgubiš s seekanjem in je čist možno, da bi blo precej hitrejš, če bi v enem threadu hashal, medtem ko drugi thread čaka na I/O. Razen če maš SSD :)

Torej če maš en 200 kilo fajl, ga prebereš in v milisekundi pohashaš, pol pa 5-15 milisekund čakaš na naslednjega :)

Zgodovina sprememb…

Brane2 ::

Že, ampak ko si en del fajla dobil, že lahko zahtevaš novega, medtem ko hashaš.

Ker si hitrejši od diska ene 5krat tudi če seek timeov ne bi bilo, ni frke.
On the journey of life, I chose the psycho path.

BlueRunner ::

Mmap in toliko threadov, kolikor je fizičnih diskov. Ta naloga je čisto I/O bound, tako da več niti ne bo ničesar spremenilo. Analogija je mount pri zagonu sistema, kjer se ti izplača sočasno fork-niti toliko mountov, kolikor je diskov. Če bi fork-nil več mountov za en disk, potem si bi lahko pri preverjanju konsistence fs + potencialen fsck neoptimalno polomili zobe. (Jaaaa, vem da dnevniki ta problem odpravljajo, ampak po konceptu je to sorodna naloga: veliko I/O po celotni površini diska in nekaj malega porabljenega CPU-ja)

Če odmisliš fragmentacijo, potem je sekvenčno branje vsake posamične datoteke iz diska še najhitrejša varianta. Več diskov, več sočasno branih datotek.

Brane2 ::

Ah, ni panike. Tako daleč ni treba.

Sem imel probleme s tem ( inštalacija Gentooja zna biti hairy ) in sem končal s kupom knjižnic in podobne navlake, ki jih uradno ni bilo gor.

Zato sem moral skup spraskat skript, ki je za vsak fajl, ki ga je našel v /lib in /usr lib šel preverjat, kateremu paketu pripada z "equery belongs /lib/libmylib.so.X.X" in to je traaajalo cel dan.

Če naredim soliden C, sem problem rešil trajno. Zadnja milisekunda niti ni pomembna.
On the journey of life, I chose the psycho path.

Mavrik ::

A ni veliko hitreje in lažje preprosto povprašati portage o seznamu vseh inštaliranih fajlov, dobit seznam vseh fajlov na disku in poiskati sirote?
The truth is rarely pure and never simple.

Brane2 ::

Takrat mi to niti ni padlo na pamet. Rabil sem quickfix, s tem da sem lahko pustil mašino mleti ( domov sem se itak vrnil naslednji dan).

Poleg tega pa niti ne vem, kako bi to izpeljal tako na brzino v bashu.

Poleg tega pa prihaja do kolizij in v takem primeru hočem vedet, točno kateremu paketu pripada inkarnacija nekega fajla.
On the journey of life, I chose the psycho path.

jype ::

BlueRunner> Ta naloga je čisto I/O bound, tako da več niti ne bo ničesar spremenilo.

Tako je.

Mavrik> A ni veliko hitreje in lažje preprosto povprašati portage o seznamu vseh inštaliranih fajlov, dobit seznam vseh fajlov na disku in poiskati sirote?

Seveda.

something that lists installed files in $(something that lists all installed packages) > allfiles
find / | grep -v -f allfiles

Zgodovina sprememb…

  • spremenilo: jype ()

Brane2 ::


Seveda.

something that lists installed files in $(something that lists all installed packages) > allfiles
find / | grep -v -f allfiles


Ne dela. Dobim seznam ~45k fajlov, obkaterem se grep zagifta s sporočilom "invalid regular expression" nekje na polovici.

Sem probal vzet samo prvih 11k linij, pa sicer kao neki dela ampak vleče se ko šmrkelj. Po eni uri sem prekinil zadevo, ne da bi dala karkoli od sebe.
On the journey of life, I chose the psycho path.
«
1
2


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

Asinhronost

Oddelek: Programiranje
122347 (2116) mihies
»

Hitrost Linuxovega jedra skozi čas (strani: 1 2 3 )

Oddelek: Novice / Operacijski sistemi
10824801 (20081) Icematxyz
»

c# debugger noce ujeti exceptiona!!

Oddelek: Programiranje
161395 (1066) BlueRunner
»

Niti (threads)

Oddelek: Programiranje
141800 (1468) snow
»

Desktop aplikacije večinoma niso multithreaded??? (strani: 1 2 )

Oddelek: Programiranje
554639 (3885) Gundolf

Več podobnih tem