Вы должны понимать, что переменные, поступающие из внешней области, которые объявлены private
, работают так, как если бы они были локально объявлены без инициализатора . Таким образом, каждая локальная копия является пустым вектором, поэтому ваш код не может работать.
Как правило, с OpenMP лучше объявлять закрытые переменные локально - таким образом вы избежите путаницы между «внешним значением» и «внутренними частными значениями», которые вообще не связаны. Вы можете сделать это, разделив директивы parallel
и for
.
#pragma omp parallel
{
std::vector<std::vector<int>> v;
v.resize(3);
#pragma omp for
for(int i = 0; i < 10; i++){
v[1].push_back(i);
}
}
Обратите внимание, что v
недоступен после параллельной области - это хорошо! В вашем исходном примере v
доступен после параллельной области - но это значение не имеет ничего общего со значением из потоков внутри.
Если вам нужно сохранить информацию из v
, вы можете посмотреть на сокращение, но это зависит от вашего конкретного варианта использования.
Ваш подход myVector[omp_get_thread_num()]
общий наивный подход. Этот код правильный , но в любом случае, когда вы изменяете значения самого внешнего вектора , он имеет плохую производительность из-за ложного совместного использования.
myVector[omp_get_thread_num()].push_back(); // Bad performance
myVector[omp_get_thread_num()][1].push_back(i); // Ok
Так что, как правило, желательно не делать этого и использовать вместо этого объявленные локально переменные. Тем не менее, если ваш код вылетает, значит что-то не так. В этом случае вам нужно подготовить минимальный воспроизводимый пример и задать второй вопрос (ссылаясь на это).
Теперь threadprivate
- это нечто иное, чем private
. private
обычно является тем, что вы хотите, и относится к конкретной задаче / области. В большинстве случаев вам не нужно или не нужно threadprivate
.