<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[threading Problem]]></title><description><![CDATA[<p>Hallo zusammen</p>
<p>Ich experimentiere gerade mit Parallelisierung herum. Ich habe einen Threadpool geschrieben und versuch, damit einen Akkumulierungsalgorithmus zu parallelisieren. Leider funktioniert das ganze manchmal und manchmal nicht, d.h. manchmal stürzt das Programm ab. Ich frage mich, ob das ein Bug in gcc 4.7 sein könnte. Mir ist nicht bewusst, etwas falsch zu machen. Es würde mich freuen, wenn mal jemand einen Blick auf den Code werfen könnte (ist kompilierbar). Danke <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<pre><code>#include &lt;thread&gt;
#include &lt;condition_variable&gt;
#include &lt;mutex&gt;
#include &lt;vector&gt;
#include &lt;queue&gt;
#include &lt;functional&gt;
#include &lt;iostream&gt;

class task
{
    bool done;
    std::mutex mutex;
    std::condition_variable cond;
    std::function&lt;void()&gt; func;
public:
    template&lt;class F,  class ...Args&gt;
    task(const F&amp; f, Args ...args):
        done(false),
        func(std::bind(f, args...))
    {
    }

    void run()
    {
        func();
        set_done();
    }

    void set_done()
    {
        std::lock_guard&lt;std::mutex&gt; lock(mutex);

        done = true;
        cond.notify_all();
    }

    void wait()
    {
        std::unique_lock&lt;std::mutex&gt; lock(mutex);

        while(!done)
        {
            cond.wait(lock);
        }
    }
};

class thread_pool
{
    bool m_quit;
    int m_num;
    int m_idle;

    std::vector&lt;std::thread&gt; m_threads;
    std::queue&lt;task*&gt; m_queue;

    mutable std::mutex m_mutex;
    std::condition_variable m_cond;

    void worker()
    {
        while(1)
        {
            std::unique_lock&lt;std::mutex&gt; lock(m_mutex);

            ++m_idle;

            while(!m_quit &amp;&amp; m_queue.empty())
            {
                m_cond.wait(lock); // wait for quit signal or data in queue
            }

            if(m_quit) return;

            task* t = m_queue.front();
            m_queue.pop();
            --m_idle;
            lock.unlock();

            t-&gt;run();
        }
    }

public:
    thread_pool(int num_threads):
        m_quit(false),
        m_num(num_threads),
        m_idle(0)
    {
        std::lock_guard&lt;std::mutex&gt; lock(m_mutex);

        for(int i = 0; i &lt; m_num; ++i)
        {
            m_threads.emplace_back(std::thread(&amp;thread_pool::worker, this));
        }
    }

    ~thread_pool()
    {
        std::unique_lock&lt;std::mutex&gt; lock(m_mutex);
        m_quit = true;
        m_cond.notify_all();
        lock.unlock();

        for(auto &amp;i: m_threads) i.join();
    }

    void schedule(task&amp; t)
    {
        std::unique_lock&lt;std::mutex&gt; lock(m_mutex);

        m_queue.push(&amp;t);
        m_cond.notify_all();
    }

    void run(task&amp; t)
    {
        std::unique_lock&lt;std::mutex&gt; lock(m_mutex);

        if(m_idle &lt; 1)
        {
            lock.unlock();
            t.run();
        }
        else
        {
            m_queue.push(&amp;t);
            m_cond.notify_all();
        }
    }

    bool try_run(task&amp; t)
    {
        std::unique_lock&lt;std::mutex&gt; lock(m_mutex);

        if(m_idle &lt; 1)
        {
            return false;
        }
        else
        {
            m_queue.push(&amp;t);
            m_cond.notify_all();
        }
    }

    int num_idle() const
    {
        std::lock_guard&lt;std::mutex&gt; lock(m_mutex);

        return m_idle;
    }
};

template&lt;class Iter, class T&gt;
void accumulate(Iter start, Iter end, T&amp; val, thread_pool&amp; tp)
{
    if(start == end) return;

    if(std::distance(start, end) == 1)
    {
        val = *start;
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        return;
    }

    if(std::distance(start, end) == 2)
    {
        val = 0;
        val += *start++;
        val += *start;
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
        return;
    }

    Iter mid = start;
    std::advance(mid, std::distance(start, end) / 2);

    T a = 0, b = 0;

    task t(accumulate&lt;Iter, T&gt;, start, mid, std::ref(a), std::ref(tp));
    tp.run(t);
    accumulate(mid, end, b, tp);
    t.wait();

    val = a + b;
}

int main()
{
    thread_pool tp(8);
    std::vector&lt;int&gt; v(100, 1);
    int sum = 0;
    accumulate(v.begin(), v.end(), sum, tp);
    std::cout &lt;&lt; sum;

    return 0;
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/topic/317447/threading-problem</link><generator>RSS for Node</generator><lastBuildDate>Tue, 28 Jul 2026 18:48:02 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/317447.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 09 Jun 2013 07:29:34 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to threading Problem on Sun, 09 Jun 2013 07:29:34 GMT]]></title><description><![CDATA[<p>Hallo zusammen</p>
<p>Ich experimentiere gerade mit Parallelisierung herum. Ich habe einen Threadpool geschrieben und versuch, damit einen Akkumulierungsalgorithmus zu parallelisieren. Leider funktioniert das ganze manchmal und manchmal nicht, d.h. manchmal stürzt das Programm ab. Ich frage mich, ob das ein Bug in gcc 4.7 sein könnte. Mir ist nicht bewusst, etwas falsch zu machen. Es würde mich freuen, wenn mal jemand einen Blick auf den Code werfen könnte (ist kompilierbar). Danke <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<pre><code>#include &lt;thread&gt;
#include &lt;condition_variable&gt;
#include &lt;mutex&gt;
#include &lt;vector&gt;
#include &lt;queue&gt;
#include &lt;functional&gt;
#include &lt;iostream&gt;

class task
{
    bool done;
    std::mutex mutex;
    std::condition_variable cond;
    std::function&lt;void()&gt; func;
public:
    template&lt;class F,  class ...Args&gt;
    task(const F&amp; f, Args ...args):
        done(false),
        func(std::bind(f, args...))
    {
    }

    void run()
    {
        func();
        set_done();
    }

    void set_done()
    {
        std::lock_guard&lt;std::mutex&gt; lock(mutex);

        done = true;
        cond.notify_all();
    }

    void wait()
    {
        std::unique_lock&lt;std::mutex&gt; lock(mutex);

        while(!done)
        {
            cond.wait(lock);
        }
    }
};

class thread_pool
{
    bool m_quit;
    int m_num;
    int m_idle;

    std::vector&lt;std::thread&gt; m_threads;
    std::queue&lt;task*&gt; m_queue;

    mutable std::mutex m_mutex;
    std::condition_variable m_cond;

    void worker()
    {
        while(1)
        {
            std::unique_lock&lt;std::mutex&gt; lock(m_mutex);

            ++m_idle;

            while(!m_quit &amp;&amp; m_queue.empty())
            {
                m_cond.wait(lock); // wait for quit signal or data in queue
            }

            if(m_quit) return;

            task* t = m_queue.front();
            m_queue.pop();
            --m_idle;
            lock.unlock();

            t-&gt;run();
        }
    }

public:
    thread_pool(int num_threads):
        m_quit(false),
        m_num(num_threads),
        m_idle(0)
    {
        std::lock_guard&lt;std::mutex&gt; lock(m_mutex);

        for(int i = 0; i &lt; m_num; ++i)
        {
            m_threads.emplace_back(std::thread(&amp;thread_pool::worker, this));
        }
    }

    ~thread_pool()
    {
        std::unique_lock&lt;std::mutex&gt; lock(m_mutex);
        m_quit = true;
        m_cond.notify_all();
        lock.unlock();

        for(auto &amp;i: m_threads) i.join();
    }

    void schedule(task&amp; t)
    {
        std::unique_lock&lt;std::mutex&gt; lock(m_mutex);

        m_queue.push(&amp;t);
        m_cond.notify_all();
    }

    void run(task&amp; t)
    {
        std::unique_lock&lt;std::mutex&gt; lock(m_mutex);

        if(m_idle &lt; 1)
        {
            lock.unlock();
            t.run();
        }
        else
        {
            m_queue.push(&amp;t);
            m_cond.notify_all();
        }
    }

    bool try_run(task&amp; t)
    {
        std::unique_lock&lt;std::mutex&gt; lock(m_mutex);

        if(m_idle &lt; 1)
        {
            return false;
        }
        else
        {
            m_queue.push(&amp;t);
            m_cond.notify_all();
        }
    }

    int num_idle() const
    {
        std::lock_guard&lt;std::mutex&gt; lock(m_mutex);

        return m_idle;
    }
};

template&lt;class Iter, class T&gt;
void accumulate(Iter start, Iter end, T&amp; val, thread_pool&amp; tp)
{
    if(start == end) return;

    if(std::distance(start, end) == 1)
    {
        val = *start;
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        return;
    }

    if(std::distance(start, end) == 2)
    {
        val = 0;
        val += *start++;
        val += *start;
        std::this_thread::sleep_for(std::chrono::milliseconds(200));
        return;
    }

    Iter mid = start;
    std::advance(mid, std::distance(start, end) / 2);

    T a = 0, b = 0;

    task t(accumulate&lt;Iter, T&gt;, start, mid, std::ref(a), std::ref(tp));
    tp.run(t);
    accumulate(mid, end, b, tp);
    t.wait();

    val = a + b;
}

int main()
{
    thread_pool tp(8);
    std::vector&lt;int&gt; v(100, 1);
    int sum = 0;
    accumulate(v.begin(), v.end(), sum, tp);
    std::cout &lt;&lt; sum;

    return 0;
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2329504</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329504</guid><dc:creator><![CDATA[__Stefan__]]></dc:creator><pubDate>Sun, 09 Jun 2013 07:29:34 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Sun, 09 Jun 2013 07:45:45 GMT]]></title><description><![CDATA[<p>Fehlermeldung? Was sagt der Debugger/Stacktrace?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2329507</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329507</guid><dc:creator><![CDATA[SeppJ]]></dc:creator><pubDate>Sun, 09 Jun 2013 07:45:45 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Sun, 09 Jun 2013 07:54:48 GMT]]></title><description><![CDATA[<p><strong>Stefan</strong> schrieb:</p>
<blockquote>
<p>Leider funktioniert das ganze manchmal und manchmal nicht, d.h. manchmal stürzt das Programm ab.</p>
</blockquote>
<p>Ja, genau das passiert, wenn man bei mehreren Threads was falsch macht.</p>
<blockquote>
<p>Ich frage mich, ob das ein Bug in gcc 4.7 sein könnte.</p>
</blockquote>
<p>Sehr unwahrscheinlich.</p>
<blockquote>
<p>Mir ist nicht bewusst, etwas falsch zu machen. Es würde mich freuen, wenn mal jemand einen Blick auf den Code werfen könnte (ist kompilierbar). Danke <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
</blockquote>
<p>Geh mal davon aus, dass du was falsch gemacht hast und verwende einen Debugger.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2329512</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329512</guid><dc:creator><![CDATA[oh876ztgfcd]]></dc:creator><pubDate>Sun, 09 Jun 2013 07:54:48 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Sun, 09 Jun 2013 08:29:27 GMT]]></title><description><![CDATA[<p>threading ist die hölle</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2329519</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329519</guid><dc:creator><![CDATA[gcc]]></dc:creator><pubDate>Sun, 09 Jun 2013 08:29:27 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Sun, 09 Jun 2013 08:36:35 GMT]]></title><description><![CDATA[<p>SeppJ schrieb:</p>
<blockquote>
<p>Fehlermeldung? Was sagt der Debugger/Stacktrace?</p>
</blockquote>
<p>Windows sagt &quot;test.exe funktioniert nicht mehr&quot;</p>
<p>Wie könnte man da mit einem Debugger ansetzten? Mir kommt langsam die Vermutung dass da irgendwo noch Memorybarrieren rein müssen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2329521</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329521</guid><dc:creator><![CDATA[__Stefan__]]></dc:creator><pubDate>Sun, 09 Jun 2013 08:36:35 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Sun, 09 Jun 2013 08:38:03 GMT]]></title><description><![CDATA[<p>gcc schrieb:</p>
<blockquote>
<p>threading ist die hölle</p>
</blockquote>
<p>Ein gutes Programm sollte aber alle CPU-Kerne optimal nutzen. Nur so werden Programme heutzutage noch schneller.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2329522</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329522</guid><dc:creator><![CDATA[__Stefan__]]></dc:creator><pubDate>Sun, 09 Jun 2013 08:38:03 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Sun, 09 Jun 2013 09:20:12 GMT]]></title><description><![CDATA[<p><strong>Stefan</strong> schrieb:</p>
<blockquote>
<p>Wie könnte man da mit einem Debugger ansetzten?</p>
</blockquote>
<p>So wie sonst auch... <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2329537</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329537</guid><dc:creator><![CDATA[dot]]></dc:creator><pubDate>Sun, 09 Jun 2013 09:20:12 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Sun, 09 Jun 2013 09:34:30 GMT]]></title><description><![CDATA[<p>lol warum sind da sleep aufrufe drin <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2329541</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329541</guid><dc:creator><![CDATA[conf.]]></dc:creator><pubDate>Sun, 09 Jun 2013 09:34:30 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Sun, 09 Jun 2013 09:44:04 GMT]]></title><description><![CDATA[<p>conf. schrieb:</p>
<blockquote>
<p>lol warum sind da sleep aufrufe drin <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /></p>
</blockquote>
<p>Das ist nur zum testen ob man überhaupt einen Geschwindigkeitszuwachs durch Parallelisierung sieht. Das macht die Zeitmessung einfacher.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2329544</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329544</guid><dc:creator><![CDATA[__Stefan__]]></dc:creator><pubDate>Sun, 09 Jun 2013 09:44:04 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Sun, 09 Jun 2013 11:50:33 GMT]]></title><description><![CDATA[<p><strong>Stefan</strong> schrieb:</p>
<blockquote>
<p>Das ist nur zum testen ob man überhaupt einen Geschwindigkeitszuwachs durch Parallelisierung sieht. Das macht die Zeitmessung einfacher.</p>
</blockquote>
<p>Und verfälscht das Ergebnis extremst. Ob du Aufgaben parallelisierst die jeweils 2-3 Prozessortakte brauchen (die Addition) oder Aufgaben, die 200ms brauchen (sleep) ist ein gewaltiger Unterschied.</p>
<p>P.S.: Eine wesentlich bessere Strategie wäre hier übrigens, den Bereich in num_threads Teile aufzuteilen, die dann von den einzelnen Threads komplett bearbeitet werden. Das Aufteilen bis hinunter zu 1 oder 2 Elementen bringt hingegen massiven Overhead und dürfte deutlich(!) langsamer sein als eine Lösung mit nur einem Thread. Selbst die Aufteilung in mehrere Bereiche bringt nur etwas, wenn jeder Einzelbereich sehr groß ist, so dass der Taskoverhead klein gegenüber der Dauer der Aufgabe ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2329570</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329570</guid><dc:creator><![CDATA[SeppJ]]></dc:creator><pubDate>Sun, 09 Jun 2013 11:50:33 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Sun, 09 Jun 2013 11:38:14 GMT]]></title><description><![CDATA[<p><strong>Stefan</strong> schrieb:</p>
<blockquote>
<p>Ein gutes Programm sollte aber alle CPU-Kerne optimal nutzen. Nur so werden Programme heutzutage noch schneller.</p>
</blockquote>
<p>Wenn man weiß was man tut, auf single core schon alles rausgeholt hat und das Problem überhaupt parallelisierbar ist, dann ja.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2329572</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329572</guid><dc:creator><![CDATA[otze]]></dc:creator><pubDate>Sun, 09 Jun 2013 11:38:14 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Sun, 09 Jun 2013 11:51:36 GMT]]></title><description><![CDATA[<p>SeppJ schrieb:</p>
<blockquote>
<p><strong>Stefan</strong> schrieb:</p>
<blockquote>
<p>Das ist nur zum testen ob man überhaupt einen Geschwindigkeitszuwachs durch Parallelisierung sieht. Das macht die Zeitmessung einfacher.</p>
</blockquote>
<p>Und verfälscht das Ergebnis extremst. Ob du Aufgaben parallelisierst die jeweils 2-3 Prozessortakte brauchen (die Addition) oder Aufgaben, die 200ms brauchen (sleep) ist ein gewaltiger Unterschied.</p>
</blockquote>
<p>Dann nimm von mir aus an, dass hier riesige Matrizen addiert werden. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f921.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--clown_face"
      title=":clown:"
      alt="🤡"
    /><br />
Wenn das Programm nicht crasht, sieht man sehr schön wie die Laufzeit mit der Anzahl Threads skaliert. Es geht hier mehr darum ein Konzept zu prüfen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2329580</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329580</guid><dc:creator><![CDATA[__Stefan__]]></dc:creator><pubDate>Sun, 09 Jun 2013 11:51:36 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Sun, 09 Jun 2013 11:55:22 GMT]]></title><description><![CDATA[<p>otze schrieb:</p>
<blockquote>
<p><strong>Stefan</strong> schrieb:</p>
<blockquote>
<p>Ein gutes Programm sollte aber alle CPU-Kerne optimal nutzen. Nur so werden Programme heutzutage noch schneller.</p>
</blockquote>
<p>Wenn man weiß was man tut, auf single core schon alles rausgeholt hat und das Problem überhaupt parallelisierbar ist, dann ja.</p>
</blockquote>
<p>Und wenn man dann noch lock-free programmiert.</p>
<p>sleep ist wohl die dümmste Idee um Parallelisierung zu messen. Da sind nämlich 100 Threads auf 1 CPU sogar schneller als 1 overheadfreier Thread auf 1 CPU.</p>
<p>Noch dazu ist der Code von __Stefan__ viel zu lov-level angesetzt. Richtige Parallelisierung erreicht man über Rekursion und mit std::future, denn ein parallelisiertes Programm, das manchmal abstürzt und deadlocks provoziert ist schlechter als ein korrektes unparallelisiertes.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2329583</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329583</guid><dc:creator><![CDATA[schredder]]></dc:creator><pubDate>Sun, 09 Jun 2013 11:55:22 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Sun, 09 Jun 2013 12:04:46 GMT]]></title><description><![CDATA[<p>OpenMP ist hier die Lösung. Alles andere ist zu kompliziert.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2329585</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329585</guid><dc:creator><![CDATA[CSolutionProvider]]></dc:creator><pubDate>Sun, 09 Jun 2013 12:04:46 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Sun, 09 Jun 2013 12:06:48 GMT]]></title><description><![CDATA[<p>schredder schrieb:</p>
<blockquote>
<p>otze schrieb:</p>
<blockquote>
<p><strong>Stefan</strong> schrieb:</p>
<blockquote>
<p>Ein gutes Programm sollte aber alle CPU-Kerne optimal nutzen. Nur so werden Programme heutzutage noch schneller.</p>
</blockquote>
<p>Wenn man weiß was man tut, auf single core schon alles rausgeholt hat und das Problem überhaupt parallelisierbar ist, dann ja.</p>
</blockquote>
<p>Und wenn man dann noch lock-free programmiert.</p>
<p>sleep ist wohl die dümmste Idee um Parallelisierung zu messen. Da sind nämlich 100 Threads auf 1 CPU sogar schneller als 1 overheadfreier Thread auf 1 CPU.</p>
<p>Noch dazu ist der Code von __Stefan__ viel zu lov-level angesetzt. Richtige Parallelisierung erreicht man über Rekursion und mit std::future, denn ein parallelisiertes Programm, das manchmal abstürzt und deadlocks provoziert ist schlechter als ein korrektes unparallelisiertes.</p>
</blockquote>
<p>Wie wäre es mit ein Bisschen konstruktiver Kritik an meinem Code, anstatt sinnleerem gemotze? Hast du konkrete Änderungsvorschläge für die task- und thread_pool klasse, die die Stabilität verbessern könnten?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2329586</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329586</guid><dc:creator><![CDATA[__Stefan__]]></dc:creator><pubDate>Sun, 09 Jun 2013 12:06:48 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Sun, 09 Jun 2013 13:38:34 GMT]]></title><description><![CDATA[<p><strong>Stefan</strong> schrieb:</p>
<blockquote>
<p>Dann nimm von mir aus an, dass hier riesige Matrizen addiert werden. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f921.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--clown_face"
      title=":clown:"
      alt="🤡"
    /></p>
</blockquote>
<p>Dann linkste lieber die OpenMP-Version von ATLAS anstatt das selbst zusammenzustümpern.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2329618</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329618</guid><dc:creator><![CDATA[otze]]></dc:creator><pubDate>Sun, 09 Jun 2013 13:38:34 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Sun, 09 Jun 2013 16:04:22 GMT]]></title><description><![CDATA[<p>otze schrieb:</p>
<blockquote>
<p>Wenn man weiß was man tut, auf single core schon alles rausgeholt hat und das Problem überhaupt parallelisierbar ist, dann ja.</p>
</blockquote>
<p>Das Problem, das er hier lösen möchte (große Mengen an Zahlen akkumulieren) ist sogar &quot;embarrassingly parallel&quot;. Sicherlich gibt es dafür (angefangen vom kleinen Gauß für 1 bis n) andere Methoden, aber er schreibt doch, dass er rumspielt und lernen möchte. Was sollen also diese ganzen demotivierenden Beiträge?</p>
<p>Niemand schreibt, dass der resultierenden Code produktiv eingesetzt werden soll. Von daher sind jegliche Argumente die aufs Ersparen von (Arbeits-/Lern-)Aufwand hinauslaufen unbedeutend. Wenn er etwas lernen will, muss er eben einen gewissen Aufwand betreiben.</p>
<p>Stefan, du solltest mal überprüfen, weshalb dein Programm abstürzt.</p>
<p>Valgrind (auch mit --tool=helgrind und --tool=drd) ist hierbei sehr hilfreich, gibt es aber glaube ich nicht für Windows. Notfalls mal in einer Linux-VM ausprobieren. Hast du eventuell einen GCC 4.8 zur Verfügung? Damit könntest du dein Programm auch mit ThreadSanitizer und/oder AddressSanitizer kompilieren. Beim ersteren handelt es sich um einen bei Google entwickelten Datarace-Detektor. Weiß aber auch nicht, ob die unter Windows funktionieren. Unter Linux wird ein x86-64-System benötigt.</p>
<p>Das sind so die einfachen Ansätze, die dir schnelle Ergebnisse bringen, mit bedeutend weniger Aufwand als bei einem General-Purpose-Debugger wie GDB oder dem Microsoft-Debugger nötig wäre.</p>
<p>Ansonsten kann ich dir zum Lernen für einen Überblick das Perfbook (&quot;Is Parallel Programming Hard, And, If So, What Can You Do About It?) empfehlen. Gibt es <a href="https://www.kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.html" rel="nofollow">hier kostenlos</a>. Ansonsten die üblichen Bücher über Betriebssysteme und Synchronisationsprobleme. Vorsicht bei Beispielcode von irgendwelchen Websites. In diesem Bereich ist der öfter falsch als richtig. &quot;Es funktioniert&quot; ist in der nebenläufigen Programmierung noch weniger ein Zeichen für Korrektheit als bei C und C++ ohnehin schon.</p>
<p>Wenn alles nichts hilft und du nicht weiterkommst, mach eine Pause und guck dir deinen Code danach nochmal in Ruhe an und denke jede Möglichkeit durch. Was anderes wird dir oft nicht bleiben. Dazu musst du natürlich erstmal wissen was zu erwarten ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2329644</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329644</guid><dc:creator><![CDATA[SIGSEGV]]></dc:creator><pubDate>Sun, 09 Jun 2013 16:04:22 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Sun, 09 Jun 2013 17:37:38 GMT]]></title><description><![CDATA[<p>warum löst den jetzt nicht endlich jemand die fehler in seinem konkreten code wenn multithreading doch angeblich so einfach ist <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f644.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_rolling_eyes"
      title=":rolling_eyes:"
      alt="🙄"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2329685</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329685</guid><dc:creator><![CDATA[mt&#x27;ler]]></dc:creator><pubDate>Sun, 09 Jun 2013 17:37:38 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Mon, 10 Jun 2013 06:22:19 GMT]]></title><description><![CDATA[<p>mt'ler schrieb:</p>
<blockquote>
<p>warum löst den jetzt nicht endlich jemand die fehler in seinem konkreten code wenn multithreading doch angeblich so einfach ist <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f644.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_rolling_eyes"
      title=":rolling_eyes:"
      alt="🙄"
    /></p>
</blockquote>
<p>Weil es eben vermutlich doch nicht so einfach ist, und vor allem mit viel Arbeit verbunden.</p>
<p>@TE: Ich kann dir das Buch <a href="http://www.amazon.de/C-Concurrency-Action-Anthony-Williams/dp/1933988770" rel="nofollow">C++ Concurrency in Action</a> empfehlen, in dem auf genau solche Aufgabenstellungen wie deine eingegangen wird. Die Erklaerungen sind sehr ausfuehrlich.</p>
<p>Ansonsten hab ich gerade nicht die Zeit, mir dein Problem genauer anzusehen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2329787</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329787</guid><dc:creator><![CDATA[Kellerautomat]]></dc:creator><pubDate>Mon, 10 Jun 2013 06:22:19 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Mon, 10 Jun 2013 07:33:12 GMT]]></title><description><![CDATA[<p>Der Threadpool läuft jetzt mit std::packaged_task anstatt meiner eigenen Taskklasse. Soweit scheint jetzt alles stabil zu sein. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2329798</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329798</guid><dc:creator><![CDATA[__Stefan__]]></dc:creator><pubDate>Mon, 10 Jun 2013 07:33:12 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Mon, 10 Jun 2013 07:50:08 GMT]]></title><description><![CDATA[<p>Warum nicht einfach futures benutzen anstatt seine eigene Threadklassen zu basteln?</p>
<p>Angenommen, es laufen 8 Threads, wie wird sichergestellt, dass nur einer gleichzeitig diese Variable veraendert (jaja, ints etc. sollen ja atomic sein). Angenommen val ist kein int ...</p>
<pre><code class="language-cpp">if(std::distance(start, end) == 1) 
    { 
        val = *start; 
        std::this_thread::sleep_for(std::chrono::milliseconds(100)); 
        return; 
    }
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2329799</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329799</guid><dc:creator><![CDATA[knivil]]></dc:creator><pubDate>Mon, 10 Jun 2013 07:50:08 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Mon, 10 Jun 2013 07:53:45 GMT]]></title><description><![CDATA[<p>knivil schrieb:</p>
<blockquote>
<p>Warum nicht einfach futures benutzen anstatt seine eigene Threadklassen zu basteln?</p>
</blockquote>
<p>Ich hatte eben gedacht, ich kann das auch <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /><br />
Jetzt verwende ich ja packaged_task zusammen mit future. Es erfordert etwas mehr Tipparbeit bei der Verwendung, aber zumindest läuft es sauber.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2329806</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329806</guid><dc:creator><![CDATA[__Stefan__]]></dc:creator><pubDate>Mon, 10 Jun 2013 07:53:45 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Mon, 10 Jun 2013 08:05:00 GMT]]></title><description><![CDATA[<blockquote>
<p>aber zumindest läuft es sauber.</p>
</blockquote>
<p>Nein, tut es nicht, weil du mit sum einen shared state hast, dessen Zugriff nicht synchronisiert ist (eigentlich).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2329812</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329812</guid><dc:creator><![CDATA[knivil]]></dc:creator><pubDate>Mon, 10 Jun 2013 08:05:00 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Mon, 10 Jun 2013 08:12:10 GMT]]></title><description><![CDATA[<p>knivil schrieb:</p>
<blockquote>
<p>Warum nicht einfach futures benutzen anstatt seine eigene Threadklassen zu basteln?</p>
<p>Angenommen, es laufen 8 Threads, wie wird sichergestellt, dass nur einer gleichzeitig diese Variable veraendert (jaja, ints etc. sollen ja atomic sein). Angenommen val ist kein int ...</p>
<pre><code class="language-cpp">if(std::distance(start, end) == 1) 
    { 
        val = *start; 
        std::this_thread::sleep_for(std::chrono::milliseconds(100)); 
        return; 
    }
</code></pre>
</blockquote>
<p>Ich habs mal kommentiert. Ansonsten bitte nicht den Sinn des Algos hinterfragen. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<pre><code>template&lt;class Iter, class T&gt; 
void accumulate(Iter start, Iter end, T&amp; val, thread_pool&amp; tp) 
{ 
    if(start == end) return; 

    if(std::distance(start, end) == 1) 
    { 
        val = *start; 
        std::this_thread::sleep_for(std::chrono::milliseconds(100)); 
        return; 
    } 

    if(std::distance(start, end) == 2) 
    { 
        val = 0; 
        val += *start++; 
        val += *start; 
        std::this_thread::sleep_for(std::chrono::milliseconds(200)); 
        return; 
    } 

    Iter mid = start; 
    std::advance(mid, std::distance(start, end) / 2); 

// Temporäre objekte für rekursive Aufrufe
    T a = 0, b = 0; 
// range wird in zwei Teile geteilt, rekursiver Aufruf von accumulate für beide
// Teile.
// rekursiver Aufruf 1. Hälfte von Range. Threaded wenn thread verfügbar.
    task t(accumulate&lt;Iter, T&gt;, start, mid, std::ref(a), std::ref(tp)); 
    tp.run(t); 
// rekursiver Aufruf 2. Hälfte von Range.
    accumulate(mid, end, b, tp); 

    t.wait(); 

    val = a + b; 
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2329818</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329818</guid><dc:creator><![CDATA[__Stefan__]]></dc:creator><pubDate>Mon, 10 Jun 2013 08:12:10 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Mon, 10 Jun 2013 08:21:54 GMT]]></title><description><![CDATA[<blockquote>
<p>Es erfordert etwas mehr Tipparbeit bei der Verwendung</p>
</blockquote>
<p>Nicht bei mir. So haette ich es gemacht (quick and dirty), keine extra Klassen fuer Task, Threadpool etc:</p>
<pre><code class="language-cpp">#include &lt;algorithm&gt;
#include &lt;numeric&gt;
#include &lt;thread&gt;
#include &lt;future&gt;
#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;chrono&gt;

template&lt;typename T&gt;
int acc(T start, T end)
{
    int sum = 0;
    for(auto it = start; it != end; ++it)
    {
        sum += *it;
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
    return sum;

    //return std::accumulate(start, end, 0);
}

template&lt;typename T&gt;
int para_acc(T start, T end, int split_count)
{
    //return acc(start, end);
    if (split_count != 0)
    {
        auto mid = start + std::distance(start, end)/2;
        auto v1 = std::async(para_acc&lt;T&gt;, start, mid, split_count-1);
        auto v2 = std::async(para_acc&lt;T&gt;, mid, end, split_count-1);
        return v1.get() + v2.get();
    }
    else
        return acc(start, end);
}

int _tmain(int argc, _TCHAR* argv[])
{
    std::vector&lt;int&gt; vec(100,1);
    std::cerr &lt;&lt; para_acc(vec.begin(), vec.end(), 3) &lt;&lt; '\n';
    return 0;
}
</code></pre>
<pre><code class="language-cpp">// Temporäre objekte für rekursive Aufrufe 
    T a = 0, b = 0;
</code></pre>
<p>Diese Zeile habe ich wohl uebersehen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2329823</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329823</guid><dc:creator><![CDATA[knivil]]></dc:creator><pubDate>Mon, 10 Jun 2013 08:21:54 GMT</pubDate></item><item><title><![CDATA[Reply to threading Problem on Mon, 10 Jun 2013 08:54:38 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/21632">@knivil</a></p>
<p>Weshalb verwendest du überhaupt Rekursion? Du gibst ja die die Threadanzahl durch split_count direkt vor: n = 2^split_count.<br />
Ausserdem erzugst du so Threads, die nichts machen ausser zu warten, abgesehen davon dass Threaderzeugung einen Overhead hat, den man mit Pools vermeiden kann.</p>
<p>Ich will 1 Thread pro CPU-Kern haben, nicht mehr, und die sollen immer schön gefüttert werden.</p>
<p>Dann musst du bedenken, dass die Abarbeitung eines sub-ranges schneller gehen kann als die eines anderen, das heisst Workerthreads können frei werden, während der Algo läuft. Der Algorithmus soll den frei werdenden Worker an anderer Stelle verwenden können.</p>
<p>Wenn man async verwendet, sollte man das so machen, ansonsten geht die Parallelität möglicherweise flöten:</p>
<pre><code>std::async(std::launch::async, ...);
</code></pre>
<p>Übrigens läuft dein Algo nur mit random access Iteratoren.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2329849</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2329849</guid><dc:creator><![CDATA[__Stefan__]]></dc:creator><pubDate>Mon, 10 Jun 2013 08:54:38 GMT</pubDate></item></channel></rss>