Olen päätellyt että olisi tehokkainta säilyttää suurta määrää olioita muistissa sijoittamalla ne taulukkoon.
Kannattaisiko tehdä luokka, josta periytyvät lapsiluokat ovat samaa kokoa muistissa, kuin vanhempi? Se olisi tietojen säilyttämisen kannalta eduksi, esim. taulukoissa. Lapset voisivat käyttää samaa taulukkoa kuin vanhempi.
Ja miten sellainen tehdään. GCC:ssä on __attribute__((packed)), jolla luokan ja rakenteen pituuden voi tiivistää, mutta voiko samaa käyttää määrittelemään luokalle kiinteän koon.
jsbasic kirjoitti:
Olen päätellyt että olisi tehokkainta säilyttää suurta määrää olioita muistissa sijoittamalla ne taulukkoon.
Pitänee paikkaansa, joskin kannattaa muistaa myös std::list ja std::vector, ovat usein aivan riittäviä ja muistin kanssa ei tarvitse olla niin tarkkana.
jsbasic kirjoitti:
Kannattaisiko tehdä luokka, josta periytyvät lapsiluokat ovat samaa kokoa muistissa, kuin vanhempi? Se olisi tietojen säilyttämisen kannalta eduksi, esim. taulukoissa. Lapset voisivat käyttää samaa taulukkoa kuin vanhempi.
Ehkä kuitenkin kannattaa tehdä ihan vain luokka, joka tekee tehtävänsä niin hyvin kuin mahdollista ja alkaa viilaamaan vasta kun sille on tarvetta.
premature optimization is the root of all evil
Olioiden tehokas säilyttäminen riippuu hyvin paljon siitä, millaisen ohjelman olet tekemässä. Yleensä omat purkkaviritelmät eivät kannata; jos kannattaisivat, C++ tukisi niitä valmiiksi tai niistä olisi tehty helppokäyttöinen lisäkirjasto.
Luultavasti järkevintä olisi käyttää listaa (std::list
) tai taulukkoa (std::vector
), jossa olisi osoittimia (Olio*
) olioihin, jotka olisi luotu yksitellen new
-operaattorilla. Poiston yhteydessä täytyy luonnollisesti muistaa delete
, ellei käytä tavallisen osoittimen sijaan luokkaa boost::shared_ptr<Olio>
(tai std::tr1::shared_ptr<Olio>
), jolloin delete on tarpeeton.
jsbasic kirjoitti:
Olen päätellyt että olisi tehokkainta säilyttää suurta määrää olioita muistissa sijoittamalla ne taulukkoon.
Tehokkainta missä mielessä?
jsbasic kirjoitti:
Kannattaisiko tehdä luokka, josta periytyvät lapsiluokat ovat samaa kokoa muistissa, kuin vanhempi? Se olisi tietojen säilyttämisen kannalta eduksi, esim. taulukoissa. Lapset voisivat käyttää samaa taulukkoa kuin vanhempi.
Noinkohan? Haluaisitko kenties antaa esimerkin tilanteesta, jossa yksi taulukko säilöö useampaa eri tyyppistä oliota?
Teuro kirjoitti:
"premature optimization is the root of all evil"
No jokainen joka on lapsena siirtynyt Dublo-legoista tavallisiin, tietää että kaikki pitää rakentaa uudestaan. :) "Evil is in The Detail".
jsbasic kirjoitti:
No jokainen joka on lapsena siirtynyt Dublo-legoista tavallisiin, tietää että kaikki pitää rakentaa uudestaan. :)
Jos nyt tuolle linjalle lähdetään, niin sinustako ongelmaan sitten auttaa se, että ne väärin kirjoitetut Duplo-palikat liimaa ensin purukumilla yhteen?
Metabolix kirjoitti:
...väärin kirjoitetut Duplo-palikat liimaa purukumilla kasaan?
Joskus täytyy tehdä myös omia palikoita. Jos ei täytyisi, C++ olisi poistunut jo käytöstä, koska vectorit löytyy javastakin.
jsbasic kirjoitti:
Metabolix kirjoitti:
...väärin kirjoitetut Duplo-palikat liimaa purukumilla kasaan?
Joskus täytyy tehdä myös omia palikoita. Jos ei täytyisi, C++ olisi poistunut jo käytöstä, koska vectorit löytyy javastakin.
Et ole tosissasi. Toivottavasti.
Aloituspostiin: näytä esimerkki tapauksesta, jossa kahden luokan sama koko (ja vain se) mahdollistaa kahden eri tyyppisen olion tallettamisen samaan taulukkoon. Kun olet huomannut mitä tarkoitan, hanki itsellesi hyvä C++-opus ja jatka opiskelua siitä.
eq kirjoitti:
näytä esimerkki tapauksesta, jossa kahden luokan sama koko (ja vain se) mahdollistaa kahden eri tyyppisen olion tallettamisen samaan taulukkoon.
En tarkoita osoitintaulukkoja, vaan haluan sijoittaa oliot muistiin perätysten. Eiköhän se lisää rutkasti nopeutta, ja myös pienentää tilaa kun osoitintaulukonkin jättää pois. Kyse on vain data-alkioista, joita haluaisin herätellä olioksi yksi kerrallaan. Ei ole välttämätöntä käsitellä tuota dataa olioina, mutta tuntuu helpommalta vaihtoehdolta. Ehkä pitää keksiä stardardimpi ratkaisu.
Jos data täyttää POD-määritelmän (eli suunnilleen, että kaikki jäsenet julkisia ja ei-virtuaalisia), voit tehdä rakenteista unionin. Se olisi luultavasti järkevä ratkaisu.
Jos olet ihan varma muistinhallintataidoistasi, voit myös varata haluamasi kokoisen taulukon ja käyttää erityistä new-syntaksia ja eksplisiittistä destruktorikutsua. Muista, että kaikki virheet ovat silloin sinun vastuullasi.
#include <cstdio> #include <memory> using std::printf; struct A { A() { printf("%p: A()\n", this); } virtual ~A() { printf("%p: ~A()\n", this); } virtual void f() { printf("%p: A::f()\n", this); } }; struct B: A { B() { printf("%p: B()\n", this); } virtual ~B() { printf("%p: ~B()\n", this); } virtual void f() { printf("%p: B::f()\n", this); } }; template <typename T1, typename T2 = char> union Tilaa { char data_a[sizeof(T1)]; char data_b[sizeof(T2)]; }; typedef Tilaa<A, B> TilaaAB; // typedef Tilaa<Tilaa<Tilaa<A, B>, C>, D> TilaaABCD; int main() { printf("sizeof(A) = %d\n", (int) sizeof(A)); printf("sizeof(B) = %d\n", (int) sizeof(B)); printf("sizeof(TilaaAB) = %d\n", (int) sizeof(TilaaAB)); TilaaAB data[1]; A* a; printf("&data[0] = %p\n", &data[0]); printf("new A:\n"); a = new (&data[0]) A; a->f(); a->~A(); printf("new B:\n"); a = new (&data[0]) B; a->f(); a->~A(); }
Alkuun:
Metabolix kirjoitti:
template <typename T1, typename T2 = char> union Tilaa { char data_a[sizeof(T1)]; char data_b[sizeof(T2)]; };
Unionille ei tässä tapauksessa ole mitään erityistä tarvetta. Koska sizeof-operaattorin ilmoittama koko on käännönaikainen vakio, myös konditionaali sizeof(A) > sizeof(B) ? sizeof(A) : sizeof(B)
on vakiolauseke. Esimerkki:
template<typename T1, typename T2 = char> struct Tilaa { char data[sizeof(T1) > sizeof(T2) ? sizeof(T1) : sizeof(T2)]; };
Unionin käytön hyödyt (visuaalinen apu virheiden varalta) eivät juuri realisoidu mallien kanssa, koska nimet data_a ja data_b eivät välttämättä auta pelkän muuttujan kanssa toimiessa (silloin, kun muuttujan tyyppi on etäämmällä).
Metabolix kirjoitti:
a = new (&data[0]) A;
Tämä keskusteluaihe ei ole tavattoman poikkeuksellinen C++-keskustelujen parissa; myös vastaukset noudattavat tiettyä kaavaa.
Väite: Placement new
'n suurin ongelma on sen (jopa yllättävän suuri) alustariippuvaisuus.
Perustelut: Operaattori ei sinänsä ole alustariippuvainen ollenkaan: ongelma on siinä, että sitä usein haluttaisiin käyttää ei-dynaamisesti varatun puskurin kanssa. Tässä kohtaa ongelmaksi nousee nykyisen C++:n (ja C:n) olematon tuki alignmentille. Toki monilla arkkitehtuureilla tämä lähinnä hidastaa ohjelman suoritusta (samanlainen ongelma esiintyy tietorakenteen pakkaamisen yhteydessä) - toisilla ohjelma ei toimi lainkaan.
Alignment-ongelmaa voi kiertää käyttämällä mallocia char-puskurin sijaan, mutta tätä aloituspostaaja erityisesti ei halunnut.
Suoritusnopeus ja muistinkäyttö asettuvat ajoittain päällekäin. Siksi aloittajankin tulisi päättää, mitä tehokkuutta hän hakee, ja sen jälkeen pohtia tarvitseeko hän todella niitä muutamaa ylimääräistä tavua suorituskyvyn kustannuksella.
eq kirjoitti:
Unionille ei tässä tapauksessa ole mitään erityistä tarvetta.
Mutta onko siitä jotain erityistä haittaa?
eq kirjoitti:
Alignment-ongelmaa voi kiertää käyttämällä mallocia char-puskurin sijaan
Aivan, unohdin taas alignmentin. Siihen on kuitenkin helppo ratkaisu: laitetaan unioniini char-taulukoiden lisäksi kaikenlaisia muita muuttujatyyppejä, jolloin alkukohdan alignmentista tullee näille kaikille sopiva. Itse luokan koko sisältää jo tarvittavan paddingin, jotta taulukon seuraavat yksilöt osuvat tämän jälkeen sopivasti.
Metabolix kirjoitti:
eq kirjoitti:
Unionille ei tässä tapauksessa ole mitään erityistä tarvetta.
Mutta onko siitä jotain erityistä haittaa?
Tuskin teknisesti ainakaan.
Aloittajalle vielä:
class yliluokka; class aliluokka /* : yliluokka */; yliluokka taulukko1[koko1]; aliluokka taulukko2[koko2]; /* On tehokkain tapa sekä muistinkäytön (ei tarvita turhaa paddingia yliluokalle), että suoritusnopeuden (ei tarvitse erikseen selvittää, minkä tyyppinen muuttuja taulukon mikäkin alkio on + aina oikea alignment) suhteen */
Placement new'n, eli olion "herättelemisen" sijaan voisin käyttää erillistä olioita, joissa on osoitin taulukossa sijaitsevalle tietueelle. Tietue voisi olla joka oliolle sama, vaikka oliot käsittelisivät sitä eri tavoin. Käyttäisin siis tietuetaulukkoa. Ei kuulosta hienostuneelta, mutta eipä teollisesti tuotetut ohjelmasovellukset usein sitä olekaan.
Millä tavalla olion sisäinen osoitin dataan olisi yhtään tehokkaampi ratkaisu kuin taulukollinen osoittimia kokonaisiin olioihin? Sitä paitsi jos tuollainen ratkaisu on tilanteessasi mahdollinen, luokkiesi on jo välttämättä täytettävä POD-määritelmä, jolloin voit edelleenkin tehdä niistä unionin:
#include <cstdio> using std::printf; struct A { int i; void f() { printf("%p: A::f(), i = %d\n", this, i); } }; struct B { char a, b, c, d; void f() { printf("%p: B::f(), abcd = %c%c%c%c\n", this, a, b, c, d); } }; union X { A a; B b; }; int main() { X x; x.a.i = 0x44434241; x.a.f(); x.b.f(); }
jsbasic kirjoitti:
Ei kuulosta hienostuneelta, mutta eipä teollisesti tuotetut ohjelmasovellukset usein sitä olekaan.
"Koodaan työkseni, joten koodaan huonosti" on perusteluna sieltä typerimmästä päästä. Jos et osaa koodata kunnolla (etkä aio edes opetella vaan teet väkisin omia viritelmiäsi), kannattaa palkata mieluummin joku taitavampi "tuottamaan teollisesti" niitä ohjelmia. Hyvin tehty koodi maksaa itsensä takaisin väistämättömien korjausten yhteydessä, varsinkin, kun hyvin tekeminen ei vie yhtään sen enempää aikaa kuin huonosti tekeminenkään, jos vain tekijä osaa asiansa.
Tuo union näyttää tosi kätevältä, mutta raja tulee tuossakin vastaan, jos haluaa kutsua f()
-metodia suoraan, x.f()
. Siis x:n pitäisi olla tyypiltään vain joko A tai B. Mutta tämä ei taitaisi olla ollenkaan standardin mukaista?
Metabolix kirjoitti:
Hyvin tehty koodi maksaa itsensä takaisin väistämättömien korjausten yhteydessä
Eipä taida olla ehdoton sääntö. Kaupallisissa sovelluksissa suosituin tekniikka on harvoin parempi. Hyvin tekemistä pitäisi rajoittaa hallitusti.
jsbasic kirjoitti:
Metabolix kirjoitti:
Hyvin tehty koodi maksaa itsensä takaisin väistämättömien korjausten yhteydessä
Eipä taida olla ehdoton sääntö. Kaupallisissa sovelluksissa suosituin tekniikka on harvoin parempi. Hyvin tekemistä pitäisi rajoittaa hallitusti.
Hyvin tekeminen ei ole sama asia kuin "parhaan tekniikan käyttäminen". Sitä paitsi mikään yksittäinen tekniikka ei ole paras kaikkeen, joten missä tahansa isommassa projektissa joudutaan tekemään painotuksia ja trade-offeja eri tekniikoiden suhteen.
Grez kirjoitti:
Hyvin tekeminen ei ole sama asia kuin "parhaan tekniikan käyttäminen". Sitä paitsi mikään yksittäinen tekniikka ei ole paras kaikkeen, joten missä tahansa isommassa projektissa joudutaan tekemään painotuksia ja trade-offeja eri tekniikoiden suhteen.
OK. Minun olisi heti avauksessa pitänyt lähestyä ongelmaa abstraktimmin ja kertoa oma ongelmani tarkemmin. Ohjelmointi vain on monimutkaista, ja epäinhimillistä puuhaa, joka olisi pitänyt jättää jo historiassa koneen huoleksi. Ihminen tekee sitä aikalailla tehottomasti joka tapauksessa.
Siis muistinkulutus oli suurin ongelmani, ja eiköhän se ole nykyään paljon isompi ongelma kuin suoritusteho. Ehkäpä C ja C++ painottaa enemmän suoritustehoa, koska se oli merkityksellisempää ennen! (Javasta puhumattakaan) Olen sen verran tutustunut konekieliohjelmointiin, että väitän(ainakin 1980-luvun) tietokoneen rakenteen sallivan vielä C++ vapaammankin muistinhallinnan.
Tässä jokin artikkeli C++ muistinhallinnasta
http://linuxdevcenter.com/pub/a/linux/2003/05/
Lisää löytyy googlettamalla "c++ memory management"
jsbasic kirjoitti:
Metabolix kirjoitti:
Hyvin tehty koodi maksaa itsensä takaisin väistämättömien korjausten yhteydessä
Eipä taida olla ehdoton sääntö. Kaupallisissa sovelluksissa suosituin tekniikka on harvoin parempi. Hyvin tekemistä pitäisi rajoittaa hallitusti.
Kyllä se on ehdoton sääntö, jos on vähääkään ajatusta tehdä kaupallista softaa. Paras tekniikka on aina tilannekohtainen, mutta useimmissa tapauksissa suosituin tekniikka on todennäköisesti joko paras tai vähintäänkin täysin riittävä.
jsbasic kirjoitti:
Siis muistinkulutus oli suurin ongelmani, ja eiköhän se ole nykyään paljon isompi ongelma kuin suoritusteho.
Tämäkin on täysin tapauskohtaista. Riippuu aivan siitä millaiseen ympäristöön olet tekemässä minkäkinlaista ohjelmaa. Oma ajatusmallisi kuluttaisi enemmän sekä suoritusaikaa, että varsinkin sitä muistia. Puhumattakaan siitä, että itse koodista tulisi melkoista kikkailua ja hankalasti ylläpidettävää. Sen lisäksi että liika kikkailu tekee siitä ihmiselle hankalasti hallittavaa, niin myös kääntäjälle. Mitä "normaalimpaa" koodia kirjoitat, niin sitä varmemmin kääntäjäkin osaa koodiasi optimoida. Ja koska kääntäjä on kyseiselle arkkitehtuurille suunniteltu, osaa se varmasti optimoinnin paremmin kuin monet ohjelmoijat.
jsbasic kirjoitti:
Ehkäpä C ja C++ painottaa enemmän suoritustehoa, koska se oli merkityksellisempää ennen!
C/C++ eivät painota suoritustehoa. Ne jättävät ohjelmoijalle vapaat kädet painottaa kokoa/nopeutta oman tarpeensa mukaan.
jsbasic kirjoitti:
Olen sen verran tutustunut konekieliohjelmointiin, että väitän(ainakin 1980-luvun) tietokoneen rakenteen sallivan vielä C++ vapaammankin muistinhallinnan.
Jos olet yhtään tutustunut C/C++ ohjelmointiin, niin varmasti tiedät että C/C++ kääntäjä tekee koodistasi konekielisen. Lienee selvä, että tekemällä itse sen mitä kääntäjä tekisi muuten, saa vapaammat kädet.
Torgo kirjoitti:
Mitä "normaalimpaa" koodia kirjoitat, niin sitä varmemmin kääntäjäkin osaa koodiasi optimoida.
Mutta optimoiko se myös muistinkäyttöä? Jos koodaan osoitintaulukon, niin muuntaako kääntäjä sen automaattisesti oliotaulukoksi?
Torgo kirjoitti:
Ne jättävät ohjelmoijalle vapaat kädet painottaa kokoa/nopeutta oman tarpeensa mukaan.
C on imperatiivinen, suorituskeskeinen kieli. Sen yksi rivi käskee useimmiten tekemään jotakin. Vertaa sitä Prologiin, jolla tehdyssä ohjelmassa ei tarvita välttämättä yhtään käskyä. Deklaratiivisessa kielessä ohjelmoija ajattelee ohjelmaa pakostakin muistin resursseina. Tuskin mikään ohjelmointikieli jättää ohjelmoijalle vapaita käsiä, paitsi Assembly.
jsbasic kirjoitti:
Mutta optimoiko se myös muistinkäyttöä?
Se optimoi koodin kokoa. RAMin käyttö on ohjelmoijan vastuulla. C/C++ ei pakota ohjelmoijaa tuhlaamaan muistia.
jsbasic kirjoitti:
Jos koodaan osoitintaulukon, niin muuntaako kääntäjä sen automaattisesti oliotaulukoksi?
Ei. Jos haluat oliotaulukon, teet oliotaulukon. Jos haluat osoitintaulukon, teet osoitintaulukon. Miten se edes olisi muistinkäytön optimointia? Viehän osoitintaulukko joka tapauksessa huomattavasti vähemmän muistia kuin oliotaulukko. Jos tarkoitat että osoitintaulukon jokainen alkio osoittaisi erilliseen olemassa olevaan olioon ja muuntaisi tämän oliotaulukoksi, niin olet jo lähtökohtaisesti yrittänyt jotain hassua, mikä ei onnistuisi assemblylläkään yhtään sen paremmin.
Torgo kirjoitti:
RAMin käyttö on ohjelmoijan vastuulla.
Ei ole täysin.
Ensinnäkin, onhan se koodikin siellä RAM-muistissa tilaa viemässä, ja siihen ei ole syytä kajota suorituksen aikana, koska sen on muoto on ohjelmoijalle tuntematon. En tosin ole varma pääseekö konekielinen ohjelmakaan käsiksi omaan koodiinsa, mutta muistaakseni aika vapaata se on. Koodin pitäminen erillään datasta lisää tietenkin laitteistoriippumattomuutta tehokkuuden kustannuksella.
Toiseksi, tässä keskustelussa on tullut ilmi, että muistia on pakko käyttää "normaalisti". Nähtävästi C/C++:lla ei ole helppo toteuttaa monimutkaisia muistiratkaisuja niin, että ne olisivat yhteensopivia C/C++:n sisäänrakennettujen taulukoiden, tietueiden ja olioiden kanssa. Union on tästä piristävä poikkeus, mutta sekään ei pysty kaikkeen.
jsbasic kirjoitti:
Tässä jokin artikkeli C++ muistinhallinnasta
http://linuxdevcenter.com/pub/a/linux/2003/05/08/cpp_mm-1.html Lisää löytyy googlettamalla "c++ memory management"
Miksi ihmeessä minun pitäisi Googlettaa C++:n muistiin liittyen, ja miten kummassa tämä avittaisi sinua pääsemään tavoitteeseesi?
jsbasic kirjoitti:
Toiseksi, tässä keskustelussa on tullut ilmi, että muistia on pakko käyttää "normaalisti". Nähtävästi C/C++:lla ei ole helppo toteuttaa monimutkaisia muistiratkaisuja niin, että ne olisivat yhteensopivia sisäänrakennettujen taulukoiden, tietueiden ja olioiden kanssa. Union on tästä piristävä poikkeus, mutta sekään ei pysty kaikkeen, ja on sellaisenaan hieman purkkaratkaisu.
Et ole missään vaiheessa esittänyt *mitään* faktaa tai figuureja siitä, mitä saavutat tai yrität saavuttaa "custom"-ratkaisuillasi: ainoa lähtökohtasi tuntuu olevan, että "epänormaali" on parempi ja monimutkainen tehokkaampi.
Kun tämän tiedon yhdistää siihen, että useissa viesteissä myönnät olevasi C++-noviisi, on vain vaikea ymmärtää mistä oikein ideoitasi ammennat ja varsinkin *miksi ihmeessä* pidät niistä niin vahvasti kiinni.
jsbasic kirjoitti:
Ensinnäkin, onhan se koodikin siellä RAM-muistissa tilaa viemässä, ja siihen ei ole syytä kajota suorituksen aikana, koska sen on muoto on ohjelmoijalle tuntematon.
Riippuu aivan arkkitehtuurista ja mahdollisesta käyttöjärjestelmästä. C/C++ ei pakota koodia ajettavaksi RAMilta. Koodia voidaan aivan yhtä hyvin ajaa ROMilta. Moderneissa PC-arkkitehtuurin käyttöjärjestelmissäkin on virtuaalisen muistin konsepti, jolla ajettavaa pätkää voidaan swapata kovalevyltä RAMille.
Siinä olen samaa mieltä, että suoritettavaan koodiin ei ole syytä kajota ajon aikana, mutta perusteluista olen täysin eri mieltä. Mahdollista se on, eikä edes kauhean vaikeaa, mutta täysin hyödytöntä.
jsbasic kirjoitti:
Nähtävästi C/C++:lla ei ole helppo toteuttaa monimutkaisia muistiratkaisuja
Sen takia niitä varmaan sanotaankin _monimutkaisiksi_ ratkaisuiksi. Mitä sellaista yrität tehdä, mitä ei helpolla (valmiilla) ratkaisulla saisi aikaiseksi? Eli kerro mitä yrität oikeasti tehdä, niin kysymyksiisi olisi helpompi vastatakin.
Torgo kirjoitti:
Siinä olen samaa mieltä, että suoritettavaan koodiin ei ole syytä kajota ajon aikana, mutta perusteluista olen täysin eri mieltä. Mahdollista se on, eikä edes kauhean vaikeaa, mutta täysin hyödytöntä.
Miksi kertoa mielipidettään, kun asian voi tarkistaakin. Kyllä itse itseään muokkaava koodin on joskus tarpeellinen:
http://en.wikipedia.org/wiki/Self_modifying_code
Jos teillä on täällä tuollaisia ennakkoluuloja, niin lienee turha yrittää kertoa mitä suunnittelen. Tai ehkä kerroin jo, mutta jotkut eivät ymmärtäneet.
Edes C:llä ei voi tehdä kaikkea, vaan Assemblyllekin on edelleen käyttöä:
http://en.wikipedia.org/wiki/Assembly_language#Current_usage
Mutta minun ongelmaan taitaa riittää C, joka on yksinkertaisempi ja ennustettavampi kuin C++:
http://linuxdevcenter.com/pub/a/linux/2003/05/
"While kernel development, embedded software, and hard real-time systems can also benefit from the use of C++, the simple, predictable C is often the better choice for such applications."
Siis pitää luopua olioista...
On kuitenkin perusteltua keskustella yleisistä tapauksista, varsinkin jos keskustelun aloittaja ei kerro mistään erityisestä tarpeesta. Jos lähtee jokaisen yksityiskohdan ja jokaisen mahdollisuuden käymään läpi, niin mistä tahansa asiasta saa kirjoitettua 1000-sivuisen romaanin - eikä se ole keskustelufoorumilla perusteltua.
Eli itsemuokkaavan koodin voidaan sanoa olevan jokseenkin hyödytöntä jos puhutaan sovellusohjelmoinnista nykyisille PC-koneille. Hyvin rajoitetuilla resursseilla ja käskykannoilla toimivat järjestelmät on asia erikseen.
Ja assemblyllä on toki käyttöä esimerksi noissa tapauksissa mitä tuolla on lueteltu, mutta en näe miten se liittyy tässä keskusteltavana olevaan aiheeseen.
jsbasic kirjoitti:
Jos teillä on täällä tuollaisia ennakkoluuloja, niin lienee turha yrittää kertoa mitä suunnittelen. Tai ehkä kerroin jo, mutta jotkut eivät ymmärtäneet.
Ehkä? Et itsekään ole aivan varma? Odotas, kasaan:
jsbasic kirjoitti:
En tarkoita osoitintaulukkoja, vaan haluan sijoittaa oliot muistiin perätysten -- Kyse on vain data-alkioista, joita haluaisin herätellä olioksi yksi kerrallaan
jsbasic kirjoitti:
Tietue voisi olla joka oliolle sama, vaikka oliot käsittelisivät sitä eri tavoin. Käyttäisin siis tietuetaulukkoa
jsbasic kirjoitti:
Siis muistinkulutus oli suurin ongelmani
Hukkuu tällaiseen joukkoon:
jsbasic kirjoitti:
Joskus täytyy tehdä myös omia palikoita. Jos ei täytyisi, C++ olisi poistunut jo käytöstä, koska vectorit löytyy javastakin.
jsbasic kirjoitti:
Kaupallisissa sovelluksissa suosituin tekniikka on harvoin parempi. Hyvin tekemistä pitäisi rajoittaa hallitusti.
jsbasic kirjoitti:
Olen sen verran tutustunut konekieliohjelmointiin, että väitän(ainakin 1980-luvun) tietokoneen rakenteen sallivan vielä C++ vapaammankin muistinhallinnan.
jsbasic kirjoitti:
Toiseksi, tässä keskustelussa on tullut ilmi, että muistia on pakko käyttää "normaalisti". Nähtävästi C/C++:lla ei ole helppo toteuttaa monimutkaisia muistiratkaisuja niin, että ne olisivat yhteensopivia C/C++:n sisäänrakennettujen taulukoiden, tietueiden ja olioiden
jsbasic kirjoitti:
Edes C:llä ei voi tehdä kaikkea, vaan Assemblyllekin on edelleen käyttöä:
Kaiken kaikkiaan, vaikka keskusteluista saisi jonkinlaisen kuvan siitä, mitä yrität saada aikaiseksi (olkoonkin, että aloituspostissa vain kysyit, kannattaako näin edes tehdä), ei siitä käy ilmi, mitä olet tekemässä. Onko valitsemasi ohjelman rakenne "ollenkaan" hyvä tähtäämääsi ongelmaan, sitä on vaikea sanoa. Tarkemmin perehtymättä voisi vain luulla, että tässä rakennetaan mutun pohjalta "tehokasta" purkkaa.
Kommentoin vanhaa:
eq kirjoitti:
Kun tämän tiedon yhdistää siihen, että useissa viesteissä myönnät olevasi C++-noviisi, on vain vaikea ymmärtää mistä oikein ideoitasi ammennat ja varsinkin *miksi ihmeessä* pidät niistä niin vahvasti kiinni.
Kyllä olen C++ noviisi, tai olin ainakin vielä vuosi sitten. Mutta kokemusta on mm. Javasta, C-kielestä, Prologista ja vähän konekielestäkin.
Enkä pidä vahvasti kiinni. Tämä oli rento muistinhallinnollinen spekulaatio, joka johti siihen päätelmään, että optimointia vaativat kohdat kannattaa kirjoittaa puhtaalla C:lla, tai joskus jopa Assylla.
Kokonaisuudesta olisi mahdotonta keskustella, ja halusinkin rajata keskustelun muistinkäytön optimointiin. Eri asia on se, onko tälle optimoinnille lopulta mitään tarvetta. Se riippuu myös siitä, kuinka paljon muistia voidaan optimoida. Ei vain ohjelman yleisestä rakenteesta.
"Evil is in The Detail"
jsbasic kirjoitti:
Tämä oli rento muistinhallinnollinen spekulaatio, joka johti siihen päätelmään, että optimointia vaativat kohdat kannattaa kirjoittaa puhtaalla C:lla, tai joskus jopa Assylla.
Tuo on aivan selvästi väärin.
C:n käytöstä ei saa muistinkäytön puolesta lainkaan etua C++:aan nähden, ja konekielelläkin ainoa ero syntyy niistä muutamasta tavusta, jotka ehkä voi pinosta säästää, jos onnistuu optimoimaan rekisterinsä paremmin kuin kääntäjä. Kääntäjää kahlitsevat tietyt esivaatimukset siitä, mitkä rekisterit saa sotkea ja mitkä on palautettava ennalleen ennen funktion päättymistä.
Vetosit konekielen "joustavampaan" muistinkäyttöön. Tässä on sinulle samaa joustavaa muistinkäyttöä puhtaalla C++:lla:
*reinterpret_cast<int*>(0x123) = 10;
Joustavaa muistinkäyttöä edustaa myös aiemmin esittelemäni placement new, jolla voi luoda vaikka VGA-näyttömuistialuetta käsittelevän olion.
Puhtaalla C:llä samainen joustava muistinkäyttö tapahtuu lyhyemmin, ja myös tämä muoto on kelvollista C++:aa:
*(int*)0x123 = 10;
jsbasic kirjoitti:
Siis x:n pitäisi olla tyypiltään vain joko A tai B.
Riittääkö ohjelmointikokemuksesi sen ymmärtämiseen, että jos A::f() tekee eri asian kuin B::f(), sinun pitää tietää jo koodissa (kuten union-esimerkissäni), kumpaa kutsutaan, tai tallentaa johonkin tieto, onko kyseessä A-olio vai B-olio, jolloin joudut tarkistamaan asian itse? Jos olet asiasta eri mieltä, näytä ihmeessä niillä konekieli- ja C-taidoillasi, miten tämä onnistuu "joustavammin".
Metabolix kirjoitti:
C:n käytöstä ei saa muistinkäytön puolesta lainkaan etua C++:aan nähden
Niin no C on imperatiivinen kieli, ja siitä voi päätellä ettei siitä ole suurta etua. Oliot kuitenkin ovat olemassa juuri muistinkäyttöä varten, tai siis yhdistämään datan ja ohjelmakoodin.
Metabolix kirjoitti:
*reinterpret_cast<int*>(0x123) = 10;
OK. Tuosta en ole kuullut...
Metabolix kirjoitti:
Joustavaa muistinkäyttöä edustaa myös aiemmin esittelemäni placement new, jolla voi luoda vaikka VGA-näyttömuistialuetta käsittelevän olion.
Placement newiä olen käyttänyt, mutta sen käyttö on vielä epäselvää. Miksi pelkkä olio-osoitin ei ei riitä, ja mitä placement newiä kutsuttaessa tapahtuu? Viekö se ylimääräistä aikaa?
Metabolix kirjoitti:
Riittääkö ohjelmointikokemuksesi sen ymmärtämiseen, että jos A::f() tekee eri asian kuin B::f(), sinun pitää tietää jo koodissa (kuten union-esimerkissäni), kumpaa kutsutaan, tai tallentaa johonkin tieto, onko kyseessä A-olio vai B-olio, jolloin joudut tarkistamaan asian itse?
Vaikea homma. C:ssä on ainakin mahdollista tehdä funktio, joka palauttaa oikean funktiopointterin riippuen siitä mitä unioni tai tietue edustaa. Oliko se nyt
pt2Func getToStringMethod(){ if(olio.tyyppi==CAR) return &carToString; }
Siten ei tarvita ehtoja tai switch-caseja.
jsbasic kirjoitti:
Oliot kuitenkin ovat olemassa juuri muistinkäyttöä varten, tai siis yhdistämään datan ja ohjelmakoodin.
Oliot ovat ohjelmoijaa varten eivätkä muuta mitenkään sitä, mitä ohjelmassa sisäisesti tapahtuu. Lue vaikka tämän oppaan ensimmäinen esimerkki.
jsbasic kirjoitti:
Tuosta [reinterpret_cast-operaatiosta] en ole kuullut...
Mutta oletko kuullut C:n vastaavasta rakenteesta? Tuloshan on aivan sama.
jsbasic kirjoitti:
Miksi pelkkä olio-osoitin ei ei riitä, ja mitä placement newiä kutsuttaessa tapahtuu? Viekö se ylimääräistä aikaa?
Tiedätkö siis yhtään mitään olioista? Jos et, on aika typerää edes aloittaa tällainen keskustelu. (Tosin aiemmistakin keskusteluista on jäänyt kuva, että usein et ole paljonkaan perehtynyt asioihin ennen kyselyä.)
Olion luonnin yhteydessä kutsutaan olion muodostinta, jos sellainen on. Tietenkin voit käyttää olio-osoitinta, jos olio ei sisällä mitään alustettavia jäseniä. Ero on tämä:
#include <cstdio> #include <memory> struct A { int x; A(): x(123) {} }; int main() { A* a; char data[sizeof(A)] = {12, 34}; a = (A*)data; std::printf("%d\n", a->x); // Tulostaa jotain roskaa. a = new (data) A; std::printf("%d\n", a->x); // Tulostaa 123, koska new kutsuu A():ta. }
jsbasic kirjoitti:
C:ssä on ainakin mahdollista tehdä funktio, joka palauttaa oikean funktiopointterin riippuen siitä mitä unioni tai tietue edustaa.
Niin varmasti on, ja C++:n virtuaalifunktiot ajavat aivan saman asian ilman yhtäkään omaa funktiokikkailua.
Jos annan sinulle seuraavanlaisen datakimpaleen, mistä tiedät, onko se tyypiltään A vai B?
struct Data { int x, y; };
Vastaus: et mistään. Kuten sanoin, sinun on tiedettävä tyyppi valmiiksi tai tallennettava se datan mukaan.
jsbasic kirjoitti:
Siten ei tarvita ehtoja tai switch-caseja.
Ota nyt silmä käteen. Koodissasi on ehto, vaikka se onkin funktion sisällä.
Kuten sanoin, tarvitset joko ehtoja (if (data.tyyppi == 'A') return A_f;
tai valmiiksi kootun taulukon funktioista (return funktiot[data.tyyppi]
).
C++: virtuaalifunktiosysteemissä olio sisältää osoittimen luokan tietoihin, jolloin yhden olion kohdalla "ylimääräistä" muistia kuluu osoittimen verran ja funktiokutsu sisältää kaksi ylimääräistä muistiviittausta tavalliseen kutsuun varten.
Käsin ei päästä tässä juuri parempaan: Muistia voi teoriassa säästää pari tavua, jos käyttää osoittimen sijaan yhden tavun kokoista tyyppi-id:tä ja GCC:n pack-attribuuttia. Samalla ohjelma hidastunee entisestään. Vaihtoehtoisesti voidaan säästää aikaa tallentamalla kaikki funktio-osoittimet suoraan olioon, jolloin taas muistia kuluu paljon enemmän ja olion luonti hidastuu mutta funktiokutsu vaatii vain yhden muistiviittauksen.
jsbasic kirjoitti:
Torgo kirjoitti:
Siinä olen samaa mieltä, että suoritettavaan koodiin ei ole syytä kajota ajon aikana, mutta perusteluista olen täysin eri mieltä. Mahdollista se on, eikä edes kauhean vaikeaa, mutta täysin hyödytöntä.
Miksi kertoa mielipidettään, kun asian voi tarkistaakin. Kyllä itse itseään muokkaava koodin on joskus tarpeellinen:
Luitkohan itse tuota pastettamaasi linkkiä lainkaan? Kuten siinä sanotaan, niin keinoa käytetään esim. korvaamaan koodia debug-koodilla riippuen ohjelman käynnistysparametrista. Tällöin varsinaisen ajon aikana ei tarvitse enää ehtolauseita erikseen. Tämä kuitenkin lisää käynnistysaikaa ja muistinkulutusta, sekä monimutkaistaa koodia tarpeettomasti. C:n esikääntäjällä voi tehdä saman asian paljon näppärämmin ilman mitään overheadia muistin- tai tehonkäytössä. Jos kerta ongelmasi oli muistinkulutus, niin miksi käyttäisit tekniikkaa joka kuluttaa sitä enemmän?
Sitten päästään tuohon tehokkuuteen. Varmuudella se tuo lisää overheadia, kun koodia joudutaan muokkaamaan ajon aikana. Itse varsinaisen koodin suoritukseenkin se luultavimmin tuo ennemmin hidastusta kuin nopeutusta. Johtuen ihan siitä, että kääntäjän optimoinnit osaavat usein käyttää prosessorin pipelinea hyvin hyväkseen. Koodia muokatessa ajon aikana se on aika hankalaa ja lisää varmuudella suoritusaikaa. Jos muokkaus tapahtuu vain kerran ohjelman alussa, niin sillä saatetaan saavuttaa aavistuksenomainen nopeutus funktio-osoittimiin tai ehtolauseisiin nähden. Paino sanalla saatetaan, koska sekin on tapauskohtaista.
Kolmas asia, jos nyt unohdetaan että itseään muokkaava koodi on virhealttiimpaa ja hankalempi ylläpitää, on että useissa platformeissa itsemuokkaava koodi on kokonaan estetty. Esim. Windows ja Linux eivät anna oikeutta kirjoittaa muistialueelle mistä komentoja suoritetaan. Tehden siis käytännössä koko homman mahdottomaksi.
jsbasic kirjoitti:
Kokonaisuudesta olisi mahdotonta keskustella, ja halusinkin rajata keskustelun muistinkäytön optimointiin. Eri asia on se, onko tälle optimoinnille lopulta mitään tarvetta. Se riippuu myös siitä, kuinka paljon muistia voidaan optimoida. Ei vain ohjelman yleisestä rakenteesta.
Kuten sanottua, niin asia on aina tapauskohtaista. Jos ei ole ongelmaa, niin siihen on hankala esittää ratkaisuakaan. Ei ole olemassa yhtä oikeaa tapaa miten tehdä kaikki. Jos olisi, niin se olisi jo c:ssä valmiiksi, eikä omia kikkailuja kannattaisi edes miettiä. Itse jouduin vähän aikaa sitten optimoimaan 12kB koodin alle 10kB:iin. Koodi pieneni mm. tavanomaisilla refactoroinneilla, kuten ehtojen ja funktioiden uudelleenjärjestelyillä. Lisäksi vähemmän tavallisilla kikkailuilla, kuten kaikkien jakolaskujen korvaamisella vähennyslaskuloopeilla ja standardikirjaston funktioiden korvaamisella sovellusta varten räätälöidyillä vastaavilla funktoilla. Käytännössä korvasin useita assylla kirjoitettuja funktioita vastaavilla pienempään tilaan menevillä c-funktioilla.
jsbasic kirjoitti:
Edes C:llä ei voi tehdä kaikkea, vaan Assemblyllekin on edelleen käyttöä:
http://en.wikipedia.org/wiki/Assembly_language#Current_usage
Lähes kaiken noista voi tehdä aivan hyvin c:llä. Joihinkin noista toki assyakin tarvitaan ja useimpiin siitä voi olla hyötyä. En nyt näe kuitenkaan tässä mitään yhteyttä keskustelun aiheen kanssa.
jsbasic kirjoitti:
Siten ei tarvita ehtoja tai switch-caseja.
Koodissasi on sekä ehtolause, että aivan turha funktiokutsu. Se on sekä muistinkulutukselta että suoritusnopeudeltaan tehoton vaihtoehto. Parempi olisi vaikka:
const pt2Func stringToMethod[] = { &carToString, &planeToString, // jne. }; stringToMethod[olio.tyyppi]();
Torgo kirjoitti:
jsbasic kirjoitti:
Miksi kertoa mielipidettään, kun asian voi tarkistaakin. Kyllä itse itseään muokkaava koodin on joskus tarpeellinen:
Luitkohan itse tuota pastettamaasi linkkiä lainkaan? Kuten siinä sanotaan, niin keinoa käytetään esim. korvaamaan koodia debug-koodilla riippuen ohjelman käynnistysparametrista. Tällöin varsinaisen ajon aikana ei tarvitse enää ehtolauseita erikseen. Tämä kuitenkin lisää käynnistysaikaa ja muistinkulutusta, sekä monimutkaistaa koodia tarpeettomasti. C:n esikääntäjällä voi tehdä saman asian paljon näppärämmin ilman mitään overheadia muistin- tai tehonkäytössä. Jos kerta ongelmasi oli muistinkulutus, niin miksi käyttäisit tekniikkaa joka kuluttaa sitä enemmän?
Sitten päästään tuohon tehokkuuteen. Varmuudella se tuo lisää overheadia, kun koodia joudutaan muokkaamaan ajon aikana.
Osallistutaan nyt tähän keskusteluun sen verran, että tuo itse muokkaavan koodin käyttö oli yleistä vanhojen 80 -ja 90-luvuilla rakennettujen kotitietokoneiden (esim. oma harraste koneeni SAM Coupé) kanssa puuhailevien keskuudessa.
Tuohon aikaan prosessorit ja tietokoneet olivat sen verran paljon yksinkertaisempia, että itse muokkaavaa koodia voitiin hyödyntää.
Ja tokihan tuo säästää tilaa, kun ohjelmassa erilliselle muuttujalle tilan varaamisen sijaan data laitetaankin suoraan jonkun käskyn opkoodiin. Samaisesta syystä joistain output rutiineista pystyttiin saamaan nopeampia, kun dataa ei erikseen tarvinnut hakea muuttujasta.
Nykypäivänä nykyprosessorien kanssa homma menee liian vaikeaksi, eikä VARMASTI ole vaivan arvoista.
jalski kirjoitti:
Osallistutaan nyt tähän keskusteluun sen verran, että tuo itse muokkaavan koodin käyttö oli yleistä vanhojen 80 -ja 90-luvuilla rakennettujen kotitietokoneiden (esim. oma harraste koneeni SAM Coupé) kanssa puuhailevien keskuudessa.
No hyvä! Itse olen kirjoitellut Commodore 64:n konekielellä pienen ohjelman, ja siinä koodin muokkaus tuntuu ihan luonnolliselta ajatukselta.
jalski kirjoitti:
Tuohon aikaan prosessorit ja tietokoneet olivat sen verran paljon yksinkertaisempia, että itse muokkaavaa koodia voitiin hyödyntää.
Olisi hyvin mielenkiintoista jos joku osaisi kertoa, että millä tavalla prosessorit ja tietokoneet olivat yksinkertaisemmin optimoitavia? Pitääkö se vain niellä luonnollisena kehityksenä?
Ainakin käsittämättömän suuret osoittimet, joita C/C++ asiantuntijat täälläkin suosivat, kertovat siitä että "monimutkaistuminen" saattaa johtua siitä että tietokoneiden kehitys on jämähtänyt von Neumannin arkkitehtuuriin, joka on aiheuttanut pullonkaulan muistin ja prosessorin välille:
http://en.wikipedia.org/wiki/
Jos prosessorien määrän ja muistin koon suhdeluku olisi säilynyt samana 80-luvulta asti, niin mitään bittimäärän kasvua 8-bitistä 64:n ei kai olisi tapahtunut.
Samoin C ja muut sen pohjalta kehitetyt imperativiiset kielet eivät nauttisi suosiosta funktionaalisten kielten kustannuksella, koska tietokoneen toiminta ei riippuisi yhdestä prosessorista ja ohjelmasta.
Diagnoosia:
http://users.jyu.fi/~antkaij/opetus/okp/2007/
"Imperatiivisen ohjelmoinnin (käskyohjelmoin-
nin) juuret ovat syvällä ratkaisuavaruudessa,
von Neumannin arkkitehtuurin perusra-
kenteissa. Imperatiivinen ohjelmoija näkee
maailman joukkona muistipaikkoja, joita
muutellaan yksitellen “von Neumannin
pullonkaulaaö pitkin. Imperatiiviselle ohjel-
moinnille tyypillistä on tiedon muuttaminen
in place (sitä kopioimatta), silmukoiden run-
sas käyttö, ohjelmakoodin korostuminen sekä
käskymetafora"
Ohjelmakoodin korostuminen tarkoittanee myös ettei siihen saa kajota (muokata) ajon aikana. Koodilla on kaikki valta.
jsbasic kirjoitti:
Olisi hyvin mielenkiintoista jos joku osaisi kertoa, että millä tavalla prosessorit ja tietokoneet olivat yksinkertaisemmin optimoitavia?
Yksinkertaisempi ja yksinkertaisemmin optimoitava eivät ole sama asia. Tässä tapauksessa asia on juurikin päinvastoin. Asiaa on mahdoton lyhyesti selittää, mutta johtuu mm. jo edellä mainitsemani pipelinen ja käskykannan kehityksestä, sekä siitä miten kääntäjät osaavat niitä hyödyntää.
jsbasic kirjoitti:
Ainakin käsittämättömän suuret osoittimet
Jaa mitkä? Osoittimet ovat vakiokokoisia.
jsbasic kirjoitti:
"monimutkaistuminen" saattaa johtua siitä että tietokoneiden kehitys on jämähtänyt von Neumannin arkkitehtuuriin
Jos prosessorien määrän ja muistin koon suhdeluku olisi säilynyt samana 80-luvulta asti, niin mitään bittimäärän kasvua 8-bitistä 64:n ei kai olisi tapahtunut.
Häh? Meinaat siis että on monimutkaisempaa tehdä koodia yhdelle 64-bittiselle prosessorille, jolla on 32 GB ulkoista muistia, kuin 524288 8-bittiselle prosessorille, jotka tappelevat jatkuvasti keskenään kuka saa tehdä mitäkin?
Torgo kirjoitti:
jsbasic kirjoitti:
Ainakin käsittämättömän suuret osoittimet
Jaa mitkä? Osoittimet ovat vakiokokoisia.
Osoittimien koon määrää tietenkin prosessorin käyttämä muistiavaruuden koko. Mikseivät kääntäjät muuten tue 16-bittisiä osoittimia? Siihenkin on todennäköisesti syynä von Neumannin arkkitehtuuri.
Torgo kirjoitti:
jsbasic kirjoitti:
"monimutkaistuminen" saattaa johtua siitä että tietokoneiden kehitys on jämähtänyt von Neumannin arkkitehtuuriin
Jos prosessorien määrän ja muistin koon suhdeluku olisi säilynyt samana 80-luvulta asti, niin mitään bittimäärän kasvua 8-bitistä 64:n ei kai olisi tapahtunut.
Häh? Meinaat siis että on monimutkaisempaa tehdä koodia yhdelle 64-bittiselle prosessorille, jolla on 32 GB ulkoista muistia, kuin 524288 8-bittiselle prosessorille, jotka tappelevat jatkuvasti keskenään kuka saa tehdä mitäkin?
32 GB:n kokoiset järjestelmät ovat joka tapauksessa monimutkaisia, mutta ehkä 524288 prosessoria olisi yhteen kuumakalleen verrattuna yksinkertaisempi, ainakin paljon luontevampi ratkaisu.
jsbasic kirjoitti:
Mikseivät kääntäjät muuten tue 16-bittisiä osoittimia?
Mistä sait päähäsi että ei tue? Riippuu arkkitehtuurista ja käytetystä muistimallista. Minulla tällä hetkellä käytössä oleva c-kääntäjä tukee vain 8- ja 16-bittisiä osoittimia. Jos aivan väkisin haluat tehdä osoittimen, jolla ei voi osoittaa kuin murto-osaan muistista, niin kyllä sekin onnistuu eksplisiittisellä tyyppimuunnoksella. Voit siten tehdä vaikka 8-bittisiä osoittimia.
jsbasic kirjoitti:
Siihenkin on todennäköisesti syynä von Neumannin arkkitehtuuri.
Nykykoneet eivät edes ole von Neumannin arkkitehtuurin mukaisia kuin osittain. Ja niidenkin jotka eivät ole lainkaan sen mukaisia, on jotenkin pystyttävä löytämään muistialueet ja muut käytössä olevat resurssit.
jsbasic kirjoitti:
ehkä 524288 prosessoria olisi yhteen kuumakalleen verrattuna yksinkertaisempi, ainakin paljon luontevampi ratkaisu.
Heh. Ratkaisu on siis jättää olemassa oleva pullonkaula ennalleen ja lisätä siihen vielä päälle toinen kahta kauheampi pullonkaula moninkertaisilla kustannuksilla. :D
Torgo kirjoitti:
Jos aivan väkisin haluat tehdä osoittimen, jolla ei voi osoittaa kuin murto-osaan muistista, niin kyllä sekin onnistuu eksplisiittisellä tyyppimuunnoksella.
Niin varmaan, mutta von Neumannin arkkitehtuurin vuoksi se ei kannata. Nykytilanteessa on toimittava niin kuin Metabolix "käskee" ja syy on von Neumannin arkkitehtuuri. Mutta tilanne muuttuu tulevaisuudessa. Tuleehan ytimiä lisää. Osoitettava alue pienenee, ja C-kielen merkitys vähenee.
Kyllä esim. Harvard arkkitehtuuria käyttävillekin on hyvin yleistä kirjoittaa esim. C:llä, enkä muutenkaan älyä miten juuri von Neumannin arkkitehtuuri (yksi muistiavaruus koodille ja datalle) suosisi millään tavalla C-kieltä. C-kielelle on ihan tasan sama vaikka koodi ei olisi ollenkaan muistissa.
Siitä olen toki samaa mieltä että C-kielen merkitys (osuus kokonaisuudesta) pienenee kaiken aikaa. Taitaa olla jo nykyään aika harvinaista tehdä C:llä. Jo C++:kin tarjoaa niin paljon miellyttävämmän ympäristön, että C:tä käytetään lähinnä silloin kun resurssit on kalliimpia kuin kehitysaika.
Grez kirjoitti:
Siitä olen toki samaa mieltä että C-kielen merkitys (osuus kokonaisuudesta) pienenee kaiken aikaa. Taitaa olla jo nykyään aika harvinaista tehdä C:llä. Jo C++:kin tarjoaa niin paljon miellyttävämmän ympäristön, että C:tä käytetään lähinnä silloin kun resurssit on kalliimpia kuin kehitysaika.
... tai silloin kun se - syystä tai toisesta - ainoa käytettävissä oleva ns. korkean tason kieli.
Onko joku erityinen ympäristö mielessä jossa näin olisi. Itselle tulee ensimmäisenä mieleen jotkut 8-bittiset mikrokontrollerit, mutta niissä mennään juuri tällä "hyvin rajoitetut resurssit" teemalla.
Ja varmaankin jos joku ympäristö oli mielessä, niin se on melko harvinainen, eli ei tee tyhjäksi teesiäni että C:n osuus ohjelmistotuotannosta olisi yhä laskussa?
Grez kirjoitti:
Kyllä esim. Harvard arkkitehtuuria käyttävillekin on hyvin yleistä kirjoittaa esim. C:llä, enkä muutenkaan älyä miten juuri von Neumannin arkkitehtuuri (yksi muistiavaruus koodille ja datalle) suosisi millään tavalla C-kieltä. C-kielelle on ihan tasan sama vaikka koodi ei olisi ollenkaan muistissa.
Täytyy myöntää että nämä ovat minulle vielä epäselviä käsitteitä, joiden käyttöä haluaisinkin tarkentaa.
Tuo rakenne, "yksi muistiavaruus koodille ja datalle" tarkoittaa käytännössä sitä, että CPU:n on haettava muistista jatkuvasti sekä komentoja että dataa, joten muistin ja prosessorin väliin tulee paljon liikennettä.
Lainaamasi käsite "muistiavaruus" tarkoittaa ilmeisesti osoiteavaruutta. Tuskin se tarkoittaa sitä, data ja koodi olisivat fyysisesti samassa muistissa, vaan siitä että ne ovat CPU:sta katsoen fyysisesti samassa väylässä, saman näköisen osoitteen takana. CPU näkee jopa Harvard-arkkitehtuurin käyttämän välimuistin ja oheislaitteet ikään kuin yhtenä muistina. Se että ohjelman syöttää ROM-muistissa, ei muuta mitenkään CPU:n arkkitehtuuria.
Arkkitehtuuri suosii imperatiivisia kieliä siksi, että kaikki toiminnallisuus on yhden CPU:n vastuulla. Vrt sitä esim yhteiskuntaan ("imperiumiin") jossa on yksi hallitsija, joka antaa käskyjä kansalle. Käskyt tulee ylhäältä, ulkopuolelta, ja kansa on vain muistipaikkoja, joilla suoritetaan operaatioita.
Grez kirjoitti:
Siitä olen toki samaa mieltä että C-kielen merkitys (osuus kokonaisuudesta) pienenee kaiken aikaa. Taitaa olla jo nykyään aika harvinaista tehdä C:llä. Jo C++:kin tarjoaa niin paljon miellyttävämmän ympäristön, että C:tä käytetään lähinnä silloin kun resurssit on kalliimpia kuin kehitysaika.
Kyllä. C++-koodista aika suuri osa on kuitenkin C-kieltä? Saattaa olla vielä aika vaikea tehdä C++ ohjelmaa, jossa ei olisi yhtään komentoa, mutta periaatteessa C++ antaa siihen mahdollisuuden. Mutta silloin se ei olisi enää C++, vaan ++ tai X++. ;)
jsbasic kirjoitti:
CPU näkee jopa Harvard-arkkitehtuurin käyttämän välimuistin ja oheislaitteet ikään kuin yhtenä muistina.
Et ilmeisesti ole koskaan koodaillut millekään Harvard-arkkitehtuurin prosessorille, koska tämähän on aivan selvästi virheellinen väite. Joissakin prosessoreissa voi toki olla käskyt myös ohjelmamuistin lukemiseen ja kirjoittamiseen. Niissä mitä olen itse käyttänyt ei ole ollut. Joka tapauksessa CPU ei näe niitä yhtenä muistina eikä näe koodaajakaan. Eli niissä mitä olen käyttänyt prosessori ei voi ohjelmallisesti lukea eikä kirjoittaa ohjelmamuistiin, ainoastaan poimia käskyjä suoritettavaksi. Ja prosessorissa on erillinen väylä ohjelmamuistille. Voi toki olla mahdollista käsitellä myös ohjelmamuistia esimerkiksi joidenkin rautarekistereiden kautta, mutta se ei ohjelmakoodillisesti eroa mitenkään siitä kun käytettäisiin vaikka DA-muunninta.
jsbasic kirjoitti:
Se että ohjelman syöttää ROM-muistissa, ei muuta mitenkään CPU:n arkkitehtuuria.
Ei toki automaattisesti muuta Harvard vs von Neumann arkkitehtuurien välillä, mutta muuten voi muuttaa. Pointtini kuitenkin oli että C:n kannalta ei ole mitään merkitystä vaikka suoritettava koodi tulisi prosessorille reikänauhalta tai taikuudella.
C ei toki ole paras mahdollinen esimerkiksi massiivisesti rinnakkaisen järjestelmän koodaamiseen. Siksi esimerkiksi massiivisesti rinnakkaisen logiikan koodaamisene käytetään esim. VHDL:ää tai Verilogia (joista ainakin toinen syntaksiltaan muistuttaa huomattavasti C:tä, en muista kumpaa olen katsellut)
jsbasic kirjoitti:
Kyllä. C++-koodista aika suuri osa on kuitenkin C-kieltä? Saattaa olla vielä aika vaikea tehdä C++ ohjelmaa, jossa ei olisi yhtään komentoa, mutta ehkä se on mahdollista.
Se että syntaksi on samankaltainen ei mielestäni tee C++:sta C-kieltä. Tuolla logiikalla Java ja Javascriptikin olisi suurelta osin C-kielellä koodaamista. Ja jos koodaa C++:aa samalla tavalla kuin koodaisi C:tä niin tekee asian ns. "väärin". C++-ohjelmoijalla pitäisi olla jossain määrin erilainen ajatusmalli kuin C-ohjelmoijalla.
jsbasic kirjoitti:
Arkkitehtuuri suosii imperatiivisia kieliä siksi, että kaikki toiminnallisuus on yhden CPU:n vastuulla. Vrt sitä esim yhteiskuntaan ("imperiumiin") jossa on yksi hallitsija, joka antaa käskyjä kansalle. Käskyt tulee ylhäältä, ulkopuolelta, ja kansa on vain muistipaikkoja, joilla suoritetaan operaatioita.
No eipä sillä imperatiivisuudella ole niinkään suurta merkitystä montako CPU:ta on. Jos CPU:t on luonteeltaan imperatiivista koodia suorittavia, niin ne suorittaa imperatiivista koodia vaikka niitä olisi 1000. (Joskin C ei välttämättä ole paras kieli 1000:n CPU:n järjestelmälle).
Jos kiinnostaa "demokraattisemmat" järjestelmät, joissa muistisolut itsenäisesti osallistuu "ohjelman" suorittamiseen niin kannattaa tutustua vaikka FPGA-piireihin tai jos hieman korkeamman tason massiivisesti rinnakkaista laskentaa niin esim. GPU-ohjelmointiin.
Grez kirjoitti:
Eli huomautan, prosessori ei voi ohjelmallisesti lukea eikä kirjoittaa ohjelmamuistiin, ainoastaan poimia käskyjä suoritettavaksi.
En ole väittänyt, että ohjelmaa luettaisiin ohjelmallisesti, vaan että sitä luetaan saman väylän kautta kuin dataakin.
Grez kirjoitti:
Tuolla logiikalla Java ja Javascriptikin olisi C:llä koodaamista.
Ymmärsit logiikan. Java ei tue osoittimia, mutta on silti melkoisesti sukua C-kielelle. Samoin BASIC, jonka syntaksi on pinnallisesti katsoen erilainen pitkästä historiasta johtuen, mutta joka on saanut C-kielestä runsaasti vaikutteita rakenteisiinsa.
Grez kirjoitti:
Jos CPU:t on luonteeltaan imperatiivista koodia suorittavia, niin ne suorittaa imperatiivista koodia vaikka niitä olisi 1000.
Onko edes mahdollista että 1000 prosessorin järjestelmä vaikka 64 megan muistilla olisi luonteeltaan imperatiivista koodia suorittava?
jsbasic kirjoitti:
En ole väittänyt, että ohjelmaa luettaisiin ohjelmallisesti, vaan että sitä luetaan saman väylän kautta kuin dataakin.
Ja minä totesin, että sitä ei lueta saman väylän kautta. (Ainakaan niissä Harvard-arkkitehtuuria käyttävissä prosessoreissa mitä olen käyttänyt)
jsbasic kirjoitti:
Ymmärsit logiikan.
Sanoisin pikemminkin että ymmärsin logiikan puutteen. Tarkoitat siis yleisesti imperatiivisilla ohjelmointikielillä ohjelmoimista mutta puhut C-ohjelmoinnista. Olisi helpompi keskustella, jos kirjoitettaisit suoraan, mitä tarkoitat.
jsbasic kirjoitti:
Onko edes mahdollista että 1000 prosessorin järjestelmä vaikka 64 megan muistilla olisi luonteeltaan imperatiivista koodia suorittava?
En näe mitään syytä miksi se ei olisi mahdollinen. Järkevä se tuskin olisi kovinkaan moneen käyttöön lähinnä siitä syystä että suoritustehoon laitettaisiin järjettömän paljon "rahaa" suhteessa muistiin.
jsbasic kirjoitti:
En ole väittänyt, että ohjelmaa luettaisiin ohjelmallisesti, vaan että sitä luetaan saman väylän kautta kuin dataakin.
Ihan jo Harvard arkkitehtuurin määritelmän mukaisesti ne luetaan fyysisesti erillisiä väyliä pitkin. Jos ne luetaan saman väylän kautta, se ei ole Harvard Arkkitehtuuria.
jsbasic kirjoitti:
Onko edes mahdollista että 1000 prosessorin järjestelmä vaikka 64 megan muistilla olisi luonteeltaan imperatiivista koodia suorittava?
Kyllä, täysin mahdollista. Eri asia sitten onko siinä mitään järkeä. Ylipäätänsäkään jotta 1000 prosessorin järjestelmästä pienellä muistikapasiteetilla saataisiin mitään iloa irti, täytyisi ohjelman a) mahtua tuohon 64 megaan ja b) olla luonteeltaan sellaista että sitä pystytään aidosti ajamaan rinnakkain riippumatta muiden yksiköiden toiminnasta. Kumpikaan näistä ei toteudu useimmissa ohjelmissa, joten näiden 1000 prosessorin on jatkuvasti keskusteltava sekä keskenään, että ulkoisen syötteen kanssa. Näin ollaan saatu aikaiseksi uusi pullonkaula. Lisääntyneen pinta-alan, tehonkulutuksen ja ennenkaikkea kustannusten nousun lisäksi se sama vanha pullonkaula säilyy.
Jos rinnakkaisarkkitehtuuria halajat, niin tutustu vaikka Grezin mainitsemiin FPGA-piireihin ja SoCeihin.
Grez kirjoitti:
Sanoisin pikemminkin että ymmärsin logiikan puutteen. Tarkoitat siis yleisesti imperatiivisilla ohjelmointikielillä ohjelmoimista mutta puhut C-ohjelmoinnista. Olisi helpompi keskustella, jos kirjoitettaisit suoraan, mitä tarkoitat.
Sanoinhan jo että "nämä ovat minulle vielä epäselviä käsitteitä, joiden käyttöä haluaisinkin tarkentaa", ja oletan että ne ovat sitä samaa teille kanssakeskustelijoille.
Torgo kirjoitti:
Jos ne luetaan saman väylän kautta, se ei ole Harvard Arkkitehtuuria.
Jos Harvard määritellään noin, niin sellaiset koneet ovat varmasti melkoisia poikkeuksia. Ehkä jossain signaalinkäsittelyssä tms. Tosin en ole aivan varma väylän käsitteestä. Puhuisin mieluummin muisti- tai osoiteavaruudesta.
Torgo kirjoitti:
jsbasic kirjoitti:
Onko edes mahdollista että 1000 prosessorin järjestelmä vaikka 64 megan muistilla olisi luonteeltaan imperatiivista koodia suorittava?
Kyllä, täysin mahdollista.
Luitko kokonaan: "luonteeltaan imperatiivista koodia suorittava". Jos et kerran voi ajaa siinä imperatiivista koodia niin miten se on "täysin mahdollista"?
jsbasic kirjoitti:
Jos Harvard määritellään noin, niin sellaiset koneet ovat varmasti melkoisia poikkeuksia. Ehkä jossain signaalinkäsittelyssä tms. Tosin en ole aivan varma väylän käsitteestä. Puhuisin mieluummin muisti- tai osoiteavaruudesta.
Miten niin _varmasti_ melkoisia poikkeuksia? Luulen että jokatoisessa pesukoneessa on tuollainen prosessori. Toki, Windows-koneen prosessorina sellainen olisi melkoinen poikkeus.
jsbasic kirjoitti:
Luitko kokonaan: "luonteeltaan imperatiivista koodia suorittava". Jos et kerran voi ajaa siinä imperatiivista koodia niin miten se on "täysin mahdollista"?
Sori, mutta nyt täytyy jo kysyä mitä oikein sekoilet? Osasimme lukea kysymyksesi. Sen sijaan en näe missään viestiä jossa joku sanoisi, että sillä ei voisi ajaa imperatiivista koodia.
Sekä minä että Torgo nähdäkseni vastasimme, että sellaisen (1000 imperatiivista koodia ajavaa prosessoria sisältävän järjestelmän) tekeminen olisi mahdollista, joskaan ei järkevää.
Jos olisi tekemisestä pulaa ja noin 1000e ylimääräistä rahaa niin voisi huvikseen rakentaa tuollaisen 1000 ytimen ja 64 megan muistin tietokoneen.
Grez kirjoitti:
Miten niin _varmasti_ melkoisia poikkeuksia? Luulen että jokatoisessa pesukoneessa on tuollainen prosessori. Toki, Windows-koneen prosessorina sellainen olisi melkoinen poikkeus.
Toivottavasti se on noinkin yleistä.
Oletan että järjestelmät joissa on paljon RAM-muistia suhteessa laskennan määrään, tehdään useimmiten von Neumann -arkkitehtuurilla. Pesukoneet eivät taida kuulua tähän kategoriaan.
Kansankielellä tietotekniikasta puhuttaessa puhutaan biteistä. (Nykyään toki yhä vähemmän.) Mutta edes 8-bittisessä Commodore 64:ssa ohjelmoijalla ei ole bittitasolle paljoakaan asiaa. Nykyisin 8-bittiset tavut ovat lähes sama kuin bitit Commorodessa. Niiden käsitteleminen yksitellen on turhan hidasta, koska tietokone pystyy käsittelemään paljon suurempia lukuja kerralla.
Oletan myös että bittimäärän kasvu on aiheuttanut sen, ettei grafiikkaa ja ääntä kannata käsitellä tietokoneen omalla prosessorilla. 64-bittisyys on enemmän eduksi mm. tietokantaoperaatioissa.
En oikein tiedä liittyykö tämä mitenkään alkuperäiseen aiheeseen. Kommentoin nyt kuitenkin kun mielestäni käsityksesi esim. syy-seuraussuhteista ovat harhaisia.
jsbasic kirjoitti:
Toivottavasti se on noinkin yleistä.
Miksi toivottavasti?
jsbasic kirjoitti:
Oletan että järjestelmät joissa on paljon RAM-muistia suhteessa laskennan määrään, tehdään useimmiten von Neumann -arkkitehtuurilla.
En näe miksi nämä asiat liittyisivät toisiinsa. Enemmänkin kyse on esimerkiksi siitä, minkä kokoisia suoritettavat ohjelmat on ja vaihtuuko ohjelma kuinka usein. Esim. PC:issä kulloinkin suoritettavia ohjelmia ladataan milloin mistäkin (kiintolevy, USB-tikku, verkko) ja ohjelmakoodi on toisissa käyttötarkoituksissa kooltaan tuhatkertaisesti isompaa kuin ohjelman käsittelemä data ja toisissa tapauksissa data on isompaa kuin ohjelmakoodi. Kun molemmat käyttää samaa muistia, niin kummassakaan tapauksessa ei osa muistista jää turhaan käyttämättä. Lisäksi selvitään yhdellä ohjelmakoodille ja datalle yhteisellä virtuaalimuistiratkaisulla. Lisäksi ei tarvita useaa väylää prosessorilta, joka on selkeä kustannussäästö.
jsbasic kirjoitti:
Pesukoneet eivät taida kuulua tähän kategoriaan.
Pesukoneet kuuluu kategoriaan jossa ajetaan aina samaa ohjelmakoodia.
jsbasic kirjoitti:
Kansankielellä tietotekniikasta puhuttaessa puhutaan biteistä. (Nykyään toki yhä vähemmän.)
Mielestäni on aika epärelevanttia kummasta kansankielellä puhutaan. Asioista jotain tietävät puhuvat biteistä tai tavuista sen mukaan kumpaa tarkoittavat. Esimerkiksi Gigabitin verkossa todellakin on kyse miljardista bitistä sekunnissa. Teratavun kiintolevyssä taas biljoonasta tavusta.
jsbasic kirjoitti:
Oletan myös että bittimäärän kasvu on aiheuttanut sen, ettei grafiikkaa ja ääntä kannata käsitellä tietokoneen omalla prosessorilla. 64-bittisyys on enemmän eduksi mm. tietokantaoperaatioissa.
Mielestäni tuo 64-bittisyys on ehkä alle 1% syistä miksi esim. grafiikkaa kannattaa käsitellä GPU:lla ennemmin kuin prosessorilla. Äänen osalta taas esim. 16-bittisen äänen käsittely bitti tai tavutasolla on hyödytöntä eikä 64-bittisen prosessorin tehosta mene 16-bittisessä käsittelyssä niin paljoa hukkaan, että sillä olisi paljoakaan merkitystä. Ääntä käsitelläänkin PC:issä nykyisin todella paljon CPU:lla, mutta toki esim. 3D ääniä lasketaan äänikorteilla. Sielläkin olennaiset laskut ei tapahdu bitti tai tavutasolla ja jälleen sen n-bittisyyden merkitys on alle 1% syistä.
Grez kirjoitti:
Asioista jotain tietävät puhuvat biteistä tai tavuista sen mukaan kumpaa tarkoittavat. [...] Teratavun kiintolevyssä taas biljoonasta tavusta.
Eikö kapasiteetin ilmoittaminen tavuina ole vähän hankalaa juuri siksi, että 64-bittisen prosessorit käsittelevät levyä useimmiten isommissa lohkoissa, kuin tavuina?
Grez kirjoitti:
esim. 16-bittisen äänen käsittely bitti tai tavutasolla on hyödytöntä...
Bittitasosta minulla ei ole tietoa, mutta tavutasolla eli 8-bittisenä äänenkäsittely on tunnettu taiteenlaji. Monien mielestä se ei ole harhaa.
http://www.last.fm/tag/8-bit
"8-bit can refer to a style of electronic music inspired by the sound of old computer consoles from the 8-bit era of video games. This music will often reflect, or consist of, sounds from technology that is seen as primitive or 'outdated' such as the Game Boy and home made synthesizers."
jsbasic kirjoitti:
Grez kirjoitti:
esim. 16-bittisen äänen käsittely bitti tai tavutasolla on hyödytöntä...
Bittitasosta minulla ei ole tietoa, mutta tavutasolla eli 8-bittisenä äänenkäsittely on tunnettu taiteenlaji. Monien mielestä se ei ole harhaa.
Huoh. Hankalaa keskustella, jos et edes yritä ymmärtää lukemaasi.
1) Minun tekstissä puhuttiin 16-bittisen äänen käsittelystä.
2) Sinun laittamassasi tekstissä puhuttiin 8-bittisen aikakauden hengessä tapahtuvasta musiikin teosta. Siinä ei edes sanottu, että käsittely itsessään tapahtuisi 8-bittisillä äänillä.
Mutta tietenkin jos halutaan käsitellä 8-bittistä ääntä, niin ei se ole yhtään mikään ongelma.
Yleistän vielä teeseni: N-bittistä ääntä käsitellessä ei ole juurikaan hyötyä yksittäisten bittien tai n:tä pienempien bittijoukkojen tehokkaasta käsittelystä.
jsbasic kirjoitti:
Eikö kapasiteetin ilmoittaminen tavuina ole vähän hankalaa juuri siksi, että 64-bittisen prosessorit käsittelevät levyä useimmiten isommissa lohkoissa, kuin tavuina?
Kumpi sinusta olisi ihan oikeasti järkevämpi tapa ilmoittaa kiintolevyn koko:
Nykyinen:
1 Teratavu
Vai ehdottamasi:
512 tavun lohkoja käytettäessä 1953 megalohkoa tai 1024 tavun lohkoja käytettäessä 976 megalohkoa tai 2048 tavun lohkoja käytettäessä 488 megalohkoa tai 4096 tavun lohkoja käytettäessä 244 megalohkoa tai 8192 tavun lohkoja käytettäessä 122 megalohkoa tai 16384 tavun lohkoja käytettäessä 61 megalohkoa tai 32768 tavun lohkoja käytettäessä 30,5 megalohkoa tai 65536 tavun lohkoja käytettäessä 15,3 megalohkoa
Olisiko myös kätevämpää jos kaupunkien väliset etäisyydet ilmoitettaisiin "tankillisina" eikä kilometreinä.. Helsingistä Utsjoelle 2,7 tankillista (jos ajat autolla X)
Yhä uudelleen täytyy hämmästyä, miten eri tasoilla tässä keskustellaan. Etkö viitsisi lukea vaikka Wikipediasta, miten tavallinen tietokone toimii? Ei tarvitsisi tahkota perusasioita. Olisi myös mukava, jos et esittäisi epävarmoja arvauksiasi tosiasioina.
jsbasic kirjoitti:
Eikö kapasiteetin ilmoittaminen tavuina ole vähän hankalaa juuri siksi, että 64-bittisen prosessorit lukevat levyä useimmiten isommissa lohkoissa, kuin tavuina?
Tavu on yhä edelleenkin tiedon perusyksikkö, ja kovalevyltä lukemisella ei ole varsinaisesti mitään tekemistä prosessorin bittisyyden kanssa. Yleensä levyltä luetaan kerralla suurempikin määrä (kilotavuja tai peräti megatavuja) suoraan keskusmuistiin.
Myös väitteesi, että 64-bittinen prosessori olisi huonompi 8-bittisen datan käsittelyssä, on aika kummallinen: pääsääntöisesti 8-bittiset laskut sujuvat suunnilleen yhtä nopeasti kuin 64-bittiset, ja monissa tilanteissa 64-bittisillä rekistereillä voidaan itse asiassa laskea 8-bittisiä lukuja 8 rinnakkain, jolloin nopeusetu on ilmeinen.
jsbasic kirjoitti:
Bittitasosta en tiedä, mutta tavutasolla eli 8-bittisenä äänenkäsittely on tunnettu taiteenlaji.
Naurettavaa. CD-ääni (1980-luvun juttu) on 16-bittistä, ja nykyään tyypillinen harrastelijaluokan äänitin kykenee äänittämään 24-bittistä, ammattilaislaitteet epäilemättä tarkempaakin. 8-bittinen äänenkäsittely ei siis todellakaan ole nykyään hyödyllinen tai tavoiteltava asia, vaikka sitä ehkä retrohengessä harrastetaankin.
Tajuatko sitä paitsi, että nykyprosessori laskee niitä 8-bittisiäkin lukuja liki tuhat kertaa nopeammin kuin nuo 8-bittisen aikakauden prosessorit?
Metabolix kirjoitti:
nykyprosessori laskee niitä 8-bittisiäkin lukuja liki tuhat kertaa nopeammin kuin nuo 8-bittisen aikakauden prosessorit?
Itse asiassa käsittääkseni useita tuhansia kertoja nopeammin. Jos puhutaan vaikka jakolaskuista niin jopa satoja tuhansia - miljoonia kertoja nopeammin.
Grez kirjoitti:
Metabolix kirjoitti:
nykyprosessori laskee niitä 8-bittisiäkin lukuja liki tuhat kertaa nopeammin kuin nuo 8-bittisen aikakauden prosessorit?
Itse asiassa käsittääkseni useita tuhansia kertoja nopeammin. Jos puhutaan vaikka jakolaskuista niin jopa satoja tuhansia - miljoonia kertoja nopeammin.
Ainakin itse olen saanut käsityksen, että miljoonia kertoja nopeammin ja samaan aikaan monia kerralla.
Metabolix kirjoitti:
Yhä uudelleen täytyy hämmästyä, miten eri tasoilla tässä keskustellaan. Etkö viitsisi lukea vaikka Wikipediasta, miten tavallinen tietokone toimii?
Samalla tasolla keskustelu olisi hyödytöntä hymistelyä. Ja olen keskustelijoista ainoa joka on viitannut Wikipediaan.
Metabolix kirjoitti:
Olisi myös mukava, jos et esittäisi epävarmoja arvauksiasi tosiasioina.
Ei ole tarkoitus esittää tosiasioina. Olen käyttänyt verbiä 'oletan'.
Metabolix kirjoitti:
Myös väitteesi, että 64-bittinen prosessori olisi huonompi 8-bittisen datan käsittelyssä, on aika kummallinen:
Mieluummin niin että 8-bittisen datan käsittely 64 bitillä on laitteen kapasiteetin tuhlaamista, ja siten 64-bitin koneet ovat ongelmallisia.
Metabolix kirjoitti:
Pääsääntöisesti 8-bittiset laskut sujuvat suunnilleen yhtä nopeasti kuin 64-bittiset
Väärä vertailutapa. 8-bittisten lukujen käsittely pitäisi tietenkin tapahtua 8 kertaa nopeammin, jotta yhtä monta bittiä tulisi manipuloiduksi.
Metabolix kirjoitti:
CD-ääni (1980-luvun juttu) on 16-bittistä, ja nykyään tyypillinen harrastelijaluokan äänitin kykenee äänittämään 24-bittistä, ammattilaislaitteet epäilemättä tarkempaakin. 8-bittinen äänenkäsittely ei siis todellakaan ole nykyään hyödyllinen tai tavoiteltava asia...
Ei 8-bittisen käsittelyn tarvitse välttämättä olla esim. 32-bittisestä käsittelystä pois. En vastusta 32-bittisyyttä, mutta minua askarruttaa se, miksi vaikka alempibittisyys on unohtunut.
Bittimäärää voi perustella hyötyohjelmilla. Esim. graafinen käyttöliittymä on helpottanut tietokoneen käyttöä. Ihmisiä hallitaan keräämällä heistä tietoja tietokantoihin, joiden osoittamiseen tarvitaan suuria lukuja.
Mutta bittimäärää ovat lisänneet myös pelit ja viihde. Pelaajat haluavat elämyksiä, eli realistista grafiikkaa ja ääntä. Niin oli jo 8-bittisissä laitteissa, kun syntetisaattorin piti tuottaa Madonnaa ym. pop-musiikkia.
Minusta tietokoneen ainoa tavoite ei ole tarjota ja muokata esim. photorealistista kuvaa, vaan myös mallintaa todellisuutta syvällisemmin. Vai onko todellisuus 64-bittinen. En usko.
Metabolix kirjoitti:
Tajuatko sitä paitsi, että nykyprosessori laskee niitä 8-bittisiäkin lukuja liki tuhat kertaa nopeammin kuin nuo 8-bittisen aikakauden prosessorit?
Tajuan, mutta vertailukohde muinaisuuteen on hyödytön.
jsbasic kirjoitti:
Samalla tasolla keskustelu olisi hyödytöntä hymistelyä.
No enpä tiedä onko tästä keskustelusta nytkään mitään hyötyä.
jsbasic kirjoitti:
Ja olen keskustelijoista ainoa joka on viitannut Wikipediaan.
Voisin minäkin räiskiä linkkejä satunnaisiin Wikipedia-artikkeleihin, mutta olisiko siinä mitään järkeä.
http://en.wikipedia.org/wiki/High_color
jsbasic kirjoitti:
Mieluummin niin että 8-bittisen datan käsittely 64 bitillä on laitteen kapasiteetin tuhlaamista, ja siten 64-bitin koneet ovat ongelmallisia.
Ei se minusta tee koneesta mitenkään ongelmallista, että et kaiken aikaa hyödynnä sen täyttä kapasiteettia. Vai laitatko aina jonkun 100% Idle-CPU-aikaa syövän ohjelman taustalle pyörimään, ettet saa tunnontuskia koneen käytöstä?
jsbasic kirjoitti:
Väärä vertailukohde. 8-bittisten lukujen käsittely pitäisi tietenkin tapahtua 8 kertaa nopeammin, jotta yhtä monta bittiä tulisi manipuloiduksi.
No, kuten tässä jo kirjoittiinkin, niin sehän voi tapahtua 8-kertaisella nopeudella, riippuen mitä tehdään. Jos kuitenkin on tarve vain laskea kaksi 8-bittistä lukua yhteen ja prosessorilla menee siihen yksi kellojakso, niin miten tuo voisi enää toimia paremmin? Ajattelitko että prosessori alkaisi edistää 7/8 kellojaksoa (jolloin tosin koko kone kaatuisi)
Mutta yleisesti ottaen mielestäni väitteesi että jonkun pitäisi tapahtua jollakin tavalla on erikoinen. Itsekö olet päättänyt että niin pitäisi olla? En ole ainakaan Intelin nähnyt markkinoivat prosessorejaan sillä, montako bittiä sekunnissa ne manipuloivat.
Toki jos sinulle on tärkeää että lasketaan maksimiteholla vaikka 3-bittisiä lukuja, niin voit rakentaa sellaisen prosessorin itse. Koska käytännössä kellään muulla ei ole tarvetta moiselle, niin kenenkään prosessorivalmistajan ei kannata alkaa valmistamaan moisia prosessoreja.
PC-tekniikan suosio perustuu nimenomaan sille, että tehdään rautaa joka suoriutuu melko hyvin mahdollisimman monista tehtävistä, jolloin sille on mahdollisimman laaja markkina jolloin suurilla valmistusmäärillä saadaan hintaa alas. Näin 100 euron PC-prosessori todennäköisesti laskee niitä 3-bittisiä laskuja nopeammin kuin sinulle räätälöity 100 euron erityisesti 3-bittisten laskujen laskemiseen optimoitu.
Minusta olet lisäksi ristiriidassa itsesi kanssa. Aikaisemmin peräänkuulutit sitä, että tehtäisiin asioita rinnakkaisesti. 64-bittinen prosessorihan periaatteessa eroaa 8-bittisestä juuri siinä että se tekee rinnakkaisesti 8-kertaisen määrän työtä. Aina ei vaan ole sopivaa kerrannaistyötä tarjolla. Eli on järkevämpää tehdä prosessori joka pystyy laskemaan 64-bittisen toimituksen nanosekunnissa kuin prosessori joka pystyy laskemaan 8-bittisen toimituksen nanosekunnissa. Ensin mainittu prosessori suoriutuu hommasta nanosekunnissa oli bittejä sitten 1-64. Jälkimmäisellä menee vähintään 8 nanosekuntia (eli 8 kertaa kauemmin) tehtävästä jossa on vaikka 60 bittiä.
jsbasic kirjoitti:
Ei 8-bittisen käsittelyn tarvitse välttämättä olla esim. 32-bittisestä käsittelystä pois. En vastusta 32-bittisyyttä, mutta minua askarruttaa se, miksi vaikka 3-bittisyys on unohtunut.
Onko sinulla kertoa hieman lisää tästä unohtuneesta 3-bittisyydestä.
Eiköhän nykyisen bittisyyskehityksen taustalla ole yksinkertaisesti se, että 8-bittisestä on loogista siirtyä 16-bittiseen, jolloin voidaan laskea kahta 8-bittistä rinnakkain, ja tästä samalla logiikalla 32-bittiseen ja 64-bittiseen.
Lisää bittejä taas tarvitaan siksi, että harvassa tehtävässä 8-bittiset luvut riittävät. 32-bittisillä luvuillakin tuli vielä helposti overflow ihan kotikäytössä, 64-bittiset riittävät yleensä minulle, tai jos eivät riitä, mennäänkin usein niin paljon yli, ettei prosessorin kannata niitä lukuja suoraan tukea. Pitkiä lukuja laskettaessa taas 64-bittisellä prosessorilla saadaan esimerkiksi yhteenlaskussa tuplanopeus 32-bittiseen nähden juuri siksi, että bittejä tulee käsitellyksi tuplasti joka operaatiolla.
Jos 3-bittisen (tai edes 8-bittisen) datan käsittelylle olisi todellista kysyntää, sitä varten varmasti olisikin tehokkaampia prosessoreita. Valtaosa maailman laskuista käyttää kuitenkin isompia lukuja eikä ole millään tavalla sidoksissa tiettyyn bittimäärään. Vai keksitkö montakin esimerkkiä tärkeästä käytännöllisestä tehtävästä, jossa tarvittaisiin välttämättä juuri 3-bittisiä lukuja ja aivan maksimaalista laskentatehoa niille?
Mutkikas prosessori on yleensä kalliimpi kuin yksinkertainen, joten mutkikkuuden hyötyjä pitää tarkkaan punnita. Nykyäänkin valmistetaan RISC-prosessoreita, joissa on huomattavasti pienempi käskykanta kuin x86:ssa. Voi vain kuvitella, mikä sotku tulisi prosessorista, joka yrittäisi natiivisti tukea sekä 3-bittisiä että 64-bittisiä laskuja – itse veikkaan, että sillä hinnalla saisi niin tehokkaan 64-bittisen prosessorin, että se lopulta laskisi niitä 3-bittisiäkin lukuja nopeammin kuin vastaava hybridi.
Laskentatehoa tarvitaan tieteeseen vielä paljon enemmän kuin peleihin ja viihteeseen, vaikka sikäli toki olet oikeassa, että ilman viihdelaitteita kysyntä olisi paljon pienempi ja kehitys luultavasti siis hitaampaa. Nykyisen kehityksen ansiona voi minusta pitää sitä, että kotikoneiden prosessoritkin pystyvät pyörittämään aika raskaita simulaatioita ja ovat niin laadukkaita, että supertietokoneet on kätevämpää kasata niistä kuin erikoisvalmisteisista osista.
Kannattaa muuten ehkä lukea supertietokoneistakin. Niissähän noita tuhansien prosessorien komplekseja käytetään, eikä se suinkaan ole yksinkertaista.
Metabolix kirjoitti:
Vai keksitkö montakin esimerkkiä tärkeästä käytännöllisestä tehtävästä, jossa tarvittaisiin välttämättä juuri 3-bittisiä lukuja ja aivan maksimaalista laskentatehoa niille?
Eikö ihmisen arkipäättely ole aina vähäbittistä. Esim. säätilannetta on käytännöllistä ilmaista 3 bitillä.
//Boforiasteikko enum Tuuli {HEIKKO, KOHTALAINEN, NAVAKKA, KOVA, MYRSKY, KOVA_MYRSKY, ANKARA_MYRSKY, HIRMUMYRSKY}; //Pilvisyys enum Pilvisyys {MELKOSELKEAA, VERRATTAINSELKEAA, PUOLIPILVISTA, VERRATTAINPILVISTA, MELKEINPILVISTA, PILVISTA};
Säätilassa on paljon suureita, ja ne ovat vain pieni osa kaikesta mahdollisista tekijöistä, joiden avulla on tehtävä arjen päätöksiä. Saman esittäminen 64-bittisesti on turhaa jo mittausvirheen vuoksi.
Tietokone on tunnetusti tehokas laskemaan, mutta surkea arkipäivän päättelyssä. Ei ihme, koska sen arkkitehtuuri suosii suuria lukuja.
Älykkyyttä, esim. neuroverkkoa mallinnettaessa oleellista on miljardien solujen yhteisvaikutus, ei se miten tarkasti yhden synapsin yhteys lasketaan.
Myös kvanttifysiikassa voi olla tarvetta epäjatkuvalle funktiolle.
Bittisyys on siis maailmankuvallinen ongelma. Jos ajattelee maailman olevan analoginen, niin suuri bittimäärä on hyvä, mutta digitaalisessa maailmankatsannassa, jota monet argumentoivat, tarve isolle bittimäärälle ei ole erityisen relevantti.
Aiheesta on keskusteltu ennenkin. Kannattaa tutustua vaikka tämän "retromiehen" kannanottoihin Newtonin matematiikasta:
http://fi.wikipedia.org/wiki/George_Berkeley
Grez kirjoitti:
Voisin minäkin räiskiä linkkejä satunnaisiin Wikipedia-artikkeleihin, mutta olisiko siinä mitään järkeä.
http://en.wikipedia.org/wiki/High_color
Tuossapa Newtonin matematiikkaa ja maailmankuvaa puhtaimmillaan!
Grez kirjoitti:
Ajattelitko että prosessori alkaisi edistää 7/8 kellojaksoa (jolloin tosin koko kone kaatuisi)
Ei vaan ajattelin että prosessoreita olisi kahdeksan.
jsbasic kirjoitti:
Tietokone on tunnetusti tehokas laskemaan, mutta surkea arkipäivän päättelyssä. Ei ihme, koska sen arkkitehtuuri suosii suuria lukuja.
Tietokone ei tee arjen päätöksiä, vaan toimii ja antaa aina tuloksen ohjelmassa määritettyjen sääntöjen ja ehtojen mukaan.
jsbasic kirjoitti:
Älykkyyttä, esim. neuroverkkoa mallinnettaessa oleellista on miljardien solujen yhteisvaikutus, ei se miten tarkasti yhden synapsin yhteys lasketaan.
Eiköhän nuo neuroverkon inputit ja outputit yleensä kuitenkin tallenneta ohjelmassa taulukkoon, joten tuo prosessorien rekisterien bittimäärä on melko yhdentekevä. Sitäpaitsi monesti on helpompi hahmottaa ja käsitellä noita inputteja ja outputteja bipolaarina (1, -1) binaarin (1, 0) sijaan.
Miten aina päädytään näihin keskusteluihin kaikissa muissa keskusteluissa kuin niille itselleen suunnatuissa :D
jsbasic kirjoitti:
Eikö ihmisen arkipäättely ole aina vähäbittistä. Esim. säätilannetta on käytännöllistä ilmaista 3 bitillä.
Esittämäsi tasoiseen päättelyyn ei todellakaan tarvita maksimaalista laskentatehoa, ja vastaavasti jos meteorologiset mallit toteutettaisiin tuolla tarkkuudella, ne eivät kykenisi ennustamaan yhtään mitään.
jsbasic kirjoitti:
Tietokone on tunnetusti tehokas laskemaan, mutta surkea arkipäivän päättelyssä. Ei ihme, koska sen arkkitehtuuri suosii suuria lukuja.
Älykkyyttä, esim. neuroverkkoa mallinnettaessa oleellista on miljardien solujen yhteisvaikutus, ei se miten tarkasti yhden synapsin yhteys lasketaan.
Esitit taas nämä kovin absoluuttisesti. Oletko perehtynyt (edes perustasolla) hermoverkkoihin tai päättelyyn tietotekniikassa tai biologiassa?
Ajattelet siis, että hermoverkon mallintamiseen riittäisivät pienet luvut. Ja mitä sitten teet, kun ne 7000 pientä lukua pitäisi laskea yhteen – vieläpä muutaman viime hetken ajalta – jotta selviää, jatkaako signaali kulkuaan kyseisestä solusta?
Käytät harhaanjohtavasti sanaa "arkipäättely", josta muodostuu kuva jostain helpommasta kuin matemaattisessa päättelyssä. Itse asiassa tilanne on pitkälti päinvastainen: Matemaattisessa päättelyssä on rajallinen määrä sääntöjä ja suureita, jolloin konekin pystyy jossain määrin käsittelemään niitä (kuten Prolog-ohjelmoijana tiedät). Sen sijaan arkipäättely biologisena prosessina ei ole vähäbittinen vaan enemmänkin analoginen, juuri päinvastoin kuin itse sanot.
Arkipäättelyssä käsitellään epämääräisempiä asioita usein täysin epäloogisella tavalla; päättelyyn vaikuttavat ne miljardit hermosolut ja niiden synapsirakenteeseen tallentunut vuosien kokemus, jonka perusteella ihminen jo alitajuisesti sulkee pois suurimman osan mahdollisuuksista, usein myös osan realistisista vaihtoehdoista. Virhepäätelmä ei ole ihmiselle tavaton asia: ihminen voi päätyä irrallisista asioista asioista kuten "maito on hapanta" ja "ulkona ukkostaa" täysin epäloogiseen päätelmään "ukkonen hapattaa maidon". Jotta hermoverkko saataisiin tekemään samanlaisia päätelmiä ja virhepäätelmiä, tarvitaan nähdäkseni enemmän kuin 3-bittisiä tai edes 8-bittisiä lukuja.
jsbasic kirjoitti:
Bittisyys on siis maailmankuvallinen ongelma. Jos ajattelee maailman olevan analoginen, niin suuri bittimäärä on hyvä, mutta digitaalisessa maailmankatsannassa, jota monet argumentoivat, tarve isolle bittimäärälle ei ole erityisen relevantti.
Tuskin voit vakavissasi väittää, että maailmankuvaa muuttamalla päästäisiin johonkin siitä tosiseikasta, että nopeudella 126 km/h kulkeva esine etenee 0,15 sekunnissa 5,25 metriä ja että tämän laskemiseen tarvitaan enemmän kuin kolme bittiä.
Metabolix kirjoitti:
Esitit taas nämä kovin absoluuttisesti.
Metabolix kirjoitti:
Tuskin voit vakavissasi väittää, että maailmankuvaa muuttamalla päästäisiin johonkin siitä tosiseikasta, että nopeudella 126 km/h kulkeva esine etenee 0,15 sekunnissa 5,25 metriä ja että tämän laskemiseen tarvitaan enemmän kuin kolme bittiä.
Itse kutsut Newtonin luonnon mallia tosiseikaksi, vaikka se on matemaattinen yksinkertaistus. Harmi vaan tietokonemaailmassa käytettyä absoluuttista koordinaatistoa ei ole välttämättä olemassa reaalimaailmassa.
Tavallaan jos olet sitä mieltä, että Newtonin lait ovat niin todentuntuisia, että ne on oltava olemassa, niin miksen minäkin saa ajatella, että 8-bittinen kulttuuri on jollakin tavalla niin aitoa, että oma maailmamme on oltava 8-bittinen. Heh!
Newtonin lait ovat atomien käyttäytymisestä johtuvia yleensä toteutuvia malleja. Energialla sitten on tarkemmat säännöt, joita ei voi rikkoa ja joita ei vielä täysin tunneta kts. "kaiken teoria".
Jos halutaan filosofoida kuten siinä pokerilangassa, vaikka filosofiointi onkin tyhmää, koska voi vain tietää, että on, niin sanon, että maailma on yksiulotteinen. Se on lista jota rekursioidaan äärellisellä nopeudella -> aika on olemassa. Jokainen rekursio päivittää maailmaa, jonka havaitsemme. Lista on muuttuva, johtuen lukemisen aiheuttamista virheistä -> jokainen päivitys on erilainen. Olen oikeassa, koska ette voi todistaa muutakaan.
jsbasic kirjoitti:
Itse kutsut Newtonin luonnon mallia tosiseikaksi, vaikka se on matemaattinen yksinkertaistus. Harmi vaan tietokonemaailmassa käytettyä absoluuttista koordinaatistoa ei ole välttämättä olemassa reaalimaailmassa.
Nyt puutut ihan naurettavaan seikkaan. Saat minun puolestani tehdä vastaavan liikelaskun vaikka yleisen suhteellisuusteorian mukaisesti, jos se sinusta on parempi. Tuskinpa se tarvittavien bittien määrää ainakaan vähentää, päinvastoin.
jsbasic kirjoitti:
8-bittinen kulttuuri on jollakin tavalla niin aitoa, että oma maailmamme on oltava 8-bittinen.
Kaikkea saa toki uskoa, mutta jos 8-bittiset laskusi antavat toistuvasti tuloksia, jotka voidaan helposti todeta epätarkoiksi tai jopa täysin virheellisiksi, eikö se ole hyvä perustelu olettaa, että ehdottamasi 8-bittinen malli ei vastaa universumin todellisuutta?
Jos et tarkoittanut ollenkaan tätä, voisitko ystävällisesti sitten selittää, millaisia laskuja sillä pienellä bittimäärällä pitäisi tehdä, jotta niistä saataisiin todellisuutta vastaavia tuloksia, ja miten se pieni bittimäärä tekisi laskennasta tehokkaampaa kuin suuri bittimäärä?
Miksi jsbasicistä tulee minulle mieleen Pasilan (tv-sarja) Routalempi. Maneerit on toki erilaiset, mutta perustoimintamalli sama.
Metabolix kirjoitti:
millaisia laskuja sillä pienellä bittimäärällä pitäisi tehdä, jotta niistä saataisiin todellisuutta vastaavia tuloksia, ja miten se pieni bittimäärä tekisi laskennasta tehokkaampaa kuin suuri bittimäärä?
Puhut koko ajan laskuista kuin mikäkin Isaac Newton. Kuitenkin eläimet ovat tulleet "ikuisuuden" toimeen tässä universumissa, vaikka eivät ne laske edes kolmeen. Eikä ihminenkään luonnostaan laske juuri 3 bittiä enempää. Älykkäälle olennolle ei taida matematiikasta olla kuin haittaa: Tuhoaa itsensä.
3-bittisillä luvuilla voi kuitenkin laskea niin isoja laskuja kuin haluaa muodostamalla 3-bittisiä bittejä. Jos luonnossa on matemaattista säännönmukaisuutta niin se voi olla tämän kaltaista. Mutta suurin osa maailmankaikkeudesta on kaaosta; siitä ollaan jo yhtä mieltä.
jsbasic, mitä ihmettä nyt selität? Käsittääkseni tässä oli tarkoitus puhua laskentatehosta eikä pohtia, onko laskemisessa mitään järkeä alun perinkään tai mitä laskeminen oikeastaan edes on.
Nyt päädyit kuitenkin kehäpäätelmään: Aiemmin tyrmäsit 64-bittisen prosessorin sillä perusteella, että sillä ei kannata laskea 3-bittisiä lukuja. Nyt taas sanot, että kyllähän 3-bittisellä prosessorilla voisi laskea 64-bittisiä lukuja. No totta kai voi, mutta ei se ole takuulla yhtään sen tehokkaampaa kuin tuo toinen, jota haukuit huonoksi.
jsbasic kirjoitti:
3-bittisillä luvuilla voi kuitenkin laskea niin isoja laskuja kuin haluaa muodostamalla 3-bittisiä bittejä.
Kyllä tuohon tehokkaaseen ja tarkkaan laskentaan isoilla luvuilla tarvitaan vähintään 4-bittiä per desimaali.
No siis toki 3-bittisillä pystyy laskemaan ihan siinä missä 64-bittisilläkin. Mutta kuten jo aikaisemmin sanoin, niin olisi älyvapaata tehdä kone joka laskee 3-bittisiä yhtä nopeasti kuin muut koneet 64-bittisiä ja 64-bittisiä 22 - 4000 kertaa hitaammin kuin muut koneet.
Eli sanon vielä lyhyemmin:
Kone joka pystyy laskemaan yhtä hyvin 64- ja 3-bittisiä on hyödyllisempi kuin kone joka pystyy laskemaan hyvin vain 3-bittisiä.
Se että jossain laskutoimituksissa mahdollisesti ei ole tarvetta enemmälle kuin 3 bitille ei millään tavalla tarkoita sitä, etteikö 64-bittinen prosessori soveltuisi ko. laskentaan erittäin hyvin.
Toivottavasti tämä ei nyt vaikuta siltä, että olisin jotenkin ilkeä jsbasicille. Alkaa vaan turhauttaa kun minä sentään luen mitä hän kirjoittaa ja vastaan niihin. Jsbasic sen sijaan tuntuu jättävän huomiota suuren osan siitä mitä muut kirjoittavat ja selittävän sitä samaa vanhaa (päätellen siitä että tässäkin viestissä toistin mitä olen jo aiemmin kirjoittanut)
Grez kirjoitti:
Se että jossain laskutoimituksissa mahdollisesti ei ole tarvetta enemmälle kuin 3 bitille ei millään tavalla tarkoita sitä, etteikö 64-bittinen prosessori soveltuisi ko. laskentaan erittäin hyvin.
Tämä on juuri se josta tässä kiistellään.
Minä olen sitä mieltä, että vaikka 4-bitin prosessori on halvempi rakentaa. Tietysti edellyttäen, että niitä tehtäisiin suurissa sarjoissa.
Edullisuutensa vuoksi se soveltuisi 4-bittisten lukujen laskentaan paremmin kuin 64 bittinen.
Useista 4-bitin prossuista voisi koota 64-bittisen rinnalle laitteistokiihdytyksen 4-bitin laskutoimituksia varten.
jalski kirjoitti:
Kyllä tuohon tehokkaaseen ja tarkkaan laskentaan isoilla luvuilla tarvitaan vähintään 4-bittiä per desimaali.
Hehee...
jsbasic kirjoitti:
Minä olen sitä mieltä, että vaikka 4-bitin prosessori on halvempi rakentaa. Tietysti edellyttäen, että niitä tehtäisiin suurissa sarjoissa.
Kuten jo aikaisemmin vihjaisin, niin koska tällaiselle (vähän bittejä, paljon tehoja) ei ole juurikaan kysyntää, niin suuret sarjat jäävät haaveeksi.
jsbasic kirjoitti:
Useista 4-bitin prossuista voisi koota 64-bittisen rinnalle laitteistokiihdytyksen 4-bitin laskutoimituksia varten.
Mitäs kustannushyötyä tästä sitten olisi, jos kuitenkin joutuisi maksamaan myös sen 64-bittisen prosessorin. Sitä paitsi eikös tämä ole ristiriidassa äsken kirjoittamasi kanssa, kun sanoit että isommatkin laskutoimitukset saisi kätevästi vähäbittisellä prossulla tehtyä?
Mielestäni olennaisin kysymys on, että mihin konkreettiseen asiaan näitä 4-bittisiä prossuja kannattaisi käyttää? Varmasti jos kehittelet merkittävän laskenta-alueen jossa on merkittävää etua 4-bittisistä prosessoreista, niin niitä aletaan jossain vaiheessa valmistaa. Olisi aika absurdi ajatus valmistaa vaikka miljardi 4-bittistä prosessoria siinä toivossa että joku joskus keksii niille jotain käyttöä.
Voisin jopa väittää, että jos pienibittisille prosessoreille on merkittävä käyttöalue, niin niitä jo valmistetaan.
Ja siis, kyllähän nykyään valmistetaan esim. 8-bittisiä prosessoreita. Niitä saa isoja eriä muutamalla kymmenellä sentillä. Itse asiassa 27e + alv kun lyö tiskiin niin saa 100 kpl. Niiden markkina-alue on erittäin vähäistä laskentatehoa vaativat sulautetut sovellukset. Jostain kumman syystä sulautettujenkin segmentissä tehon kasvaessa kasvaa myös bittisyys. Tästä voisi tehdä hypoteesin, että tehoa saa kasvatettua parhaiten kasvattamalla kellotaajuuden lisäksi myös bittien määrää.
Jokotai kirjoitti:
Newtonin lait ovat atomien käyttäytymisestä johtuvia yleensä toteutuvia malleja. Energialla sitten on tarkemmat säännöt, joita ei voi rikkoa ja joita ei vielä täysin tunneta kts. "kaiken teoria".
Jos halutaan filosofoida kuten siinä pokerilangassa, vaikka filosofiointi onkin tyhmää, koska voi vain tietää, että on, niin sanon, että maailma on yksiulotteinen. Se on lista jota rekursioidaan äärellisellä nopeudella -> aika on olemassa. Jokainen rekursio päivittää maailmaa, jonka havaitsemme. Lista on muuttuva, johtuen lukemisen aiheuttamista virheistä -> jokainen päivitys on erilainen. Olen oikeassa, koska ette voi todistaa muutakaan.
mitä
Jos tää mitenkään liittyy luokkaan joka perii kokonsa, niin kasibittisten kontrollerien/prosessorien etuhan on just se että ne on 32-bittisiä halvempia valmistaa. Niissä on toki vähemmän laskentatehoa, mut niitä käytetäänkin just semmosessa mikä ei vaadi laskentatehoa, jolloin enempi teho ois turhaa.
Nya.
Lumpio- kirjoitti:
Jokotai kirjoitti:
Newtonin lait ovat atomien käyttäytymisestä johtuvia yleensä toteutuvia malleja. Energialla sitten on tarkemmat säännöt, joita ei voi rikkoa ja joita ei vielä täysin tunneta kts. "kaiken teoria".
Jos halutaan filosofoida kuten siinä pokerilangassa, vaikka filosofiointi onkin tyhmää, koska voi vain tietää, että on, niin sanon, että maailma on yksiulotteinen. Se on lista jota rekursioidaan äärellisellä nopeudella -> aika on olemassa. Jokainen rekursio päivittää maailmaa, jonka havaitsemme. Lista on muuttuva, johtuen lukemisen aiheuttamista virheistä -> jokainen päivitys on erilainen. Olen oikeassa, koska ette voi todistaa muutakaan.mitä
Se oli huumorillinen vastaus jsbasicin 8b teoriaan :|
Grez kirjoitti:
Windows-koneen prosessorina sellainen olisi melkoinen poikkeus.
Määrittelykysymys. PC:n prosessori toimii ulkoisesti Neumannin mukaan, mutta sisäisesti siellä on Harvardin mallin mukaan erilliset muistiväylät, mistä on hyötyä ainakin pipelinen täytössä ja välimuistin käsittelyssä.
jsbasic kirjoitti:
Metabolix kirjoitti:
Etkö viitsisi lukea vaikka Wikipediasta, miten tavallinen tietokone toimii?
olen keskustelijoista ainoa joka on viitannut Wikipediaan.
Olet linkittänyt väitteittesi perään, joko asiaan täysin kuulumattomia linkkejä tai sellaisia jotka suorastaan kumoavat väitteesi. Tuollaisten irrallisten linkkien pastettaminen antaa olettaa, että et ole viitsinyt itse lukea niitä.
jsbasic kirjoitti:
Tietokone on tunnetusti tehokas laskemaan, mutta surkea arkipäivän päättelyssä.
Tietokone on siinä juuri niin hyvä, kuin siinä pyörivä ohjelma ja tietokoneen kyky pyörittää kyseistä ohjelmaa. Monesti se on siinä paljonkin ihmistä parempi.
jsbasic kirjoitti:
Eikö ihmisen arkipäättely ole aina vähäbittistä. Esim. säätilannetta on käytännöllistä ilmaista 3 bitillä.
Säätilanne ei ole päättelyä. Jos ulkona sataa lunta, niin ulkona sataa lunta. Ei minun päättelyni siihen mitään vaikuta, vaikka kuinka haluaisinkin.
jsbasic kirjoitti:
Grez kirjoitti:
Ajattelitko että prosessori alkaisi edistää 7/8 kellojaksoa (jolloin tosin koko kone kaatuisi)
Ei vaan ajattelin että prosessoreita olisi kahdeksan.
Oletetaan että nämä laskutoimitukset ovat täysin toisistaan riippumattomia ja pystytään laskemaan rinnakkain. Kysymys kuuluu: miten tästä on hyötyä yhteen 64-bittiseen nähden. Toinen kysymys: onko kaikki laskenta mielestäsi luonteeltaan sellaista, että niitä pystytään ajamaan aina 8 rinnakkain toisistaan riippumatta? Jos nyt paukautat 9 naista paksuksi, niin saatko yhden lapsen 1 kk kuluttua?
jsbasic kirjoitti:
miksen minäkin saa ajatella, että 8-bittinen kulttuuri on jollakin tavalla niin aitoa, että oma maailmamme on oltava 8-bittinen.
Koska absoluuttinen totuus on että maailma on littana ja nelikulmainen. Ei tähän tarvita kuin kaksi bittiä. Kolmas bitti tarvitaan kertomaan onko yö vai päivä.
jsbasic kirjoitti:
Kuitenkin eläimet ovat tulleet "ikuisuuden" toimeen tässä universumissa, vaikka eivät ne laske edes kolmeen. Eikä ihminenkään luonnostaan laske juuri 3 bittiä enempää. Älykkäälle olennolle ei taida matematiikasta olla kuin haittaa: Tuhoaa itsensä.
Ja minä hölmö kun luulin, että useat eläimet ovat kuolleet sukupuuttoon ja ihminen vahvistanut asemaansa. Kaikkea sitä oppii... Terve ja kiitos kaloista.
Mitä mieltä ootte Justin Bieberistä?
jsbasic,kannattaa tosiaankin lainata C ja C++ kielen oppaita tai mieluummin ostaa ne omaksi ja koodata kaikenlaista 2-3v ennekuin alkaa mietiskelemään ihmeellisiä tietorakenteita ja huolestuu suorityskyvystä tai muistin kulutuksesta.
Kerro mitä asiaa varten tarvitset sen taulukkosi olioihin?
Luultavasti olet tekemässä jotain yliviisasta. Veikkaisin että tavallisilla taulukoillakin pötkisit pitkälle. Toki linkattu lista on hyvä osata tehdä jos tarvitaan dynaamista muistinkäsittelyä.
Nykykoneissa riittää teho ja muisti vaikka mihin....
Ajatteleppa vaikka käynnissä olevaa windowsia,mp3-soitinta,tekstieditoria,internetyhteyttä,web-camia,polttavaa dvd-ram asemaa....
Kaikki pyörii samassa RAMmissa(voi olla että ne on jaettu lohkoihin?).
Itse olen koodannut kohta 26 vuotta aloittaen commodore64:än basicilla ja sen konekielellä.
Jonninjoutavaa jaarittelua koko keskustelun pätkä. Kysyt jotain alussa järkevästi ja sitten alat väittämään vastaan kaikille.
Itse en tiedä dynaamisesta muistinvarauksesta tänäkään päivänä paljoa mitään. Toki osaan perusjutut new:llä ja deletellä ja delete []:llä.
Koodaan lähes aina C:llä käyttäen C++:sta vain datankätkentää jotta ei synny bugeja joita muutaman kymmenen tuhannen rivin koodista on lähes mahdoton löytää.
Toki käytän kehittyneempää // kommentointia sekä joitain yksityiskohtia joita en nyt lähde kaivelemaan. C ja C++ ovat hyviä kieliä. Javan haluaisin oppia mutta siinäkin on se pirun siivooja taustalla pyörimässä etsien vapautettavaa muistia.
En tiiä miten nyt intoudun tähän ketjuun kirjoittamaan. Ehkä mua ottaa pannuun että putkan parhaat koodarit inttää sinun kanssasi eivätkä voi neuvoa minua eteenpäin omassa pikkuprojektissani.....:)
Kilotavu=1024 tavua. Tavu=8 bittiä. Sana=16 bittiä. Pitkä sana=32 bittiä.Ja kai joku ylipitkä sana=64 bittiä. 4 bittiä=nibble. 1 bitti on joko true tai false(bool). Kokeileppa tehdä vaikka matopeli jossa käytät linkattavaa listaa aina kun mato kasvaa.....Tai tee matopeli ilman listaa. Madon maksimipituus on vakio joten selvinnet taulukoilla. Kumma kun et sotkenut keskusteluun C++:an friendejä. Voishan tässä jaaritella mutta pointti on:MINKÄLAISTA OHJELMAA OLET TEKEMÄSSÄ?
Metabolix kirjoitti:
jsbasic kirjoitti:
Itse kutsut Newtonin luonnon mallia tosiseikaksi, vaikka se on matemaattinen yksinkertaistus. Harmi vaan tietokonemaailmassa käytettyä absoluuttista koordinaatistoa ei ole välttämättä olemassa reaalimaailmassa.
Nyt puutut ihan naurettavaan seikkaan. Saat minun puolestani tehdä vastaavan liikelaskun vaikka yleisen suhteellisuusteorian mukaisesti, jos se sinusta on parempi. Tuskinpa se tarvittavien bittien määrää ainakaan vähentää, päinvastoin.
En suoranaisesti väitä etteikö suuria lukuja tarvittaisi. Mutta kyllähän kvanttimekaniikassa puhutaan myös bittitason operaatioista. Katso esim. tästä artikkelista kohta "Formaali esimerkki".
http://fi.wikipedia.org/wiki/Lomittuminen
"Oletetaan, myös yksinkertaisuuden vuoksi, että hiukkasilla on tasan kaksi vapausastetta"
Tuossa on naurettavaa puuttua siihen pikkuseikkaan, että alkaa laskea kineettistä energiaa mahdollisimman analogisesti. Yksi bitti riittää tuossa esimerkissä hyvin.
Toinen lähtökohta on yleinen elämän simuloiminen. Varmaan kaikki tuntevat life-pelin, jossa solut ovat bittejä. Koordinaatit ovat toki vähän isompia lukuja, mutta mitään suuria laskuja ei tarvita. Silti siinä syntyy monimutkaisia kuvioita. Siinä voi nähdä monimutkaisia matemaattisia malleja, vaikka sellaisia ei oikeastaan ole olemassa. On enimmäkseen vain bittejä.
http://fi.wikipedia.org/wiki/Life-peli
Grez kirjoitti:
Voisin jopa väittää, että jos pienibittisille prosessoreille on merkittävä käyttöalue, niin niitä jo valmistetaan.
Ehkä suuri bittimäärä kuulostaa prosessorimainoksessa hyvältä.
DumTom kirjoitti:
Javan haluaisin oppia mutta siinäkin on se pirun siivooja taustalla pyörimässä etsien vapautettavaa muistia.
Kannattaa oppia. Itse olen hyötynyt siitä paljon, enkä halua pilata muiden mielenkiintoa siihen, vaikka perään myös vähäbittisiä järjestelmiä.
Torgo kirjoitti:
Toinen kysymys: onko kaikki laskenta mielestäsi luonteeltaan sellaista, että niitä pystytään ajamaan aina 8 rinnakkain toisistaan riippumatta?
Kaikesta en tiedä, mutta soluautomaatit ovat. Esimerkiksi tuo Life-peli.
jsbasic kirjoitti:
En suoranaisesti väitä etteikö suuria lukuja tarvittaisi. Mutta kyllähän kvanttimekaniikassa puhutaan myös biteistä. Katso esim. tästä artikkelista kohta "Formaali esimerkki".
http://fi.wikipedia.org/wiki/Lomittuminen
"Oletetaan, myös yksinkertaisuuden vuoksi, että hiukkasilla on tasan kaksi vapausastetta"
Miten tämäkään taas liittyy yhtään mihinkään mistä tässä on keskusteltu? Se että jollain sivulla lukee "bitti" ei tarkoita että sillä olisi jonkinlainen asiayhteys.
jsbasic kirjoitti:
Tuossa on naurettavaa puuttua siihen pikkuseikkaan, että alkaa laskea kineettistä energiaa mahdollisimman analogisesti.
Miten se on naurettava pikkuseikka, että bitin tila täytyy ensin laskea, että se osattaisiin asettaa oikein?
jsbasic kirjoitti:
Varmaan kaikki tuntevat life-pelin, jossa solut ovat bittejä.
Siitä vain sitten suunnittelemaan varta vasten life-peliin suunniteltua prosessorijärjestelmää, missä jokainen prosessori vastaa yhtä koordinaatiston "bittiä". FPGA tästä suoriutuisi näppärästi, mutta siinäkin koordinaatiston koko olisi rajoittunut porttien määrään.
jsbasic kirjoitti:
Ehkä suuri bittimäärä kuulostaa prosessorimainoksessa hyvältä.
Prosessorivalmistajien arvion mukaan 55% tänä päivänä myydyistä prosessoreista on 8-bittisiä mikrokontrollereita. Pointti mitä aiemmin yritin tuossa tuoda esille on, että jos maailmasi mallintamiseen riittää 8 bittiä, niin voit aivan hyvin niin tehdä. Niin tekevät monet muutkin. Yleensä ottaen kannattaa käyttää sellaista tekniikkaa, jolla päästään helpoimmalla ja halvimmalla riittävän lähelle haluttua lopputulosta. Kotikoneissa sellainen ei riitä. Niiden on suoriuduttava mahdollisimman laajasta joukosta ongelmia ja vieläpä siten että niillä olisi mahdollisimman laaja käyttäjäjoukko.
jsbasic kirjoitti:
Kaikesta en tiedä, mutta soluautomaatit ovat. Esimerkiksi tuo Life-peli.
Ei pidä paikkaansa edes Life-pelin tapauksessa. Solu tarvitsee tiedot naapureiltaan, jotta se pystyisi tekemään päätöksen omasta tilastaan.
Torgo kirjoitti:
Siitä vain sitten suunnittelemaan varta vasten life-peliin suunniteltua prosessorijärjestelmää, missä jokainen prosessori vastaa yhtä koordinaatiston "bittiä".
Torgo kirjoitti:
Ei pidä paikkaansa edes Life-pelin tapauksessa. Solu tarvitsee tiedot naapureiltaan, jotta se pystyisi tekemään päätöksen omasta tilastaan.
Pitääkö kaikki ymmärtää väärin? Ei jokaisen prosessorin tarvitse vastata yhtä solua, vaan isoa solujoukkoa.
jsbasic kirjoitti:
Pitääkö kaikki ymmärtää väärin? Ei jokaisen prosessorin tarvitse vastata yhtä solua, vaan isoa solujoukkoa.
Mitenkäs tämä sitten pitäisi ymmärtää, kun sinulle ei kelpaa esim. 64-bittinen prosessori joka potentiaalisesti pystyisi laskemaan 64 solua rinnakkain.
Mutta mitä itse asiaan tulee, niin mitä vikaa tossa Torgon ehdotuksessa on, että tekisi elämän pelin FPGA-piirillä. Silloin voisi ajatella että jokaisella solulla on käytössään oma prosessori ja piirille mahtuvan kokoista solumatriisia pystyisi ajamaan aika messevillä kelloilla.
(En sit tiedä kenelle olisi mitään hyötyä siitä että olisi elämän peli joka pyörii miljardi askelta sekunnissa)
Grez kirjoitti:
Mitenkäs tämä sitten pitäisi ymmärtää, kun sinulle ei kelpaa esim. 64-bittinen prosessori joka potentiaalisesti pystyisi laskemaan 64 solua rinnakkain.
Oletankin ettei se pysty.
Miksi ihmeessä moista olettelet?
No joo, ottaen huomioon, että yhden solun laskemiseen tarvitsee 4 bittiä niin realistisempaa voisi olla ajatella 14-16 solun rinnakkaista laskemista. Mutta siis kuitenkin suoraan 14-16 kertaa enemmän kuin 4-bittisellä prosessorilla.
OK. Täytyypä alkaa sitten laskeskelemaan tuota mahdollisuutta.
Tämä viritys johon tarvitsen koonsa perivää luokkaa onkin aika lähellä soluautomaattia. Siitä syystä en ole nähnyt tarvetta osoittimille.
jsbasic kirjoitti:
Grez kirjoitti:
Mitenkäs tämä sitten pitäisi ymmärtää, kun sinulle ei kelpaa esim. 64-bittinen prosessori joka potentiaalisesti pystyisi laskemaan 64 solua rinnakkain.
Oletankin ettei se pysty.
uint64_t a, b, c, d; a = rivi[i-1]; b = rivi[i+1]; c = rivi << 1; d = rivi >> 1; rivi = (~a&b&c) | (~b&c&d) | (b&~c&d) | (b&c&~d);
Tuohon tarvitaan lisäksi tarkistukset koordinaatiston reunoille. Varsinainen laskutoimitus toimii yksinkertaistetulla säännöllä. Periaate tullee ainakin selväksi ja lausekkeen voi muokata sopimaan omiin sääntöihin. Tuossa siis lasketaan rinnakkain 64 solua koordinaatistolle, jonka rivinpituus on 64. Ei ole vaikea soveltaa pidemmillekään riveille.
Putosin kärryiltä. Selittäisikö joku mistä täällä puhutaan :D
Torgo, onko toi nyt elämän peli vai joku muu soluautomaatti? Katsoin vain nopeasti mutta äkkiseltään näyttäisi että tuo huomioisi vain pääilmansuunnissa olevat naapurit (4 solua), kun elämän pelissä pitäisi huomioida 9 solua (myös väli-ilmansuunnat ja solu itse)
Torgon koodista oletettavasti puuttuu myös [i] ennen shiftejä.
Kuten tekstissä mainitsin, niin se on hieman yksinkertaistettu versio elämänpelistä, eli sopii kategoriaan "joku muu soluautomaatti". Näin äkkiä ajateltuna tuo herättää henkiin kolmella naapurilla (neljästä) ja tappaa muutoin. Indeksi tosiaan unohtui shifteistä ja itse laskutoimituksessakin rivi pitäisi laskea eri muuttujaan. Tarkoitus ei ollut antaa toimivaa elämänpelikoodia, vaan osoittaa, jos sekä lähtöarvot että lopputulos voidaan ilmaista yhdellä bitillä, niin todennäköisesti ne voidaan laskea 64 rinnakkain.
Lisätään nyt vielä sen verran, että jos aidosti tarvitsee tuhansia rinnakkaisia threadeja omaan kotikoneella pyörivään ohjelmaan, niin kannattaa tutustua CUDAan.
Torgo kirjoitti:
uint64_t a, b, c, d; a = rivi[i-1]; b = rivi[i+1]; c = rivi << 1; d = rivi >> 1; rivi = (~a&b&c) | (~b&c&d) | (b&~c&d) | (b&c&~d);
Onhan tuokin jo saavutus. Lifen säännöt ovat kuitenkin sen verran monimutkaisemmat, ettei niitä tällä tekniikalla kovin helposti sellaisenaan toteuta. Tuohon voi tarvita lisää uint64_t-lukuja, vaikka lookup-taulukoksi. Itse suunnittelin toteuttamista kokonaan lookup-taulukolla, johon suuri alue olisi laskettu jo valmiiksi, mutta se veisi ekspotenttiaalisesti muistia. En ole koskaan käyttänyt bitwise-operaatioita.
Tietenkin sääntöjä voi muuttaa jos elämän ylläpito ei siitä kärsi. Lifen säännöt on kai luotu sen ajan (1970) prosessorille.
Tässä joku on yrittänyt samaa:
http://bitlife.sourceforge.net/
Olisihan tuo hieno näytönsäästäjä.
Torgo kirjoitti:
jos sekä lähtöarvot että lopputulos voidaan ilmaista yhdellä bitillä, niin todennäköisesti ne voidaan laskea 64 rinnakkain.
Eiköhän useammankin bitin lukuja voisi laskea kun vain jakaa eri merkitsevät bitit omiin uint64_t -lukuihin. Mutta ainakaan 8-bitin luvuissa ei saavuteta enää yleisesti merkittävää nopeusetua char:n verrattuna. Joissain erikoisissa tehtävissä kuitenkin.
Ja eihän se yksi prosessori ole aina yksinkertaisin ohjelmoitava? Tässä Metabolixille ja Grezille näyttöä siitä, että laskenta on mahdollista myös rinnakkain, ilman että suoritettaisiin kellojakso 1/64 osissa. HEH!!
jsbasic kirjoitti:
Tässä Metabolixille ja Grezille näyttöä
Missä? Jos tarkoitat Torgon bittioperaatioita, niin eihän meistä kumpikaan ole väittänyt, ettei niin voisi tehdä, päinvastoin.
jsbasic kirjoitti:
suoritettaisiin kellojakso 1/64 osissa
... mitä tehtäisiin? Mistä ihmeestä nyt puhut?
Taidan joka tapauksessa vetäytyä keskustelusta. On aika absurdia väitellä rinnakkaislaskujen toimivuudesta ja kannattavuudesta sellaisen henkilön kanssa, joka ei tunne kunnolla edes bittioperaatioita, jotka sentään ovat ohjelmallisesti toteutettavan rinnakkaislaskennan kulmakivi. Nykyprosessoreilla rinnakkaislaskentaan on sitä paitsi aivan valmiita käskykantoja, ja suosittelenkin sinulle jatkolukemisiksi Wikipedian artikkeleita MMX- ja SSE-käskykannoista ja niiden seuraajista.
jsbasic kirjoitti:
Ja eihän se yksi prosessori ole aina yksinkertaisin ohjelmoitava? Tässä Metabolixille ja Grezille näyttöä siitä, että laskenta on mahdollista myös rinnakkain, ilman että suoritettaisiin kellojakso 1/64 osissa. HEH!!
Siis sinähän nimenomaan halusit laskea vain yhden bitin, et 64 bittiä rinnakkain ja halusit sen tapahtuvan nopeammin kuin 64 bitin laskeminen. Ja minä puolestani olen koko ajan sanonut, että 64-bittisellä prosessorilla voi sopivissa tilanteissa laskea 64-bittiä rinnakkain. Joka on tietysti myös itsestään selvää. Eli HEH itsellesi.
Taitaa olla minunkin aika lopetella tämä keskustelu. On erittäin turhauttavaa yrittää keskustella henkilön kanssa joka ei ymmärrä lukemaansa tai, mikä vielä pahempaa, ymmärtää kyllä mutta vääntelee sen tarkoittamaan jotain muuta ihan vaan että saa kinastella.
jsbasic kirjoitti:
Lifen säännöt ovat kuitenkin sen verran monimutkaisemmat, ettei niitä tällä tekniikalla kovin helposti sellaisenaan toteuta.
Toteutus ei ole vaikea. Ei tarvitse kuin syöttää ehdot totuustauluun ja sieventää totuustaulusta automaatilla lauseke. Itse lausekkeesta vaan tulee niin monimutkainen ettei hommassa ole mitään järkeä. Se tukee Metabolixin toteamusta siitä, että yksinkertaiseenkin kyllä/ei päätökseen tarvitaan usein monimutkaista logiikkaa.
jsbasic kirjoitti:
Mutta ainakaan 8-bitin luvuissa ei saavuteta enää yleisesti merkittävää nopeusetua char:n verrattuna.
Niin... ainoastaan vaatimaton 8-kertainen. Tosin kuten Metabolix sinua opasti, niin todellisuudessa ero on paljon merkittävämpi. Nykyprosessoreilla (siis ihan PC:n prosessoreilla, eikä ainoastaan DSP:llä) kun voidaan yhdellä ainoalla operaatiolla ydintä kohden suorittaa samanaikaisesti vaikkapa 16 kerto- JA yhteenlaskua. Siis 4-ytimisellä prossulla parhaimmillaan 128 8-bittistä operaatiota yhdellä kertaa. Ja onnistuu ihan tavallisella silmukalla c-kielessä.
Jos vaadit PC-ohjelmalta tätäkin parempaa rinnakkaisuutta, niin kannattaa ihan tosissaan tutustua siihen jo mainittuun CUDAan tai vaikka OpenCL:ään.
jsbasic kirjoitti:
Joissain erikoisissa tehtävissä kuitenkin.
Täsmälleen niissä samoissa, mihin olet rakentamassa 8-bittisten prossujen matriisia.
jsbasic kirjoitti:
Tässä Metabolixille ja Grezille näyttöä siitä, että laskenta on mahdollista myös rinnakkain, ilman että suoritettaisiin kellojakso 1/64 osissa.
Näyttö oli sinua varten. Sinä "oletit" että se ei ole mahdollista Metabolixin ja Grezin sinulle muuta sanoessa. Tarkoitus oli näyttää ihan perusesimerkki siitä mitä sinulle on yritetty sanoa ja mitä olet perusteetta "olettanut" mahdottomaksi. Tulee mieleen kauppaneuvos Paukku ja "No niinhän mä just sanoin.", kun on ensin kerennyt väittämään päinvastaista. :D
Torgo kirjoitti:
Toteutus ei ole vaikea. Ei tarvitse kuin syöttää ehdot totuustauluun ja sieventää totuustaulusta automaatilla lauseke. Itse lausekkeesta vaan tulee niin monimutkainen ettei hommassa ole mitään järkeä. Se tukee Metabolixin toteamusta siitä, että yksinkertaiseenkin kyllä/ei päätökseen tarvitaan usein monimutkaista logiikkaa.
Mitä ihmettä tuolla tarkoitat??? Jos life-peliä ei ole mahdollista laskea tehokkaasti bittitason operaatioilla, niin sitä ei vaan pysty. Selittele ihan mitä lystäät!
Siispä ainoastaan useat vähäbittiset prosessorit sopivat turing-täydelliseen bitti- ja tavulaskentaan, kuten oletan.
Jos on pakko mainostaa tässä CUDAaa tai prosessorin multimediatukea, niin eikö voi perustella miten se ratkaisee ongelman? Näistä mikään kun ei korvaa useaa itsenäistä prosessoria.
Jos ei ole itse ajatellut asiaa, eikä pysty linkittämään esim. rinnakkaislaskennan teoriaa, niin miksi inttää vastaan?
jsbasic kirjoitti:
Jos ei ole itse ajatellut asiaa, eikä pysty linkittämään esim. rinnakkaislaskennan teoriaa, niin miksi inttää vastaan?
Tätä olen yrittänyt jo pari kertaa kysyä sinulta. Kun nyt itsekin huomasit asian, voisitko myös vastata kysymykseen?
jsbasic kirjoitti:
Jos on pakko mainostaa tässä CUDAaa tai prosessorin multimediatukea, niin eikö voi perustella miten se ratkaisee ongelman?
Etpä ole itsekään vaivautunut kantaasi perustelemaan, joten miksi muidenkaan täytyisi? Asiassa on lisäksi sekin ero, että meidän mainitsemistamme asioista voi lukea Wikipediasta, kun taas sinun satuilusi tuntuvat olevan omasta päästäsi lähtöisin.
Eli jos viitsisit edes pari riviä lukea Wikipediasta, tietäisit tuonkin: SSE2-käskykanta tukee 128-bittisessä rekisterissä muun muassa 8-bittisten lukujen laskemista 16 lukua rinnakkain. CUDA puolestaan päästää koodarin ajamaan laskujaan NVidian näytönohjaimilla, joista uusimmissa on käsittääkseni 512 rinnakkaista laskentayksikköä.
jsbasic kirjoitti:
Siispä ainoastaan useat vähäbittiset prosessorit sopivat turing-täydelliseen bitti- ja tavulaskentaan, kuten oletan.
Eikö tuo väite ole jo aika monta kertaa kumottu? :D Kannattaa lukea tämä keskustelu aiheesta, siinä käy ilmi (alun koodisäätöjen jälkeen) koko joukko argumentteja, joihin sinun kannattaisi perehtyä.
jsbasic kirjoitti:
Jos life-peliä ei ole mahdollista laskea tehokkaasti bittitason operaatioilla, niin sitä ei vaan pysty.
Ja jos taas pystyy, niin sitten pystyy. Sormet suppuun nyt, kun et ole edes kokeillut ja jopa myönsit, ettet ole koskaan käyttänyt bittioperaatioita.
Saanen huomauttaa, että elämäpelin laskeminen pelkillä bittioperaatioilla (and, or, xor, not ja shift) olisi harvinaisen typerää, koska pelissä pitää laskea ympäröivien solujen lukumäärä, jolloin yhteenlasku esiintyy huomattavasti paremmin edukseen kuin vastaava bittikikkailu (joka toki myös on teoriassa mahdollinen ja vaatisi tässä tapauksessa noin kuusi operaatiota yhden yhteenlaskun sijaan).
Kun nyt noin kovasti intät, niin mietipä hetki seuraavaa koodia. Jotta varsinainen tulos ei hukkuisi pitkän koodin alle, laitan sen tähän ensiksi:
Life1: 0.438 miljoonaa kierrosta sekunnissa Life2: 14.286 miljoonaa kierrosta sekunnissa
Tuloksista näkyy siis, että varsin niukasti optimoitu "rinnakkaislaskenta" parilla bittikikkailulla pyörittää peliä 35-kertaisella nopeudella yhtä nihkeästi toteutettuun "perinteiseen" versioon nähden. Pidätkö silti kiinni väitteestäsi, että tämän toteuttaminen oli mahdotonta?
#include <stdio.h> #include <stdint.h> #include <time.h> // Tilanteen tulostus ASCIIna. template <class Life> void print(const Life& l) { for (int y = 0; y < 16; ++y) { for (int x = 0; x < 16; ++x) { putchar(l.get(x, y) ? '#' : '.'); } putchar('\n'); } } // Testaus. Luodaan alkutilanne, ajetaan n kierrosta, palautetaan tulos. template <class Life> double test(int n) { Life l; l.set(2, 4, 1); l.set(2, 5, 1); l.set(2, 6, 1); l.set(4, 2, 1); l.set(5, 2, 1); l.set(6, 2, 1); l.set(7, 4, 1); l.set(7, 5, 1); l.set(7, 6, 1); l.set(4, 7, 1); l.set(5, 7, 1); l.set(6, 7, 1); l.set(16 - 2, 4, 1); l.set(16 - 2, 5, 1); l.set(16 - 2, 6, 1); l.set(16 - 4, 2, 1); l.set(16 - 5, 2, 1); l.set(16 - 6, 2, 1); l.set(16 - 7, 4, 1); l.set(16 - 7, 5, 1); l.set(16 - 7, 6, 1); l.set(16 - 4, 7, 1); l.set(16 - 5, 7, 1); l.set(16 - 6, 7, 1); l.set(2, 16 - 4, 1); l.set(2, 16 - 5, 1); l.set(2, 16 - 6, 1); l.set(4, 16 - 2, 1); l.set(5, 16 - 2, 1); l.set(6, 16 - 2, 1); l.set(7, 16 - 4, 1); l.set(7, 16 - 5, 1); l.set(7, 16 - 6, 1); l.set(4, 16 - 7, 1); l.set(5, 16 - 7, 1); l.set(6, 16 - 7, 1); l.set(16 - 2, 16 - 4, 1); l.set(16 - 2, 16 - 5, 1); l.set(16 - 2, 16 - 6, 1); l.set(16 - 4, 16 - 2, 1); l.set(16 - 5, 16 - 2, 1); l.set(16 - 6, 16 - 2, 1); l.set(16 - 7, 16 - 4, 1); l.set(16 - 7, 16 - 5, 1); l.set(16 - 7, 16 - 6, 1); l.set(16 - 4, 16 - 7, 1); l.set(16 - 5, 16 - 7, 1); l.set(16 - 6, 16 - 7, 1); clock_t c0 = clock(); for (int i = 0; i < n; ++i) { l.step(); } clock_t c1 = clock(); print(l); return n * double(CLOCKS_PER_SEC) / (c1 - c0); } // Perinteinen toteutus: data taulukossa, laskenta silmukassa. struct Life1 { bool data[18][18]; // 1 + 16 + 1 = 18, ei tarvitse tarkistella indeksejä. Life1(): data() { } void set(int x, int y, bool val) { data[x+1][y+1] = val; } bool get(int x, int y) const { return data[x+1][y+1]; } void step() { Life1 old(*this); for (int y = 0; y < 16; ++y) { for (int x = 0; x < 16; ++x) { int n = 0; n += old.get(x - 1, y + 0); n += old.get(x - 1, y + 1); n += old.get(x + 0, y + 1); n += old.get(x + 1, y + 1); n += old.get(x + 1, y + 0); n += old.get(x + 1, y - 1); n += old.get(x + 0, y - 1); n += old.get(x - 1, y - 1); set(x, y, old.get(x, y) ? n == 2 || n == 3 : n == 3); } } } }; // Kikkailutoteutus: neljä bittiä per ruutu, koska 8 (dec) = 1000 (bin). struct Life2 { uint64_t data[16]; Life2(): data() { } void set(int x, int y, bool val) { if (val != get(x, y)) { data[y] ^= 1ULL << (x << 2); } } bool get(int x, int y) const { return (data[y] >> (x << 2)) & 1; } void step() { Life2 old(*this); data[0] = old.data[0] | ((old.data[0] << 4) + (old.data[0] >> 4) + (old.data[1] << 4) + old.data[1] + (old.data[1] >> 4)); for (int i = 1; i < 15; ++i) { data[i] = old.data[i] | ((old.data[i] << 4) + (old.data[i] >> 4) + (old.data[i+1] << 4) + (old.data[i+1] >> 4) + old.data[i+1] + (old.data[i-1] << 4) + (old.data[i-1] >> 4) + old.data[i-1]); } data[15] = old.data[15] | ((old.data[15] << 4) + (old.data[15] >> 4) + (old.data[14] << 4) + old.data[14] + (old.data[14] >> 4)); for (int i = 0; i < 16; ++i) { data[i] = data[i] & (data[i] >> 1) & 0x1111111111111111ULL; } } }; int main() { printf("Life1: %6.3f miljoonaa kierrosta sekunnissa\n", test<Life1>(1000000) / 1000000.0); printf("Life2: %6.3f miljoonaa kierrosta sekunnissa\n", test<Life2>(1000000) / 1000000.0); }
Onhan tuo paljon tehokkaampi nopeudelta ja muistinkulutukselta kuin osasin odottaa, mutta jos toteutus on tälläistä kikkailua, niin voiko sitä hyväksyä näytöksi siitä, että 64-bittinen prosessori sopisi bitti- ja tavulaskentaan?
Vaihtoehtona voisi ajatella sitä että Life1:tä ajettaisiin usealla vähempibittisellä prosessorilla. Tehon menetys ei olisi huima, mutta koodi pysyisi selkeänä.
Tuo muu koodi on hienoa, mutta miksi ratkaisevan osan pitää olla lähes yhtä rakenteetonta kuin konekieli. Ymmärrän kyllä suunnilleen mitä siinä tapahtuu, mutta olisi hyvä jos voisit lisätä siihen abstraktiota osoittaaksesi esim. sen ylläpidettävyyttä.
Tässä versio joka häviää nopeudessa enää 20-kertaisesti. Siinä on naapurien laskeminen omana funktiona.
// Oma "8-bittinen" versio struct Life1opt2 { bool data[18][18]; // 1 + 16 + 1 = 18, ei tarvitse tarkistella indeksejä. Life1opt2(): data() { } void set(int x, int y, bool val) { data[x][y] = val; } bool get(int x, int y) const { return data[x][y]; } //kuinka monta naapuria on päällä int getnaapurisumma(int x, int y) const { return data[x-1][y]+data[x+1][y]+data[x-1][y-1]+data[x][y-1]+ data[x+1][y-1]+data[x-1][y+1]+data[x][y+1]+data[x+1][y+1]; } void step() { Life1opt2 old(*this); for (int y = 1; y < 17; ++y) { for (int x = 1; x < 17; ++x) { int n = old.getnaapurisumma(x,y); set(x, y, old.get(x, y) ? n == 2 || n == 3 : n == 3); } } } };
Aihe on jo aika vanha, joten et voi enää vastata siihen.