2014-05-09 2 views
1

Я использую boost::thread_group для управления своими темами. Дизайн был таким образом, что каждый поток в группе потоков вызывает последовательность функторов структуры A.Поведение объекта в многопоточном

псевдокод:

struct A { 
    int n; 
    vector p; 

    void operator()() { 
     for(number_of_steps) // Do computations involving members n, p, x and y. 
    } 
private: 
    float x; 
    vector y; 
}; 

struct parallel_A : boost::thread_group { 
    parallel_A(const A* a) : m_a(a) { 
     for(number_of_cpu) { 
      create_thread(inner_struct(this)); 
     } 
    } 

    void run() { 
     (*m_a)(); 
    } 
private: 
    struct inner_struct { 
     parallel_A* a; 

     inner_struct(parallel_A* _a) : a(_a) {} 

     void operator()() { 
      a->run(); 
     } 
    } 
    const A* m_a; 
} 

Мой вопрос:

  1. Будут ли переменные данные n, p, x и y и вычисление в объекте A, быть перемежаются по потокам?

  2. Если бы мы должны были идти дальше, имея больше вызовов для функтора A для каждого процессора, например, 1 потока 1 CPU и для каждой нити более 4 вызова функтора A делать вычисление, каким будет поведение условия состояния переменных и вычисление A?

ответ

0
  1. на основе кода:

    for(number_of_cpu) { 
        create_thread(inner_struct(this)); 
    

    то же значение this указатель будет передан всем потокам и таким образом потоки будут одни и те же n, p, x и y переменные данных. Вычисления A будут чередоваться в любом случае (за исключением, возможно, критических разделов), но теперь, поскольку вычисления имеют одни и те же переменные данных, весьма вероятно, что в одном вычислении будут использоваться промежуточные значения, предназначенные для другого вычисления, приводящего к повреждению данных.

    Я предлагаю использовать некоторую форму локального хранилища потоков либо путем определения массива объектов A, и/или с использованием формального механизма, такого как boost::thread_specific_ptr.

  2. Если нитовое локальное хранилище не используется (т. Е. Приведенный выше код поддерживается как таковой), добавление дополнительных указаний на функтор A увеличит вероятность повреждения данных.

    Если используется поточное локальное хранилище, поскольку инструкции по-прежнему выполняются последовательно в потоке, добавление еще 4 вызовов функтора A в каждом потоке будет означать, что вычисление займет примерно в 5 раз. Это предполагает, что в каждом потоке не создаются подпотоки для обработки дополнительных вызовов.

Смежные вопросы