Keresés

Új hozzászólás Aktív témák

  • flugi

    tag

    válasz flugi #41 üzenetére

    a harmadik bekezdésből hiányzik az asszociativitás a kommutativitás mellől, természetesen beleértendő.

  • flugi

    tag

    válasz dezz #40 üzenetére

    A GPU kódot ha kézzel lapogatjuk ki (memóriaterhelés ritkítás aritmetika közé), akkor gyorsul. Ez alátámasztja azt a heurisztikus állásfoglalást is, hogy a GPU stream processzor nem rendez át, mert az sokat bonyolít a magon, és sok a mag. Ezt a feladatot a driver végzi el, amikor előállítja az adott architektúra számára kedves átrendezést fordítási időben. (a fenti kísérletet nVidia GPU-n, assemblerrel csináltuk)

    Az OpenCL és a driver adatfüggőséget kezel, ahol is nem átrendezhető két művelet, ha az egyik írja a másik bemenetét.

  • flugi

    tag

    válasz Sir Ny #39 üzenetére

    Oké, most érthetően kifejezted magad, elnézést kell kérnem a gyanúsításért. De ha már kekeckedünk, legyünk precízek.

    Egy pl. C/C++ nyelven kifejezett x=a+b+c értékadásnak pontosan egy megoldása van, mivel az összeadás műveletek azonos prioritásuk miatt jobbról balra értékelődnek ki, amit nem rendezhet át se fordító, se processzor az adatfüggőségek miatt.

    Ha arra hivatkozunk, hogy az összeadás kommutatív, tehát tetszőleges sorrendben jó az összeadás, akkor az a matematika a maga valós, racionális számaival, ahol az x=a+b+c pontosan egyetlen megoldása van, de ugye az most nem játszik, most a lebegőpontos számok játszanak.

    Ha tehát úgy fogalmazol, hogy az a+b+c összeg operandusainak tetszőleges átrendezése más-más eredményt adhat lebegőpontos számoknál, akkor pontos vagy. Ez ugye akár 3*2*1=6 lehetséges sorrend, viszont ha feltételezzük, hogy az összeadás kommutatív (IEEE kompatibilis implementációnál például az), akkor 3 féle lehetséges eredménye van.

    Összefoglalva: csak abban tévedsz, hogy az utasítások általánosságban átrendezhetőek. Ez nem így van, például x86-on C/C++-ban nem. Vegyük észre, hogy ha sérül az asszociativitás a műveletre nézve, akkor a gépi kódú lépésekre bontás szintjén a kommutativitásra hivatkozva sem rendezhetünk át utasításokat, mert potenciálisan sértjük az asszociativitást. Az ADD utasítás két operandusát szabad csak felcserélni, és azt is elvileg csak olyan architektúrán, ahol az implementáció kommutatív.

    Kész vagyok viszont elismerni az igazad, ha tudsz mutatni olyan nyelvet, fordítót, és architektúrát, amit használnak is valamire, és ahol az x:=a+b+c kifejezése nem determinisztikus, mert én nem ismerek ilyet.

  • flugi

    tag

    válasz Sir Ny #37 üzenetére

    Természetesen az a+b+c=x egyenletnek (amennyiben x ismert, és a,b,c értékekre kell megoldani) végtelen sok megoldása van. Három megoldása egyetlen értelmezésben sem lehet, a kötött operandusok számától függően vagy pontosan egy megoldás van, vagy végtelen sok.

    A másodfokú egyenlet megoldásakor sem azt mondja a programozó, hogy kérek egy megoldást. Konstruktív megoldást kell adjon a programozó a másodfokú egyenlet megoldására. Konkrétan a x1 := (-b + sqrt(b*b - 4*a*c))/(2*a) értékadással konkrétan az egyik, x1 := (-b - sqrt(b*b - 4*a*c))/(2*a) értékadással konkrétan a másik értéket számolják ki (pozitív diszkrimináns esetén).

    Matlabban van [x1 x2] = roots([a b c]) függvény, ami lényegében pont ez, csak komplex számokkal dolgozik, és konkrétan mindkét megoldást visszaadja. Nem csak random az egyiket.

    Ha messzemenően jóindulatúan kezelem az általad elmondottakat (amire nem sok okom van, mert több jel utal arra, hogy nem vagy képben, mintsem hogy túl bonyolult fogalmakra utalsz azok megnevezése nélkül), akkor azt mondhatom, hogy az iteratív közelítő eljárások, genetikus algoritmus implementációk hasonlítanak arra, amit körvonalazol, de ezeknek a módszereknek semmi értelme zárt alakban kifejezhető értékek keresésekor, és a példa még mindig a másodfokú egyenlet volt. Ráadásul ezeknek a módszereknek a lassúságuk az egyik fő ismérvük.

  • flugi

    tag

    válasz Sir Ny #34 üzenetére

    a példa értelmezése szerint az egyenletrendszernek egyetlen, két értékű megoldása van, az 1 és a -1 páros. Egyetlen pár, amiben két valós szám van. Egyetlen más pár sem megoldása az egyenletrendszernek. Nincs alternatíva.

    Ez a matematika. Valós számok, racionális számok, egész számok. Nem float típus típusértékhalmaza, hacsak külön nem jelöljük, mivel ezek a halmazok nem alkotnak csoportot vagy gyűrűt. Nem jelölte a példa. A számelméleti axiomák nem teljesülnek a számítástechnikai típusokra, speciális fogalmakat kell hozzá használni.

    Más: a 0.999 leírva nem egyezik meg a 0.999... kezdetű végtelen törttel, és én természetesen nem gondolhattam a végtelen törtre, ez a kontextusból nyilvánvaló volt. A 0.999 = 999/1000 racionális érték. A float és double értékek mindegyike egy racionális szám, és mint ilyen, az 1-es érték, és a 0.999 kezdetű float érték különböző.

    Egyszálú igényes CPU programok esetében lehet gondoskodni a helyes eredmény erőltetéséről, ami az esetek jó részében elegendő a jó megoldáshoz. Vannak olyan több hónapos futási eredmények klasztereken, ahol az eredmény sokadik tizedesjegyének pontossága kedvéért fut a program a futásidő felében, mert azon a szakterületen ez a tizedesjegy éppen nagyon fontos. Ilyen esetekben a klasszikus "kisebb számokat adom össze először" hozzáállással már sokszor meg lehet oldani a determinisztikus helyes eredményt adó programot, máskor egyéb trükkökre is szükség lehet.

    Schrödinger macskája pedig arról szól, hogy abban a kvantummechanikai modellben, ahol úgy fogalmazunk, hogy "összeomlik a hullámfüggvény" a megfigyelőtől, annak milyen vicces következménye egy olyan gondolatkísérlet, ahol direkt nem omlasztjuk össze egy darabig. A véletlengenerálás ebben a dologban egy (persze kihagyhatatlan, de) részletkérdés. Nem arról szól a Schrödinger macska, hogy nem lehet tudni, hogy él-e vagy nem, hanem hogy mikor mit lehet tudni, nyitás előtt és után. Pláne nem arról szól, hogy akár él, akár nem, mindkettő jó megoldás :D

  • flugi

    tag

    válasz dezz #31 üzenetére

    Az out of order képességnek ügyelnie kell arra, hogy ne legyen megváltoztató hatása. Nem ütemezhet át olyan utasításokat, amik egymás eredményeit olvassák. Ha vesszük az a+=b; a+=c; dataflow-t, akkor az kifejtve matematikailag egyenértékű kellene legyen az a := a + b + c -vel, de sajnos az utasítások sorrendje pontosan a számábrázolási pontatlanságok miatt számít.

    Két számnál még nem különösebben érdekes ez, de ha vesszük a következő példát:

    #include <iostream>
    #include <iomanip>
    #include <vector>

    using namespace std;

    int main()
    {
    int N = 100;
    float f = 1.0;
    vector<float> szamok(N);
    for (int i=1;i<N;i++) {
    szamok[i] = f;
    f*=.8;
    }

    float sum = 0.0;
    for (int i=0;i<N;i++) {
    sum += szamok[i];
    }
    cout <<setprecision(16) << sum << endl;

    sum = 0.0;
    for (int i=0;i<N;i++) {
    sum += szamok[N-i-1];
    }
    cout <<setprecision(16) << sum << endl;
    return 0;
    }

    Akkor az adott mértani sorozat összege 5-höz tart, elegendő darabszámú sorozattag összege a float precizitás erejéig pontosan ki is adja az eredményt (a második eredmény 5), míg ha rossz sorrendben adjuk össze a számokat, akkor az eredmény 4.99999.

    Ebből következően hiába igaz, hogy a matematikában az összeadás kommutatív, float és double számokra az ADD gépi utasítás nem az.

  • flugi

    tag

    válasz Sir Ny #30 üzenetére

    Schrödinger macskája annak köszönheti a népszerűségét, hogy furcsa, és sokan, köztük te is asszociatívan használják, vagyis "erről eszembe jutott" módon.

    A példád irreleváns. Az egyenletrendszernek van két megoldása valós számokon, ez két konkrét megoldás. Megoldási elvektől függően tudok olyan aritmetikai kifejtést adni, amivel a végigszámolás (ami ugye, emlékszünk, tartalmaz gyökvonást is, a másodfok miatt, úgyhogy a példád ilyen szempontból kényelmes) helyes megoldásnak egy 0.9999999938782736 alakú megoldást fog adni 1 helyett. Nem az a probléma ugyanis, hogy magának az egyenletrendszernek hány megoldása van, hanem az, hogy tetszőleges megoldáshoz való eljutás, a konkrét kiszámolás lépései azok, amiken a számábrázolás miatt zaj van, kerekítési pontatlanságok ÉS számábrázolási határok. Akinek van teszkógazdaságos számológépe, az tudja, hogy gyökháromszor gyökhárom az 2.99999999. A drágábbak sem azért tudják, hogy 3, mert ennek kell kijönnie, hanem mert szerencsésebbek a kerekítési és számábrázolási kérdésekben. Nem véletlen, hogy az FPU 80 biten számolja a 64 bites double-t.

    Abu azt mondta, hogy az baj, ha matekot végigszámolva hol 1, hol 0.999999 jön ki, és ilyen értelemben van több válasz ugyanarra a kérdésre. Ezt kreatívan kell félreérteni a válaszod kiindulópontjához, és még kreatívabban képzavarba verődve a Schrödinger cicájához eljutni.

  • flugi

    tag

    válasz #32839680 #24 üzenetére

    tízszeres sebességkülönbség. Néha a pontosság van olyan fontos, hogy kivárjuk, máskor meg a sebesség fontosabb. Most lehet választani. Ha csak egyfajta megoldás lenne, akkor lenne olyan feladat, amire alkalmatlanná válna az eszköz.

  • flugi

    tag

    válasz Sir Ny #20 üzenetére

    ez képzavar a javából. Abu állítása az volt, hogy tetszőleges aritmetikai kifejezés (akár több értékű is) determinisztikus, mivel a matematika átrendezési szabályai mentén masszírozott tetszőleges úton kapott végeredmény azonos. Ez a matematikában tényleg így van. Csak programozásban nem.

    Schrödinger cicája pedig tartja az irreleváns tudományosnak szánt hivatkozások világrekordját, szoros versenyben a Gödel tétellel, és a relativitáselmélettel. Nem csoda, hogy itt is felbukkant :D

  • flugi

    tag

    válasz polika #19 üzenetére

    a kerekítés szó többféle jelentése itt keveredik. Ha úgy értjük, hogy a kettedeslevágás helyett igényesebben csinálást nevezzük kerekítésnek, akkor arról az igaz, hogy nagy számú művelet mellett a kijövő eredmény várható értéke közel torzításmentes becslése a valódi végeredmény adott számábrázolásra csonkolásának. Ezzel szemben a kettedeslevágás mindig a nulla felé torzít, tehát sok művelet esetében a várható érték is a nulla felé mozdul el.

    Vicces apróság, hogy ha kettedeslevágás után az utolsó bitnyi értéket random hozzáadnánk a mantisszához, akkor statisztikailag javulna a pontosság :)

  • flugi

    tag

    válasz dezz #25 üzenetére

    vedd észre, hogy a CPU out of order tisztán függetlenséget vizsgál, tehát nem rendezhet át formálisan függő műveleteket. Pontosan a tárgyalt okok miatt.

    Az a+=b; a+=c; tehát nem rendezhető át a+=c; a+=b; formára, holott az összeadás elvileg kommutatív.

  • flugi

    tag

    válasz Abu85 #17 üzenetére

    Ez a hozzáállás alapvetően sérül a gyakorlatban, és ez nem a kerekítési probléma miatt van, hanem mert véges az ábrázolható kettedesjegyek száma. Egy IEEE float-ban 23, egy IEEE double-ben 52 kettedesjegy van. Ha van néhány ezer számod, amik nagyságrendben is eltérnek egymástól, akkor az összegük értéke attól fog függni, hogy milyen sorrendbe adod őket össze, mert ha a nagyobbakkal kezded, akkor a részösszeg nagyságrendje annyira különbözhet az összeadás kisebb operandusaitól, hogy azok konkrétan nem okoznak változást a bitekben, mert a 23-id (vagy akár 52-ik) kettedesjegy utániak.

    Az tehát eleve lehetetlen feladat, hogy egzakt, lebonyolításfüggetlen eredményt várjunk el. A kerekítési, illetve pontossági elvárások, amiket az IEEE float és double leír, azért érdekesek, mert amennyire lehet, maximalizálni tudják az egyes aritmetikai lépések pontosságát. Egy klasszikus közelítő GPU implementáció egy-két bitben akár el is térhet ettől, cserébe a hatékonysága akár 10-szeres is lehet. Tipikus, hogy a szögfüggvényeket float-ban GPU-n néhány FMA lépéssel lehet hardveresen megoldani, de ennek az eredménye nem egyezik pontosan az IEEE float pontosságával, ami grafikában általában tökmindegy, de egy GPGPU alkalmazásban fontos lehet, mert a sok részeredmény sok pontatlansága gyorsabban nő, mint az IEEE kevesebb pontatlansággal járó részeredményei.

    Érdekességképpen megjegyzendő, hogy különösen GPGPU alapokon domborodik ki a különböző ütemezések miatti eltérő részeredmény-csoportosítás miatti "újra számolom és más jön ki" jelenség, mivel a GPU atomikus művelete (amivel a párhuzamosan számolt részeredményeket összedolgozni érdemes) ütemezőfüggő sorrendben hajtódik végre, CPU programokban ez általában determinisztikus, hacsaknem több szálú, trükkös kódot csinál az ember.

Új hozzászólás Aktív témák

Hirdetés