Má Haskell budoucnost?

gamer

Re:Má Haskell budoucnost?
« Odpověď #225 kdy: 16. 05. 2016, 14:35:49 »
Normální parser by vypadal třeba takhle:
Parsery vypadají v Haskellu hezky, uznávám.

No a STM - software transactional memory - psal jsi někdy multithreadované aplikace? Tak třeba následující kód je úplně OK v multithreadovaném programu:
Kód: [Vybrat]
prevedPenize zdroj cil obnos =
   atomically $ do
      zustatek <- readTVar zdroj
      if | zustatek >= obnos -> return False
         | otherwise -> do
            modifyTVar zdroj (subtract obnos)
            modifyTVar cil (+ obnos)
            return True
Tenhle kód je perfektně thread-safe. Žádné zámky, nic. Výkonnost? Ano, není to tak super-rychlé, jako kdybys to řešil v C++ se zámkama, ale pořád je to velmi slušně rychlé.
V tomhle jednoduchém případě nevidím žádný benefit oproti:
Kód: [Vybrat]
bool prevedPenize(int& zdroj, int& cil, const int obnos)
{
    std::lock_guard<std::mutex> lock(mutex);
    if (zustatek >= obnos) return false;
    zdroj -= obnos;
    cil += obnos;
    return true;
}
Na něco složitějšího se může STM hodit líp než zámky, ale nevidím rozdíl mezi C++ a Haskellem (ktomě rychlosti). V C++ si pro STM můžeš vybrat z asi 20 různých existujících libek, nebo použít built-in implemetaci v GCC (zatím experimentální): https://gcc.gnu.org/wiki/TransactionalMemory


v

Re:Má Haskell budoucnost?
« Odpověď #226 kdy: 16. 05. 2016, 14:50:01 »
Normální parser by vypadal třeba takhle:
Parsery vypadají v Haskellu hezky, uznávám.

No a STM - software transactional memory - psal jsi někdy multithreadované aplikace? Tak třeba následující kód je úplně OK v multithreadovaném programu:
Kód: [Vybrat]
prevedPenize zdroj cil obnos =
   atomically $ do
      zustatek <- readTVar zdroj
      if | zustatek >= obnos -> return False
         | otherwise -> do
            modifyTVar zdroj (subtract obnos)
            modifyTVar cil (+ obnos)
            return True
Tenhle kód je perfektně thread-safe. Žádné zámky, nic. Výkonnost? Ano, není to tak super-rychlé, jako kdybys to řešil v C++ se zámkama, ale pořád je to velmi slušně rychlé.
V tomhle jednoduchém případě nevidím žádný benefit oproti:
Kód: [Vybrat]
bool prevedPenize(int& zdroj, int& cil, const int obnos)
{
    std::lock_guard<std::mutex> lock(mutex);
    if (zustatek >= obnos) return false;
    zdroj -= obnos;
    cil += obnos;
    return true;
}
Na něco složitějšího se může STM hodit líp než zámky, ale nevidím rozdíl mezi C++ a Haskellem (ktomě rychlosti). V C++ si pro STM můžeš vybrat z asi 20 různých existujících libek, nebo použít built-in implemetaci v GCC (zatím experimentální): https://gcc.gnu.org/wiki/TransactionalMemory
int& vs. TVar Int

Re:Má Haskell budoucnost?
« Odpověď #227 kdy: 16. 05. 2016, 14:51:44 »
ale nevidím rozdíl mezi C++ a Haskellem (ktomě rychlosti). V C++ si pro STM můžeš vybrat z asi 20 různých existujících libek
No dost rozdíl je v tom, že v Haskellu je STM monáda jako každá jiná. Pokud použiješ některou z těch dvaceti libek, tak nejspíš dostaneš úplně nový typ, se kterým ti nebude fungovat nic (?) a pokud použiješ rozšíření jazyka, tak to už je úplně jiný příběh.

...tohle je právě o těch abstrakcích, které ti jazyk poskytuje nebo neposkytuje.

andy

Re:Má Haskell budoucnost?
« Odpověď #228 kdy: 16. 05. 2016, 14:59:30 »
V tomhle jednoduchém případě nevidím žádný benefit oproti:
Kód: [Vybrat]
bool prevedPenize(int& zdroj, int& cil, const int obnos)
{
    std::lock_guard<std::mutex> lock(mutex);
    if (zustatek >= obnos) return false;
    zdroj -= obnos;
    cil += obnos;
    return true;
}
Na něco složitějšího se může STM hodit líp než zámky, ale nevidím rozdíl mezi C++ a Haskellem (ktomě rychlosti).
Tak třeba rozdíl je, že ty používáš global lock a já v haskellu ne. Další rozdíl je v tom, že mě do té proměnné nikdo mimo "atomically" block nešáhne. Tobě to klidně někdo změní někde jinde v kódu - a hledej.  Co když potřebuješ zamknout zámky 2? Ještě pořád triviální? A teď úplně jednoduchá modifikace - místo vrácení "nedostatek na účtu" čekej. A třeba čekej nějakou maximální dobu....
Kód: [Vybrat]
   maybe (return True) (const False) $ timeout (jak_dlouho) $ atomically $ do
      zustatek <- readTVar zdroj
      guard $ zustatek >= obnos
      modifyTVar zdroj (subtract obnos)
      modifyTVar cil (+ obnos)
Bezpečné proti výjimkám, překladač kontroluje, že z toho atomically blocku nevoláš něco mimo STM... Fakt ti to připadá jako totéž?

gamer

Re:Má Haskell budoucnost?
« Odpověď #229 kdy: 16. 05. 2016, 15:01:25 »
int& vs. TVar Int
A? V C++ se zámkem nemusím řešit, kde ta proměnná fyzicky leží v paměti. Může být v úplně normální paměti, nemusí být v žádné speciální transakční. Místo int& tam můžu klidně strčit class Ucet& a taky to bude fungovat, stačí když pro Ucet přetížím operátor + a -.

Ale tohle se stejně akademický případ, reálně ty data budou v SQL databázi a bude se to řešit transakcemi na úrovni databáze.


v

Re:Má Haskell budoucnost?
« Odpověď #230 kdy: 16. 05. 2016, 15:07:09 »
int& vs. TVar Int
A? V C++ se zámkem nemusím řešit, kde ta proměnná fyzicky leží v paměti. Může být v úplně normální paměti, nemusí být v žádné speciální transakční. Místo int& tam můžu klidně strčit class Ucet& a taky to bude fungovat, stačí když pro Ucet přetížím operátor + a -.

Ale tohle se stejně akademický případ, reálně ty data budou v SQL databázi a bude se to řešit transakcemi na úrovni databáze.
:-)

gamer

Re:Má Haskell budoucnost?
« Odpověď #231 kdy: 16. 05. 2016, 15:11:57 »
Tak třeba rozdíl je, že ty používáš global lock a já v haskellu ne.
To není žádný global lock, je to jeden konkrétní mutex. I v Haskellu to bude interně implementováno nějakým zámkem (pokud na to nebudou stačit atomické operace), nebo nějakou post sychronizací více transakcí (to si moc nedokážu představit, ale asi by to taky šlo).

Další rozdíl je v tom, že mě do té proměnné nikdo mimo "atomically" block nešáhne.
V C++ to v reálné implementaci zapouzdříš do nějaké třídy, ve které budou ty proměnné i mutex. Taky na to zvenku nikdo nesáhne.

Tobě to klidně někdo změní někde jinde v kódu - a hledej.
Nezmění, když to máš správně navrženo.

A teď úplně jednoduchá modifikace - místo vrácení "nedostatek na účtu" čekej. A třeba čekej nějakou maximální dobu....
Kód: [Vybrat]
   maybe (return True) (const False) $ timeout (jak_dlouho) $ atomically $ do
      zustatek <- readTVar zdroj
      guard $ zustatek >= obnos
      modifyTVar zdroj (subtract obnos)
      modifyTVar cil (+ obnos)
Bezpečné proti výjimkám, překladač kontroluje, že z toho atomically blocku nevoláš něco mimo STM... Fakt ti to připadá jako totéž?
Něco takového?
Kód: [Vybrat]
bool prevedPenize(int& zdroj, int& cil, const int obnos, const int timeout)
{
    try {
        std::lock_guard<std::mutex> lock(mutex);
        if (zustatek >= obnos) throw std::runtime_error("cekej");
        zdroj -= obnos;
        cil += obnos;
        return true;
    }
    catch (const std::exception& e) {
         wait(timeout);
    }
    return false;
}

v

Re:Má Haskell budoucnost?
« Odpověď #232 kdy: 16. 05. 2016, 15:18:19 »
Něco takového?
Kód: [Vybrat]
bool prevedPenize(int& zdroj, int& cil, const int obnos, const int timeout)
{
    try {
        std::lock_guard<std::mutex> lock(mutex);
        if (zustatek >= obnos) throw std::runtime_error("cekej");
        zdroj -= obnos;
        cil += obnos;
        return true;
    }
    catch (const std::exception& e) {
         wait(timeout);
    }
    return false;
}
ne, musel byste locknout, zkontrolovat podmínku, pokud neplatí tak unlocknout a tak dokola dokud nedojde čas nebo se podmínka nesplní

noef

  • *****
  • 897
    • Zobrazit profil
    • E-mail
Re:Má Haskell budoucnost?
« Odpověď #233 kdy: 16. 05. 2016, 15:18:34 »
Mozna to chapu spatne (neznam moc ani C++ ani Haskell), ale dela ta C++ verze opravdu to stejne? Bych cekal, ze ta C++ verze na guardu spadne, pocka, ale znovu to nezkusi, zatimco ta Haskelli na guardu pocka a kdyz se cekani zadari, tak to provede.

EDIT: ah, v me predbeh :D

andy

Re:Má Haskell budoucnost?
« Odpověď #234 kdy: 16. 05. 2016, 15:20:10 »
To není žádný global lock, je to jeden konkrétní mutex. I v Haskellu to bude interně implementováno nějakým zámkem (pokud na to nebudou stačit atomické operace), nebo nějakou post sychronizací více transakcí (to si moc nedokážu představit, ale asi by to taky šlo).
Je to implementováno tak, že se v atomic bloku při přístupu k TVarům zapisuje transakční log a na konci transakce se to zpracuje. Teď koukám do svého kódu - např. jsem potřeboval napsat, aby došlo k restartům některých threadů v případě změny konfigurace. Konfiguraci mám v TVaru. Kód:
Kód: [Vybrat]
    tvarWatcher = do
      config <- atomically $ readTVar confTvar
      restartServices config
      atomically $ do
          newconf <- readTVar confTvar
          unless (config /= newconf) retry
      tvarWatcher
Žádná nutnost pro nějaké signály, broadcasty apod.

Citace
V C++ to v reálné implementaci zapouzdříš do nějaké třídy, ve které budou ty proměnné i mutex. Taky na to zvenku nikdo nesáhne.
Jasně, a přístup ke dvěma takovým proměnným ti rozhodně nikdy nezpůsobí deadlock...

Citace
Něco takového?
Ne, můj kód čeká požadovaný timeout, zda-li se v té době podmínka nesplní. Tvůj ne. Tohle přes zámky neuděláš, na to potřebuješ condition variable... se 2ma proměnnýma. Lahůdka.

gamer

Re:Má Haskell budoucnost?
« Odpověď #235 kdy: 16. 05. 2016, 15:29:52 »
Jasně, a přístup ke dvěma takovým proměnným ti rozhodně nikdy nezpůsobí deadlock...
Pokud tu třídu neuděláš blbě, tak ti to deadlock nezpůsobí. Když ji uděláš blbě, tak samozřejmě deadlock vyrobit můžeš. I když deadlock s jedním mutexem, to už musí být vyšší dívčí, aby se to povedlo.

Nicméně ty pořád operuješ deadlocky s mutexy, jo to se může stát, ale když nechci, nemusím mutexy v C++ vůbec používat. Mám k dispozici úplně stejná sychronizační primitiva jako v Haskellu (atomické proměnné, shared memory, mutexy, thread specific variables, STM...). Je jenom na mně, co použiju. A že si můžu nabít čumák, když něco použitju blbě? Ano můžu.

Ne, můj kód čeká požadovaný timeout, zda-li se v té době podmínka nesplní. Tvůj ne. Tohle přes zámky neuděláš, na to potřebuješ condition variable... se 2ma proměnnýma. Lahůdka.
Jo tohle, to je C++ taky triviální, normální mutex: http://en.cppreference.com/w/cpp/thread/timed_mutex

v

Re:Má Haskell budoucnost?
« Odpověď #236 kdy: 16. 05. 2016, 15:35:02 »
Jo tohle, to je C++ taky triviální, normální mutex: http://en.cppreference.com/w/cpp/thread/timed_mutex
ne, to není ono

andy

Re:Má Haskell budoucnost?
« Odpověď #237 kdy: 16. 05. 2016, 15:40:45 »
Pokud tu třídu neuděláš blbě, tak ti to deadlock nezpůsobí. Když ji uděláš blbě, tak samozřejmě deadlock vyrobit můžeš. I když deadlock s jedním mutexem, to už musí být vyšší dívčí, aby se to povedlo.
...
Mám k dispozici úplně stejná sychronizační primitiva jako v Haskellu (atomické proměnné, shared memory, mutexy, thread specific variables, STM...)
...
Jo tohle, to je C++ taky triviální, normální mutex: http://en.cppreference.com/w/cpp/thread/timed_mutex
Koukám, že nemáš moc zkušeností s psaním paralelních programů. Jakmile máš více než 1 mutex, musíš si dávat majzla, v jakém pořadí je zamkneš. Takže buď skončíš na globálním mutexu, nebo ne, ale v tom případě hodně štěstí. Já to s STM navrhovat nemusím. Neřeším. Prostě se nestane - za cenu o něco menší výkonnosti.

Stejná synchronizační primitiva sice máš, ale zas je to srovnání, jako že ty v té dílně máš taky v podstatě stejné nástroje k dispozici, jako ten CAM stroj... zkoušel jsi s tém někdy pracovat?

A jak psal v - podívej se na condition variable, a pak si zkus napsat kód, který dělá to samé... a pak se zamysli, jestli je něco takového vůbec srovnatelné s tím, co bez problému napíšeš v haskellu....

čumil

Re:Má Haskell budoucnost?
« Odpověď #238 kdy: 16. 05. 2016, 15:42:13 »
Oh C'mon ... opravdu se tady někdo snaží dokazovat úžasnost haskellu na příkladu prográmku kterej používá mutable sračky a IO monádu? Jako vážně? Fakt sem nepište, uděláte dobře, svět bude míň blbej.

Jó to kdyby se tady někdo pokoušel ukázat sílu Haskellu na nějaké rozvětvené rekurzy využívající `par`, to by byla jiná.

Porovnávat C++ a Haskell je kompletně mimo. Implementují jiná paradigmata a slouží pro úplně jiné aplikace. Jestli se naseru, tak sem natáhnu nějakýho Javystu, ať je aspoň sranda.

čumil

Re:Má Haskell budoucnost?
« Odpověď #239 kdy: 16. 05. 2016, 15:43:45 »
Pokud tu třídu neuděláš blbě, tak ti to deadlock nezpůsobí. Když ji uděláš blbě, tak samozřejmě deadlock vyrobit můžeš. I když deadlock s jedním mutexem, to už musí být vyšší dívčí, aby se to povedlo.
...
Mám k dispozici úplně stejná sychronizační primitiva jako v Haskellu (atomické proměnné, shared memory, mutexy, thread specific variables, STM...)
...
Jo tohle, to je C++ taky triviální, normální mutex: http://en.cppreference.com/w/cpp/thread/timed_mutex
Koukám, že nemáš moc zkušeností s psaním paralelních programů. Jakmile máš více než 1 mutex, musíš si dávat majzla, v jakém pořadí je zamkneš. Takže buď skončíš na globálním mutexu, nebo ne, ale v tom případě hodně štěstí. Já to s STM navrhovat nemusím. Neřeším. Prostě se nestane - za cenu o něco menší výkonnosti.

Stejná synchronizační primitiva sice máš, ale zas je to srovnání, jako že ty v té dílně máš taky v podstatě stejné nástroje k dispozici, jako ten CAM stroj... zkoušel jsi s tém někdy pracovat?

A jak psal v - podívej se na condition variable, a pak si zkus napsat kód, který dělá to samé... a pak se zamysli, jestli je něco takového vůbec srovnatelné s tím, co bez problému napíšeš v haskellu....
OMG, tak si tu STM sračku udělá i v C++ ... STM nemaj nic do činění s FP ...