Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > [boost::thread] Параллельность выполнения


Автор: borisbn 15.10.2011, 10:15
Добрый день.
Набросал наипростейшую программку с сабжем и ... не работает ( памагите smile )
Код

class Worker
{
public:
    static void s_thread_f( Worker * who, int value, int maxN ) {
        who->thread_f( value, maxN );
    }
    void print() {
        for ( auto i = m_storage.begin(); i != m_storage.end(); ++i ) {
            std::cout << (*i) << " ";
        }
    }
private:
    void thread_f( int value, int maxN ) {
        for ( int i = 0; i < maxN; i++ ) {
            m_mutex.lock();
            m_storage.push_back( value );
            m_mutex.unlock();
        }
    }

    boost::mutex m_mutex;

typedef std::vector< int > storage_t;
    storage_t m_storage;
};

int main()
{
    Worker worker;
    boost::thread thread1( Worker::s_thread_f, &worker, -42, 42 );
    boost::thread thread2( Worker::s_thread_f, &worker, 42, 42 );
    thread1.join();
    thread2.join();
    worker.print();
}

вывод
Цитата
42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 42 -42 -42 
-42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42 -42
-42 -42 -42

http://liveworkspace.org/code/753152e3115e9af41788468135f2c606
Почему не в перемешку ?
Пробовал не 42 раза добавлять, а 500 - рез-т тот же.
Спасибо.

Автор: azesmcar 15.10.2011, 10:48
borisbn

Во первых элементов слишком мало (даже 500-а может не хватить), чтобы что-то почувствовать, скорее всего первый поток уже завершен, когда второй начинает работать.
Во вторых это зависит и от планировщика задач, возможно поток просто не получает управление.
Поставь барьер на входе и добавь boost::this_thread::yield().

Код

#include <boost/thread.hpp>
#include <boost/thread/barrier.hpp>
#include <iostream>

class Worker
{
public:
    void print()
   {
        for ( auto i = m_storage.begin(); i != m_storage.end(); ++i ) {
            std::cout << (*i) << " ";
        }
    }
    void thread_proc(int value, int maxN, int id) {
      boost::barrier meet_point(2);
        for ( int i = 0; i < maxN; i++ )
      {
            m.lock();
            m_storage.push_back(value);
            m.unlock();
         boost::this_thread::yield();
        }
    }
private:
   boost::mutex m;
   typedef std::vector< int > storage_t;
    storage_t m_storage;
};
int main()
{
    Worker worker;
    boost::thread thread1(&Worker::thread_proc, &worker, 0, 500, 0);
    boost::thread thread2(&Worker::thread_proc, &worker, 1, 500, 1);
    thread1.join();
    thread2.join();
    worker.print();
}

http://liveworkspace.org/code/f6daba84b38a1328a15813f0a0499dca

Автор: borisbn 15.10.2011, 11:31
Цитата(azesmcar @  15.10.2011,  10:48 Найти цитируемый пост)
добавь boost::this_thread::yield()

о! точно. сработало. спасибо.
а вот это
Цитата(azesmcar @  15.10.2011,  10:48 Найти цитируемый пост)
Поставь барьер на входе

не понял зачем... убрал - работает так же, как и без него.

Автор: azesmcar 15.10.2011, 12:56
Цитата(borisbn @  15.10.2011,  11:31 Найти цитируемый пост)
не понял зачем... убрал - работает так же, как и без него. 

На всякий случай, чтобы потоки дождались друг друга.

Автор: ecspertiza 15.10.2011, 16:39
Я может что то из буста подзабыл, но на мой взгляд проблема в 

Код

thread1.join();
thread2.join();


ты сначала дожидаешься выполнения одного потока потом второго, вот они по очереди и работают.

Автор: math64 15.10.2011, 19:15
Нет, не в этом - без yield();  никто не хочет отдавать процессор, кто его забрал - тот и работает. На двухядерной машине потоки могли бы работать действительно одновременно. 

Автор: azesmcar 15.10.2011, 21:14
Цитата(ecspertiza @  15.10.2011,  16:39 Найти цитируемый пост)
ты сначала дожидаешься выполнения одного потока потом второго, вот они по очереди и работают. 

Дожидается основной поток, а остальные два работают (их там три).
Цитата(math64 @  15.10.2011,  19:15 Найти цитируемый пост)
никто не хочет отдавать процессор, кто его забрал - тот и работает

А его никто не спрашивает чего он там хочет smile это планировщик решает и выделяет время каждому потоку. В данном случае у потоков одинаковый приоритет. В самой задаче yield() естественно не нужен, я привел пример лишь для того, чтобы объяснить причину такого поведения.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)