Vlákna ještě jednou – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu
Reklama
Reklama

Vlákna ještě jednou – C / C++ – Fórum – Programujte.comVlákna ještě jednou – C / C++ – Fórum – Programujte.com

 

Toto vlákno bylo označeno za vyřešené.
Hledá se programátor! Plat 1 800 € + bonusy (firma Boxmol.com)
Sefiros0
Návštěvník
12. 8. 2013   #1
-
0
-

Hoj,

nečelím v tuto chvíli ani tak problému jako spíš nejasnosti. Mám dvě vlákna které provádějí operace nad stejnou globální proměnnou. Globální proměnná je atomického datového typu. Přesto se moc atomicky nechová. Výsledek tohoto programu je pokaždé jiný, ačkoli by měl být stejný což znamená že se mi tam rvou vlákna. Není mi moc jasné proč, neb přece používám atomický datový typ který by měl být ňák "olockovaný" ne? Je dost možné že my něco uniklo, přece jenom někdy anglické věty hádám takže se radši ptám.

#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>

std::atomic<unsigned long> result(0);

void work()
{
    using namespace std;
    for (int i=0;i < 10000000;++i)
    {
        if (result.is_lock_free()) /*result není nikdy zamčen ???*/
        {
            //++result; /*funguje jak má*/ 
            result.store(result.load()+1); /*pokaždé jiný vysledek*/
        }
        else
        {
            cout << "Atom result je zamcen!" << endl; 
        }
    }
}

int main()
{
    using namespace std;
    thread alphaThread(work);
    thread betaThread(work);
    alphaThread.join();
    betaThread.join();
    cout << result.load() << endl;
    return 0;
}
Nahlásit jako SPAM
IP: 80.188.252.–
Reklama
Reklama
vitamin+8
Grafoman
12. 8. 2013   #2
-
0
-

#1 Sefiros
skus toto:

#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>

std::atomic<unsigned long> result(0);

void work(){
    for (int i=0;i < 10000000;++i){

		result++;
    }
}

int main()
{
    using namespace std;
    thread alphaThread(work);
    thread betaThread(work);
    
    alphaThread.join();
    betaThread.join();
    
    cout << result << endl;
    return 0;
}
Nahlásit jako SPAM
IP: 95.105.152.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
KIIV+42
God of flame
12. 8. 2013   #3
-
+1
-
Zajímavé

problem je v tom, ze tim load a store vesmes udelas neatomickou operaci.... load a store jsou samo o sobe atomicke ale ne uz pokud je spojis

Nahlásit jako SPAM
IP: 213.220.241.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Sefiros0
Návštěvník
12. 8. 2013   #4
-
0
-

No a zde je jádro mé otázky. Co se stane když místo atomické kapsle kolem longu použiji prostě jen long? Uniká mě totiž přesná funkce atomických datových typů. Je mi jasné že ++i je atomický zatímco i=i+1 už ne.

Nahlásit jako SPAM
IP: 80.188.252.–
KIIV+42
God of flame
12. 8. 2013   #5
-
+1
-
Zajímavé

nemusi to byt nutne pravda...  slo hlavne o to, ze si pouzil vice atomickych operaci a tim uz si nemel jednu atomickou - nahral sis do nejakeho jineho mista obsah promenne, pricetl jedna a pak ulozil - to uz muze byt kdykoliv preruseno... Jinak u normalnich promennych neni atomicita zarucena nikdy (zalezi jen na procesoru, cache, a tak dale) a museji se pak pouzivat zamky...

Zamky jsou oproti atomickym operacim vyrazne pomalejsi - to je duvod, proc se pouzivaji ty atomicke promenne. + se to taky postara o urcity side effekty co se tyce procesorove cache...

A kdyz pouzijes toto, tak hned uvidis, ze to neni proste ani trochu atomicke:

#include <atomic>

//std::atomic<unsigned long> result(0);
unsigned long result(0);

void work()
{
    using namespace std;
    for (int i=0;i < 10000000;++i)
    {
        ++result; /*funguje jak má*/ 
        //result.store(result.load()+1); /*pokaždé jiný vysledek*/
    }
}

int main()
{
    using namespace std;
    thread alphaThread(work);
    thread betaThread(work);
    alphaThread.join();
    betaThread.join();
    //cout << result.load() << endl;
    cout << result << endl;
    return 0;
}
Nahlásit jako SPAM
IP: 213.220.241.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Sefiros0
Návštěvník
12. 8. 2013   #6
-
0
-

Už jsem to začal chápat, díky. Poslední otázka. Jak je vlastně vytvořena atomická operace? Třeba load() a nebo store(). Jsou využívány atomické instrukce procesoru a nebo je "atomicita" emulována nějak jinak?

Nahlásit jako SPAM
IP: 80.188.252.–
KIIV+42
God of flame
12. 8. 2013   #7
-
0
-

jen pro srovnani:  

#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
#include <vector>
#include <cstdint>

uint64_t result(0);
std::mutex mx;

void work()
{
    using namespace std;
    for (int i=0;i < 10000000;++i)
    {
        mx.lock();
        ++result; 
        mx.unlock();
    }
}

int main()
{
    using namespace std;
    thread  thrd[4] {thread{work},thread{work},thread{work},thread{work}};

    for (int x = 0; x<4; ++x) thrd[x].join();

    cout << result << endl;
    return 0;
}

identicky kod bez mutexu s atomickou hodnotou (bez zapnutych optimalizaci) (bezi to na 4jadrovym 64b virtualu :)):

time ./a.out
40000000

real    0m1.179s
user    0m4.308s
sys     0m0.064s

s mutexem:

time ./a.out
40000000

real    0m6.707s
user    0m4.020s
sys     0m15.313s

Nahlásit jako SPAM
IP: 213.220.241.–
Program vždy dělá to co naprogramujete, ne to co chcete...
KIIV+42
God of flame
12. 8. 2013   #8
-
+1
-
Zajímavé

#6 Sefiros
jsou na to specialni instrukce, ktery pak atomicitu zaruci + specialni priznaky pro stranky cache - jestli jsou pouzivany pro cteni, tak ji muze mit vic jader v cache, pokud pro zapis tak uz jen jedno jadro v jeden okamzik a tak dale...

Nahlásit jako SPAM
IP: 213.220.241.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Sefiros0
Návštěvník
12. 8. 2013   #9
-
0
-

Díky za pomoc. Už tuším o co go. 

Nahlásit jako SPAM
IP: 80.188.252.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 201 hostů

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032016 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý