2015-10-07 2 views
0

Я немного запутался в следующем случае относительно контейнеров STL в C++. Такие операции, как push_back (.), Небезопасны для потоковой передачи, но в противном случае я думаю, что могут использоваться контейнеры STL.OpenMP Nested For Loop с контейнерами STL

std::vector<int> global_vector; 

#pragma omp parallel for 
for (int i = 0; i < height; i++) 
{ 
for(std::vector<int>::iterator it = fvec.begin(); it != fvec.end(); it++) 
{ 
    // process here with some push_back into global_vector 
    global_vector.push_back(/*SOMETHING*/); 
} 
} 

Глядя на приведенный выше код только Outter для петли параллельно, так что я интересно, будет толчок назад во внутренней цикл влияет делает нить небезопасно.

+0

[c-openmp-parallel-for-loop-alternatives-to-stdvector] (http://stackoverflow.com/questions/18669296/c-openmp-parallel-for-loop-alternatives-to-stdvector/18671256 # 18671256) –

ответ

1

Ответ, безусловно, ДА, код, такой как сейчас, является поточно-опасным.

Причина этого заключается в том, что push_back() зависит от внутреннего состояния вектора и изменяет его состояние между потоками для изменения этого внутреннего состояния. Чтобы сделать код безопасным для потоков, вам нужно убедиться, что никаких параллельных вызовов этого метода никогда не произойдет.

Это, вероятно, может быть приведено в исполнение таким образом:

std::vector<int> global_vector; 

#pragma omp parallel for 
for (int i = 0; i < height; i++) { 
    for(std::vector<int>::iterator it = fvec.begin(); it != fvec.end(); it++) { 
     // process here with some push_back into global_vector 
     #pragma omp critical 
     global_vector.push_back(/*SOMETHING*/); 
    } 
} 

Однако, этот код будет просто катастрофой в перспективе параллельной эффективности, поскольку все доступы будет сериализовать, с также добавляет много накладных расходов для управления замки. Поэтому просто забывайте о таком подходе.

Однако вы можете заранее вычислить размер конечного вектора, а также индексы, которые вы действительно хотите получить, и использовать только функции доступа без атак, а также для непересекающихся подмножеств индексов. Это будет соответствовать global_vector[i] = /*SOMETHING*/; вместо вашего global_vector.push_back(/*SOMETHING*/);, так как вы знаете, что диапазоны для каждой строки i индексы не пересекаются.