Več

Ali bodo osnovne funkcije QGIS izkoristile večnitnost?

Ali bodo osnovne funkcije QGIS izkoristile večnitnost?


Po branju Omogočanje večnitne obdelave v QGIS? Me zanima, ali bo QGIS 2.6 to vključeval med izvajanjem različnih procesov. Preveril sem na spletu in to sem lahko le našel upodabljanje z več nitmi je bil uveden v QGIS 2.4 (predvidevam, da bo spet na voljo v 2.6). Zdaj je zemljevide mogoče zelo hitro prerisati, še posebej, če se ukvarjate z velikimi nabori podatkov.

Prebral sem, da je dokaj težko vključiti večnitne funkcije v osnovno funkcionalnost in da uporabnikom svetujemo, da manipulirajo s kodo Python, da bi to dosegli, na primer pri vzporednem izvajanju GIS operacij v PyQGIS ?.

Preveril sem tudi zahtevo za funkcijo, vendar jo je Tim Sutton zaprl že 9 mesecev, zadnji komentar pa je bil:

"To zaključujem - Martin Dobias ima izvedbo v podružnici, ki bo po QGIS 2.2 združena."

Ali bodo nekatere funkcije v QGIS 2.6 izkoriščale večnitnost (ali bo spet osredotočena na upodabljanje) in če ne, se bo to spremenilo pri QGIS 3.0?


Mislim, da je odgovor za QGIS 3.0 mogoče najti v tem nedavnem pogovoru, objavljenem v Nabble:

Ali bo obdelava v QGIS 3 podpirala paralelizacijo?

Citiram Nyall Dawson:

Če ste po paralelizaciji znotraj en algoritem (npr. funkcije medpomnjenja z več nitmi), potem ne poznam nobenih načrtov za to.


Prikaz samo v tem trenutku (QGIS 2.6).

Z Martinom sva govorila o nekakšnem generičnem API-ju z navojnimi postopki, toda trenutno gre le za pogovore.


V: Kdaj naj uporabljate večnitnost?

A: & quot; Vaše vprašanje je zelo široko. Malo je netrivialnih sistemov, kjer je funkcionalnost mogoče preprosto, hitro in zanesljivo izpolniti samo z eno nitjo. Na primer: [izberi tipičen sistem, ki ga prodaja ciljno podjetje, in izberi nekaj vidikov njegove funkcije, ki bi jih bilo bolje odšteti - težka CPU, komunikacija, več uporabnikov - samo izberi nekaj verjetno in pojasnilo].

V: Ali bi bilo večnitnost koristno, če različne niti izvajajo medsebojno neodvisne naloge?

O: & quotOdvisno od tega, kaj mislite z "izvrševanjem nalog". Večnitnost bi bila zagotovo koristna, če niti sočasno obdelajo medsebojno neodvisne podatke - zmanjšuje zahteve za ključavnice in verjetnost mrtvih blokov se super linearno povečuje s številom ključavnic. OTOH, pri nitih, ki izvajajo isto kodo, ni težav, to je varno in zelo pogosto. & Quot


3 odgovori 3

Operacijski sistem ponuja časovna rezinas CPU v niti, ki so primerne za zagon.

Če je samo eno jedro, potem operacijski sistem razporeja najustreznejšo nit, ki naj se v tem jedru izvaja za časovni rez. Po zaključku časovne rezine ali ko se izvajajoča nit blokira na IO ali ko procesor prekinejo zunanji dogodki, operacijski sistem ponovno oceni, katero nit naj zažene naslednji (in lahko znova izbere isto nit ali drugo).

Upravičenost do kandidature je sestavljena iz različic glede poštenosti, prednostnih nalog in pripravljenosti, pri čemer različne niti dobijo časovne rezine, nekatere več kot druge.

Če je več jeder, N, potem operacijski sistem razporeja najustreznejše N niti, ki naj se izvajajo na jedrih.

Afiniteta procesorja je vprašanje učinkovitosti. Vsakič, ko CPU zažene drugačno nit kot prej, se ponavadi nekoliko upočasni, ker je njen predpomnilnik topel za prejšnjo nit, hladen pa za novo. Tako je izvajanje iste niti na istem procesorju v številnih časovnih rezinah prednost v učinkovitosti.

Vendar pa operacijski sistem lahko ponuja časovne rezine ene niti na različnih CPU-jih in se lahko vrti skozi vse CPU-je na različnih časovnih rezinah. Vendar pa, kot pravi @ gnasher729, ne more zagnati ene niti na več CPU hkrati.

Hyperthreading je metoda v strojni opremi, s katero se en sam okrepljeno Jedro CPU lahko podpira izvajanje dveh ali več drugačen niti hkrati. (Tak CPU lahko v silicijevih nepremičninah ponudi dodatne niti z nižjimi stroški kot dodatna polna jedra.) To izboljšano jedro procesorja mora podpirati dodatno stanje za druge niti, kot so vrednosti registra CPU, in ima tudi stanje koordinacije in ojačevalnika, ki omogoča skupno rabo funkcionalnih enot znotraj tega CPU-ja, ne da bi se povezale niti.

Hyperthreading, čeprav je s programske perspektive tehnično zahteven, je izvedbeni model zgolj model dodatnih procesorskih jeder in ne kaj bolj zapletenega. Torej, operacijski sistem vidi dodatna jedra CPU, čeprav je nekaj novih težav z afiniteto procesorja, saj si več hipernitnih niti deli eno arhitekturo predpomnilnika jedra CPU.

Morda bi naivno mislili, da dve niti, ki se izvajata na hipernitnem jedru, delujeta pol hitreje, kot bi vsaka s svojim polnim jedrom. Vendar to ni nujno tako, saj je izvedba ene niti polna ohlapnih ciklov, nekaj pa jih lahko uporabi druga hipernitna nit. Nadalje lahko tudi med ciklusi brez ohlapnosti ena nit uporablja drugačne funkcionalne enote kot druga, zato lahko pride do sočasne izvedbe. Izboljšani CPU za hipertekanje ima lahko še nekaj nekaterih zelo pogosto uporabljenih funkcionalnih enot, posebej v podporo temu.

Ne obstaja ena sama nit, ki bi se izvajala na več jedrih hkrati.

Ne pomeni pa, da navodil iz ene niti ni mogoče izvajati vzporedno. Obstajajo mehanizmi, imenovani cevovod navodil in izvrševanje brez naročila ki to omogočajo. Vsako jedro ima veliko odvečnih virov, ki jih preprosta navodila ne izkoristijo, zato je mogoče več takih navodil zagnati skupaj (če naslednje ni odvisno od prejšnjega rezultata). Vendar se to še vedno dogaja znotraj enega jedra.

Hiper-nit je nekakšna skrajna različica te ideje, pri kateri eno jedro ne izvaja le vzporedno navodil iz ene niti, temveč meša navodila iz dveh različnih niti, da še bolj optimizira uporabo virov.

povzetek: Iskanje in izkoriščanje vzporednosti (na ravni navodil) v enonitnem programu poteka izključno v strojni opremi s pomočjo jedra CPU, na katerem deluje. In le čez okno nekaj sto navodil, ne obsežnega preurejanja.

Programi z enim navojem nimajo koristi od večjedrnih procesorjev, razen tega drugo stvari lahko tečejo na drugih jedrih, namesto da bi si vzeli čas za enonitno opravilo.

OS organizira navodila vseh niti tako, da ne čakajo drug na drugega.

OS NE gleda znotraj tokov navodil niti. Nite razporeja samo na jedra.

Pravzaprav vsako jedro zažene funkcijo načrtovalnika OS, ko mora ugotoviti, kaj storiti naprej. Razporejanje je porazdeljeni algoritem. Če želite bolje razumeti večjedrne stroje, si oglejte vsako jedro kot zagnano jedro posebej. Tako kot večnitni program je tudi jedro zapisano tako, da lahko njegova koda v enem jedru varno komunicira s svojo kodo na drugih jedrih za posodobitev skupnih podatkovnih struktur (kot je seznam niti, ki so pripravljene za zagon.

Kakorkoli že, OS je v pomoč pri izkoriščanju večnitnih procesov vzporednost na ravni niti, ki jo je treba izrecno izpostaviti z ročnim pisanjem večnitnega programa. (Ali s samodejnim paraleliziranjem prevajalnika z OpenMP ali kaj podobnega).

Nato čelni del CPU ta navodila še naprej organizira tako, da vsakemu jedru razdeli eno nit in razdeli neodvisna navodila iz vsake niti med vse odprte cikle.

Jedro CPU izvaja samo en tok navodil, če ni zaustavljeno (v mirovanju do naslednje prekinitve, npr. Prekinitev s časovnikom). Pogosto je to nit, lahko pa je tudi obdelovalec prekinitve jedra ali razna koda jedra, če se je jedro po ravnanju in prekinitvi ali sistemskem klicu odločilo narediti kaj drugega kot le vrnitev v prejšnjo nit.

Pri HyperThreading ali drugih SMT modelih fizično jedro CPU deluje kot več "logičnih" jeder. Edina razlika z vidika OS med štirijedrnim procesorjem s 4-bitnim (4c8t) procesorjem in navadnim 8-jedrnim računalnikom (8c8t) je ta, da bo OS, ki se zaveda HT, poskušal načrtovati niti za ločevanje fizičnih jeder, ne tekmujejo med seboj. OS, ki ni vedel za hipertekanje, bi videl samo 8 jeder (razen če v BIOS-u onemogočite HT, bi zaznal le 4).

Izraz "front-end "se nanaša na del jedra procesorja, ki pridobi strojno kodo, dekodira navodila in jih izda v nepravilnem delu jedra. Vsako jedro ima svoj prednji del in je del jedra kot celote. Navodila, ki jih pridobi so kaj trenutno deluje CPU.

Znotraj odpovedanega dela jedra se navodila (ali uops) pošljejo v izvedbena vrata, ko so njihovi vhodni operandi pripravljeni in obstaja prosta izvedbena vrata. To se ni treba zgoditi v vrstnem redu programov, zato tako lahko CPU OOO izkoristi vzporednost na ravni navodil znotraj ene niti.

Če v svoji ideji zamenjate "jedro" z "izvršilno enoto", boste to skoraj popravili. Da, CPU vzporedno distribuira neodvisna navodila / ups izvršilnim enotam. (Vendar obstaja terminološka zmeda, saj ste rekli "front-end", ko je v resnici načrtovalnik navodil CPU, imenovan Reservation Station, izbere navodila, pripravljena za izvajanje).

Izvrševanje po naročilu lahko najde ILP le na zelo lokalni ravni, le do nekaj sto navodil, ne pa med dvema neodvisnima zankama (razen če so kratke).

Na primer, asm ekvivalent tega

bo deloval približno tako hitro kot ista zanka, pri čemer bo le povečal en števec na Intel Haswell. i ++ je odvisen samo od prejšnje vrednosti i, medtem ko je j ++ odvisen samo od prejšnje vrednosti j, torej oba verige odvisnosti lahko teče vzporedno, ne da bi razbil iluzijo, da se vse izvaja v programskem vrstnem redu.

Na x86 bi bila zanka videti nekako takole:

Haswell ima 4 vrata s celoštevilčnimi izvršilnimi enotami, vsa pa imajo seštevalne enote, tako da lahko vzdržujejo pretok do 4-palčnih navodil na uro, če so vsa neodvisna. (Z zakasnitvijo = 1, zato potrebujete le 4 registre, da maksimirate prepustnost, tako da v letu držite 4 inc navodila. To primerjajte z vektor-FP MUL ali FMA: zakasnitev = 5 prepustnost = 0,5 potrebuje 10 vektorskih akumulatorjev, da ostane 10 FMA-jev v in maksimalen pretok. Vsak vektor je lahko 256b in ima 8 plovcev z eno natančnostjo).

Prevzeta veja je tudi ozko grlo: zanka vedno vzame vsaj eno celo uro na iteracijo, ker je prepustnost sprejete veje omejena na 1 na uro. V zanko bi lahko dal še eno navodilo, ne da bi zmanjšal zmogljivost, razen če tudi bere / piše eax ali edx, v tem primeru bi podaljšal to verigo odvisnosti. Če v zanko vstavite še dve navodili (ali eno zapleteno navodilo z več splošnimi navodili), bi to ustvarilo ozko grlo na sprednjem delu, saj lahko v jedro, ki ni v redu, izda le 4 povratne informacije na uro. (Oglejte si ta SO Q & ampA za nekaj podrobnosti o tem, kaj se zgodi z zankami, ki niso večkratniki 4 ups: vmesni pomnilnik in uop predpomnilnik naredijo stvari zanimive.)

V bolj zapletenih primerih je za iskanje vzporednosti treba gledati večje okno navodil. (npr. morda obstaja zaporedje 10 navodil, ki so vsa odvisno, nato pa nekaj neodvisnih).

Kapaciteta ponovnega naročanja medpomnilnika je eden od dejavnikov, ki omejuje velikost okna, ki ni v redu. V podjetju Intel Haswell je 192 ups. (In lahko ga celo poskusno izmerite, skupaj z zmogljivostjo za preimenovanje registra (velikost datoteke registra).) Jedra CPU z majhno porabo, kot je ARM, imajo veliko manjše velikosti ROB, če sploh izvajajo naročila zunaj naročila.

Upoštevajte tudi, da je treba CPU napeljati, pa tudi ne v redu. Torej mora pridobiti in ampdecode navodila precej pred izvedenimi, po možnosti z dovolj pretoka, da napolni medpomnilnike po izpuščenih ciklih pridobivanja. Podružnice so zapletene, saj ne vemo, od kod sploh priti, če ne vemo, v katero smer je šla veja. Zato je napovedovanje vej tako pomembno. (In zakaj sodobni CPU uporabljajo špekulativno izvedbo: ugibajo, v katero smer bo šla veja, in začnejo pridobivati ​​/ dekodirati / izvajati ta tok ukazov. Ko odkrijejo napačno napoved, se vrnejo v zadnje dobro znano stanje in od tam izvršujejo.)

Če želite prebrati več o notranjih delih CPU, je v wikiju Stackoverflow x86 nekaj povezav, med drugim tudi do vodnika za mikroarhiranje Agnerja Foga in do podrobnih zapisov Davida Kanterja z diagrami procesorjev Intel in AMD. Iz njegovega zapisa o mikroarhitekturi Intel Haswell je to končni diagram celotnega cevovoda Haswellovega jedra (ne celotnega čipa).

To je blokovni diagram a samski CPU jedro. Štirijedrni CPU ima na čipu 4 te procesorje, vsak s svojimi predpomnilniki L1 / L2 (delijo si predpomnilnik L3, krmilnike pomnilnika in povezave PCIe s sistemskimi napravami).

Vem, da je to pretežno zapleteno. Kanterjev članek prikazuje tudi del tega, da na primer govori o fronti ločeno od izvršilnih enot ali predpomnilnikov.


GO - Goroutina in sočasnost

pthreads upoštevajte predhodno načrtovanje, medtem ko Vlakna C ++ sledite načrtovanju sodelovanja.

S Pthreads: trenutna pot izvajanja se lahko kadar koli prekine ali prepreči. To pomeni, da je za niti celovitost podatkov velika težava, ker se lahko ena nit ustavi sredi posodabljanja dela podatkov, zaradi česar je celovitost podatkov v slabem ali nepopolno stanje. To tudi pomeni, da lahko operacijski sistem izkoristi več CPU-jev in procesorskih jeder tako, da hkrati zažene več niti in prepusti razvijalcu, da varuje dostop do podatkov.

Z uporabo C,

Uporaba niti, aplikacija ima lahko sočasno,

Lastnosti sočasnosti:

1) Več igralcev

2) Skupni vir

3) Pravila za dostop (atomska / pogojna sinhronizacija)

Z vlakni C ++: trenutna pot izvajanja se prekine šele, ko optično vlakno izvede izvedbo. To pomeni, da se vlakna vedno zaženejo in ustavijo na natančno določenih mestih, zato je integriteta podatkov veliko manjša težava. Ker vlaken pogosto upravljamo v uporabniškem prostoru, ni treba spreminjati dragih kontekstnih stikal in stanja stanja procesorja, zaradi česar je prehod iz enega vlakna v drugega izjemno učinkovit. Po drugi strani pa, ker nobeno vlakno ne more delovati popolnoma istočasno, samo uporaba vlaken ne bo izkoristila več procesorjev ali več jeder procesorja.

V Win32, a vlakno je nekakšna nit, ki jo upravljajo uporabniki. Fiber ima svoj sklad in svoj kazalnik navodil itd., Vendar OS ne načrtuje vlaken: SwitchToFiber morate izrecno poklicati. Niti pa operacijski sistem vnaprej načrtuje vnaprej.

Torej, optično gledano je vlakno nit, ki se upravlja na ravni aplikacije / zagona, namesto da bi bila prava nit OS.

Z uporabo C,

Zakaj vlakna C ++?

OS niti dajte nam vse, kar si želimo, vendar za visoko zmogljivost: preklapljanje med nitmi vključuje preskakovanje uporabnika v način jedra, morda celo čez meje naslovnega prostora. To so drage operacije, delno tudi zato, ker povzročajo TLB splakne, predpomnilnik pogreša in CPU cevovod opustoši: tudi zato so pasti in syscalls lahko za velikost veliko počasnejši od običajnih klicev postopkov.

Poleg tega jedro razporeja niti (tj. Njihovo nadaljevanje dodeli jedru CPU-ja) z uporabo algoritma splošnega razporejanja, ki lahko upošteva vse vrste niti, od tistih, ki strežejo posamezno transakcijo, do tistih, ki predvajajo celoten video.

Vlakna, ker so razporejeni na ravni aplikacije, lahko uporabijo načrtovalnik, ki je primernejši za njihov primer uporabe. Kot je navajena večina vlaken služijo transakcijam, ponavadi so aktivni zelo kratek čas in zelo pogosto blokirajo. Njihovo vedenje je pogosto treba prebuditi z IO ali drugim vlaknom, zagnati kratek cikel obdelave in nato prenesti nadzor na drugo vlakno (z uporabo čakalne vrste ali drugega sinhronizacijskega mehanizma). Takšno vedenje je najbolje uporabiti načrtovalnik, ki uporablja algoritem, imenovan "Krajo dela"Ko se vlakna obnašajo tako, krajo dela zagotavlja minimalne napake v predpomnilniku kdaj preklapljanje med vlakni.

Vlakna ne izkoriščajo moči večjedrnega, ker tisto, kar OS ve, je enonitni postopek.

V GO prikličemo goroutine z uporabo ključne besede go

1) Ali je GO rutina (f) a vlakno to je vnaprej načrtovano s strani izvajalnega okolja GO v uporabniškem prostoru?


10 odgovorov 10

Vse, kar nit naredi, je prepletanje operacij, tako da se zdi, da se deli postopka pravočasno prekrivajo. Enojedrni stroj z več nitmi zgolj poskoči: izvrši majhne koščke kode iz ene niti, nato preklopi na drugo nit. Preprost načrtovalnik se odloči, katera nit je najpomembnejša in se dejansko izvaja v jedru.

V enojedrnem računalniku nič dejansko zgodi "istočasno". Vse je samo prepletena izvedba.

Obstaja veliko, veliko načinov za dosego prepletanja. Veliko.

Recimo, da imate preprost dvonitni postopek, ki uporablja preprosto ključavnico, tako da lahko obe niti pišeta v skupno spremenljivko. Imate šest blokov kode.

  • T1 - pred zaklepanjem
  • T1-s ključavnico
  • T1-zaklepanje
  • T2 - pred zaklepanjem
  • T2-s ključavnico
  • T2-zaklepanje

[Ta je lahko v zanki ali ima več ključavnic ali kar koli drugega. Vse, kar počne, je daljše in ne bolj zapleteno.]

Koraki T1 se morajo izvajati po vrstnem redu (T1-pred, T1-s, T1-po) in koraki T2 morajo potekati po vrstnem redu (T2-pred, T2-s, T2-po).

Razen omejitve "v vrstnem redu" jih je mogoče na kakršen koli način prepletati. Kakorkoli. Lahko jih zaženete, kot je navedeno zgoraj. Drugo veljavno naročilo je (T1-pred, T2-pred, T2-zaklepanje, T1-zaklepanje, T2-po, T1-po). Veljavnih naročil je veliko.

To je samo državni stroj s šestimi državami.

To so nedeterministični avtomati s končnim stanjem. Razvrščanje stanj T1-xxx s stanji T2-xxx je nedoločeno in ni pomembno. Obstajajo torej kraji, kjer je "naslednje stanje" metanje kovancev.

Na primer, ko se FSM zažene, sta T1-pred ali T2-prej legitimni prvi državi. Vrzi kovanec.

Recimo, da je prišel pred T1. Naredi to. Ko to storite, obstaja izbira med T1-with in T2-before. Vrzi kovanec.

Na vsakem koraku v FSM bosta na voljo dve možnosti (dve niti - dve izbiri) in metanje kovancev lahko določi, kateremu posebnemu stanju se sledi.

Funkcije za blokiranje zapisov so namenjene ljudem, ki ne morejo ustvariti državnih strojev)

Niti so uporabne, če ne morete zaobiti blokade. Nobena temeljna računalniška dejavnost resnično ne blokira, le veliko jih je tako implementiranih zaradi enostavnosti uporabe. Namesto da vrne znak ali "branje ni uspelo", funkcija branja blokira, dokler ne prebere celotnega vmesnega pomnilnika. Namesto preverjanja povratnega sporočila v čakalni vrsti in vrnitve, če ga ni mogoče najti, funkcija povezovanja čaka na odgovor.

V državnem računalniku ne morete uporabljati blokirnih funkcij (vsaj tistih, ki jim ni dovoljeno "zamrzniti").

In da, uporaba državnega stroja je izvedljiva alternativa. V sistemih v realnem času je to edina možnost, ki zagotavlja okvir za stroj. Uporaba niti in blokirnih funkcij je le "najlažji izhod", ker običajno en klic blokirne funkcije nadomesti približno 3-4 stanja v državnem stroju.

Kako doseči funkcionalnost z več nitmi v jeziku na visoki ravni, kot je Java, z uporabo samo ene niti in stanja? Kaj na primer, če je treba izvesti 2 dejavnosti (opravljanje izračunov in izvajanje V / I) in lahko ena dejavnost blokira?

To, kar opisujete, se imenuje kooperativno večopravilnost, kjer imajo naloge CPU in se pričakuje, da ga bo prostovoljno odstopil po določenem času ali aktivnosti, ki ste ga določili sami. Naloga, ki ne sodeluje, če nadaljuje z uporabo CPU-ja ali blokira celotno delo, in če nima strojne opreme za nadzor časa, koda, ki nadzira naloge, ne more storiti ničesar.

To, kar vidite v sodobnih sistemih, se imenuje prednostno večopravilnost, kjer nalogam ni treba odstopiti CPU, ker jih nadzornik naredi namesto njih, ko pride strojno ustvarjena prekinitev. Rutinska storitev prekinitve v nadzorniku shrani stanje CPU-ja in ga obnovi naslednjič, ko je naloga zaslužna za časovni rez, nato obnovi stanje iz katere koli naloge, ki jo je treba zagnati, in skoči nazaj vanj, kot da se ni nič zgodilo . To dejanje se imenuje a stikalo za kontekst in je lahko drago.

Ali je uporaba načina "samo državni stroj" izvedljiva alternativa večnitnemu načinu v jezikih na visoki ravni?

Izvedljivo? Seveda. Sane? Včasih. Ali uporabljate niti ali neko obliko domačega zadružnega večopravilnega delovanja (npr. Državni stroji), je odvisno od kompromisov, ki ste jih pripravljeni sprejeti.

Niti poenostavijo načrtovanje opravil do te mere, da lahko vsako obravnavate kot svoj program, ki si izmenjuje podatkovni prostor z drugimi. To vam daje svobodo, da se osredotočite na zadevno delo in ne na vsa ravnanja in gospodinjstva, ki so potrebna, da lahko naenkrat deluje ponavljanje. Ker pa nobeno dobro dejanje ne ostane nekaznovano, plačate za vse to udobje v kontekstnih stikalih. Če imate veliko niti, ki dajo CPU po minimalnem delu (prostovoljno ali z nečim, kar bi blokiralo, na primer V / I), lahko pojeste veliko časa procesorja pri preklopu konteksta. To še posebej velja, če vaše blokiranje redko blokira zelo dolgo.

V nekaterih primerih je zadružna pot bolj smiselna. Nekoč sem moral napisati nekaj uporabniške programske opreme za del strojne opreme, ki je prenašal številne kanale podatkov prek pomnilniško preslikanega vmesnika, ki je zahteval anketiranje. Vsak kanal je bil objekt, zgrajen tako, da sem ga lahko pustil, da se je izvajal kot nit ali večkrat izvedel en sam cikel ankete.

Zmogljivost večnitne različice sploh ni bila dobra iz točno navedenega razloga, ki sem ga omenil zgoraj: vsaka nit je opravljala minimalno delo in nato dajala CPU, da so lahko ostali kanali imeli nekaj časa, kar je povzročalo veliko preklopov konteksta. Pustiti, da se niti izvajajo, dokler ni vnaprej preprečeno, je pomagalo pri prepustnosti, vendar je povzročilo, da nekateri kanali niso servisirani, preden je strojna oprema doživela prekoračitev medpomnilnika, ker niso dobili dovolj časa.

Različica z enim navojem, ki je izvedla celo ponovitve vsakega kanala, je delovala kot oparjena opica in obremenitev sistema je padla kot kamen. Kazen, ki sem jo plačal za dodaten nastop, je bila, da sem moral sam žonglirati z nalogami. V tem primeru je bila koda za to dovolj preprosta, da so bili stroški njenega razvoja in vzdrževanja vredni izboljšanja učinkovitosti. Mislim, da je to resnično bistvo. Če bi bile moje niti tiste, ki so sedele in čakale, da se vrne sistemski klic, se vaja verjetno ne bi splačala.


[Udemy 100% popusta] -Qgis 101

Pridobite 100% brezplačno kodo kupona za popust Udemy (brezplačna promocijska koda UDEMY), lahko se boste vpisali na tečaj & # 8220Qgis 101& # 8221 popolnoma BREZPLAČNO za vseživljenjski dostop. Pohitite ali pa boste morali plačati $ $

Zahteve

Trajanje tečaja: 2 uri

Inštruktor: Rudarski geolog

Angleške ocene: 4.3

Opis

Cilj predmeta je spodbuditi študenta v QGIS, brezplačno in odprtokodno namizna programska oprema za geografski informacijski sistem s kompleksnim delovnim okoljem, ki uporabnikom omogoča analizo in urejanje prostorskih informacij. QGIS podpira več vrst podatkov (vektorski in rastrski formati), spletne storitve, ki hkrati zagotavljajo številne uporabne ukaze in pripomočke za geo-obdelavo zaradi integracije z GDAL in OGR knjižnice.

Predmet je razdeljen na enote z različno zahtevnostjo, ki pomaga študentu, ki se bo naučil splošnih pojmov Geografskega informacijskega sistema, delal z vektorskimi, alfanumeričnimi in rastrskimi podatki, uporabljal orodja za geo-obdelavo in ustvarjal zemljevide.

Vpisani študentje tega spletnega tečaja se bodo do konca tega tečaja naučili, kako učinkovito uporabljati Qgis. Predmet bo zajemal le osnove na začetku in oddelek za vmesno stopnjo, nadaljevalni oddelek pa bo dodan kasneje.


2 odgovora 2

(To ni popoln odgovor, vendar se zdi predolg, da bi se prilegal komentarju.)

Na stopnjo sprejemanja "Oblikovanja za vzporednost" v industriji programske opreme vpliva veliko dejavnikov. Nekateri od njih niso imeli nič skupnega s koristmi. Na primer, sklopi spretnosti in stopnje znanja razvijalcev itd.

Eno od mojih ugotovitev je, da vrsta aplikacije določa stopnjo sprejetja vzporedne paradigme. Vsaka linija (raven) ali komponenta programske opreme ima eno ali več "naravnih domen / paradigem", to pomeni, da bi bilo programsko opremo veliko lažje razviti in vzdrževati, če bi bila izvedena v določeni paradigmi.

Če je za vzporeditev določene aplikacije potrebno stikalo paradigme, obstaja verjetnost, da podjetja, ki se ukvarjajo s programsko opremo, tega ne bodo upravičila stroškovno učinkovito. Če je to posebno paradigmo enostavno vzporediti, potem vidite, da bi imela ta programska oprema višjo stopnjo sprejemanja za vzporedno programiranje.

Glede seznama paradigem bi rad dodal Dataflow. Vse naloge so prijavljene vnaprej. Vsaka naloga izjavi svoje vhode in izhode pred izvajanjem. Opravilo se začne takoj, ko so na voljo vsi vhodni podatki.

Primeri paradigme pretoka podatkov:

Imeti eno zelo uspešno paradigmo ni dovolj. Da bi vzpostavili stopnjo sprejemanja vzporednega programiranja, je treba paralelizem uvesti tudi v druge paradigme (vključno z "zastarelimi").

Videl sem druge, ki so uspešno izvajali paralelizem v programu Windows GUI, tako da so na vsako računsko nalogo ustvarili eno pogovorno okno Windows (vsako pogovorno okno Windows je nameščeno v niti) in si izmenjali podatke s pomočjo sporočil sistema Windows.

To odseva moje zgornje opažanje: če bo uvedba vzporednosti v aplikacijo zahtevala, da se aplikacija prepiše v nenaravno paradigmo, se bo zapletenost razvoja in vzdrževanja povečala.

Pri povsem računsko intenzivnih opravilih se povečanje učinkovitosti običajno zelo ujema z napovedjo po Amdahlovem zakonu, pod pogojem, da se vsi izračuni izvajajo lokalno v računalniku (tj. Ni podvržen veliko počasnejšemu omrežnemu V / I prometu).

Kljub temu boste hitro ugotovili, da v vaših aplikacijah obstajajo ozka grla, ki jih ni mogoče vzporediti. Včasih se ta ozka grla teoretično ne dajo vzporediti, kar pomeni, da ni upanja, da bi našli boljši algoritem.

Osebna zgodba. Napisal sem preprost paraleliziran program, ki dešifrira datoteko JPEG, ji spremeni velikost in jo nato shrani v obliko slikovne datoteke po meri. Po preizkusu ugotovim, da program traja 1,6 sekunde, ko se preizkusi z uporabo 3 niti 4 niti. Izkazalo se je, da korak dekodiranja JPEG traja več kot 25% časa, zaradi česar je to najpočasnejši neparalelni korak.

Z drugimi besedami, zakon Amdahla začne veljati s samo 3-4 jedri CPU za moj mali program.

Včasih je mogoče ta ozka grla odstraniti, če lahko spreminjate zahteve glede programske opreme (na primer, če lahko od svojih strank zahtevate ne uporabite določen format slike), vendar so zahteve največkrat postavljene v kamen.

Ne morete čarobno narediti, da koda, ki ni napisana za sočasno delovanje, deluje dobro hkrati (in čarobno vključuje uporabo prevajalnikov).

Pogosto so se pogoji spremenili in kode je bilo treba narediti drugače. V zelo starih časih je bil spomin vrhunec, zato je bila samo-spreminjajoča se koda pogosta. Danes so prednosti kode v pomnilniku samo za branje tako velike, da jo želijo uveljaviti vsi sodobni operacijski sistemi.

Pomislite tudi, kaj se je zgodilo, ko je Windows postal priljubljen. Vsi programerji DOS so morali premisliti o svojih načinih programiranja. V enem navojnem programu ni bilo mogoče imeti niti ene zanke za anketiranje tipkovnice, ki bi poklicala celotno funkcionalnost aplikacije - morali ste imeti obdelovalce dogodkov - kar je spremenilo način oblikovanja kode aplikacije.

Mantre, kot je "uporabljaj nespremenljive predmete!" so izkušnje, naučene na težji način. Razlogi, zakaj se pogosto izgubijo na poti, vendar jih je mogoče rekonstruirati. "Uporabi nespremenljive predmete" je preprost način, ki omogoča predpomnjenje podatkov na več mestih, ne da bi se program ločil na enem od teh mest.

Sprememba, ki naj bi bila sočasna, ne zahteva popolnega prepisovanja v funkcionalnem jeziku, vendar jo je mogoče rešiti s knjižnicami, ki omogočajo ohranitev obstoječih knjižnic kod, vendar morate kljub temu napisati svoj program, da jo uporabite. Pristop OpenCL (Grand Central v OS X) je zelo zanimiv način uporabe CPU-ja in GPU-jev za izvajanje kode, vendar morate spet ustrezno pripraviti svoj program.

V Javi je bilo veliko truda namenjenega zagotavljanju dobrih gradnikov za transparentno merjenje izvajanja majhnih delčkov kode, vendar ga ne morete uporabiti, če zanj ne pišete.


4 odgovori 4

Specifikacija funkcij ctime in asctime sega v čas C89, v tistih časih pa so bile stvari nekoliko drugačne, predvsem zato, ker večprocesorski sistemi niso bili zelo pogosti in zato uporaba statičnega vmesnega pomnilnika ne bi povzročala velikih težav.

Najverjetneje niso vrnili dinamično dodeljenega pomnilnika, ker je trajal dodaten čas, v tistih časih pa je bilo težje doseči cikle CPU.

Če uporabljate sistem POSIX, kot je Linux, imate na voljo še dve funkciji, ki sta v bistvu opisani kot alternativa:

Te funkcije vzamejo kazalec na vmesnik, ki lahko prejme izhod (in vrnejo kazalec na isti vmesnik). Pripona _r pomeni "povratno", kar pomeni, da jo lahko varno prikličete v večnitnem programu ali večkrat brez zaporedne točke vmes.


Izgleda v redu, če bi bili malce površni z drugačnim oblikovanjem za nekatere klice print x v primerjavi s print (x) (slednji je resnično najprimernejši), bi verjetno morali uporabiti tudi nove slogovne razrede, to je razred Loader (objekt):.

Razen tega je moja glavna skrb, da je treba semafor zaščititi pred izjemami. To večinoma skrbi za večje scenarije, vendar je to ne glede na to dobra navada. Tako je treba poklicati metodo sproščanja ne glede na to o tem, ali je izjemo sprožilo kaj drugega v niti - sicer bi se lahko program tam kar zataknil, kar je verjetno za enkratni skript.

Verjetno bi morali tudi preveriti, ali navajanje res izboljša pretočnost, ob upoštevanju zaklepanja globalnega tolmača Pythons.


Odpravljanje napak v pomnilniku

Najprej se zavedam, da to ni popolno vprašanje v stilu Q & ampA z absolutnim odgovorom, vendar si ne predstavljam nobenega besedila, da bi to bolje delovalo. Mislim, da za to ni absolutne rešitve, in to je eden od razlogov, zakaj jo objavljam tukaj namesto Stack Overflow.

V zadnjem mesecu sem prepisoval dokaj star del strežniške kode (mmorpg), da bi bil sodobnejši in lažji za razširitev / mod. Začel sem z omrežnim delom in uvedel lastno knjižnico (libevent), ki je zame delala stvari. Z vsemi spremembami faktorjev in sprememb kode sem nekje uvedel poškodbe spomina in se trudim ugotoviti, kje se to zgodi.

Zdi se mi, da ga ne morem zanesljivo reproducirati v svojem okolju za razvijalce / preizkuse, tudi ko izvajam primitivne bote za simulacijo neke obremenitve, ne dobim več zrušitev (odpravil sem težavno težavo, ki je povzročila nekaj stvari)

Valgrinding the hell out of it - No invalid writes until the thing crashes (which may take 1+ day in production.. or just an hour) which is really baffling me, surely at some point it would access invalid memory and not overwrite stuff by chance? (Is there a way to "spread out" the address range?)

Code-Analysis tools, namely coverity and cppcheck. While they did point out some.. nastiness and edge cases in the code there was nothing serious.

Recording the process until it crashes with gdb (via undodb) and then working my way backwards. This /sounds/ like it should be doable, but I either end up crashing gdb by using the auto-complete feature or I end up in some internal libevent structure where I get lost since there's too many possible branches (one corruption causing another and so on). I guess it would be nice if I could see what a pointer originally belongs to/where it was allocated, that would eliminate most of the branching-issues. I cant run valgrind with undodb though, and I the normal gdb record is unusably slow (if that even works in combination with valgrind).

Code review! By myself (thoroughly) and having some friends look over my code, though I doubt it was thorough enough. I was thinking about maybe hiring a dev to do some code review/debugging with me, but I cant afford to put too much money in it and I wouldn't know where to look for someone who'd be willing to work for little-to-no money if he doesn't find the issue or anyone qualified at all.

I should also note: I usually get consistent backtraces. There are a few places where the crash happens, mostly related to the socket class becoming corrupted somehow. Be it an invalid pointer pointing to something which isn't a socket or the socket class itself becoming overwritten (partially?) with gibberish. Although I suspect it's crashing there the most since that's one of the mostly used parts, so it's the first corrupted memory which gets used.

All in all this issue has had me busy for nearly 2 month (on and off, more of a hobby project) and is really frustrating me to the point where I become grumpy IRL and think about just giving up. I just can't think about what else I am supposed to do to find the issue.

Are there any useful techniques I missed? How do you deal with that? (It can't be that common since there isn't much information about this.. or I'm just really blind?)

Some specs in case it matters:

Using c++(11) via gcc 4.7 (version supplied by debian wheezy)

The codebase is around 150k lines

Edit in response to david.pfx post: (sorry for the slow response)

Are you keeping careful records of crashes, to look for patterns?

Yes, I still have dumps of the recent crashes lying around

Are the few places really similar? V kakšnem smislu?

Well, in the most recent version (they seem to change whenever I add/remove code or change related structures) it would always get caught in an item timer method. Basically an item has a specific time after which it expires and it sends updated info to the client. The invalid socket pointer would be in the (still valid as far as I can tell) Player class, mostly related to that. I am also experiencing loads of crashes in the cleanup phase, after the normal shutdown where it's destroying all the static classes that haven't been explicitly destroyed ( __run_exit_handlers in the backtrace). Mostly involving std::map of one class, guessing that's just the first thing that comes up though.

What does the corrupt data look like? Zeros? Ascii? Patterns?

I haven't found any patterns yet, seems somewhat random to me. It's hard to tell since I don't know where the corruption started.

It's entirely heap-related (I enabled gcc's stack guard and that didn't catch anything).

Does the corruption happen after a free() ?

You're going to have to elaborate a bit on that one. Do you mean having pointers of already free'd objects lying around? I'm setting every reference to null once the object gets destroyed, so unless I missed something somewhere, no. That should show up in valgrind though which it didn't.

Is there something distinctive about the network traffic (buffer size, recovery cycle)?

The network traffic consists of raw data. So char arrays, (u)intX_t or packed (to remove padding) structs for more complex things, each packet has a header consisting of an id and the packet size itself which is validated against the expected size. They are around 10-60bytes with the biggest (internal 'bootup' packet, fired once at startup) having a size of a few Mb.

Lots and lots of production asserts. Crash early and predictably before the damage propagates.

I once had a crash related to std::map corruption, each entity has a map of it's "view", each entity that can see it and vice versa is in that. I added a 200byte buffer in front and after, filled it with 0x33 and checked it before each access. The corruption just magically vanished, I must've moved something around which made it corrupt something else.

Strategic logging, so you know accurately what was happening just before. Add to the logging as you get closer to an answer.

In desperation, can you save state and auto-restart? I can think of a few pieces of production software that do that.

I somewhat do that. The software consists of a main "cache" process and some other worker ones which all access the cache to get and save stuff. So per crash I don't lose much progress, it still disconnects all the users and so on, it's definitely not a solution.

Concurrency: threading, race conditions, etc

There's a mysql thread to do "async" queries, that's all untouched though and only shares information to the database class via functions with all lock.

There's an interrupt timer to prevent it from locking up that just aborts if it didn't complete a cycle for 30 seconds, that code should be safe though:

tics is volatile int tics = 0 which is increased each time a cycle is completed. Old code too.

events/callbacks/exceptions: corrupting state or the stack unpredictably

Lots of callbacks are being used (async network I/O, timers), but they shouldn't do anything bad.

Unusual data: unusual input data/timing/state

I've had a few edge cases related to that. Disconnecting a socket while packets are still being processed resulted in accessing a nullptr and such, but those have been easy to spot so far since every reference gets cleaned up right after telling the class itself it's done. (Destruction itself is handled by a loop deleting all the destroyed objects each cycle)

Dependency on an asynchronous external process.

Care to elaborate? This is somewhat the case, the cache process mentioned above. Only thing I could imagine off the top of my head would be it not finishing quick enough and using garbage data, but that's not the case since that's using network too. Same packet model.


Poglej si posnetek: QGIS Tutorial: Filtering based on attributes in QGIS EN