OpenMP и STL-вектор

У меня есть код, для которого я хотел бы использовать OpenMP следующим образом:

std::vector<int> v(1000);
# pragma omp parallel for
for (int i = 0; i < 1000; ++i) {
    v[i] = i;
}

Я читал, что векторный контейнер STL не является потокобезопасным в ситуации, когда несколько потоков записываются в один контейнер, что подразумевает, что мне нужно будет заблокировать вектор перед записью; однако мне также сказали, что операция записи выше как-то "атомарна", и поэтому условия гонки не выше. Может ли кто-нибудь прояснить это?

Ответ 1

В этом конкретном примере это будет безопасно.

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

Обратите внимание, что вы можете законно сделать это:

std::vector<int> v(1000);
int *ptr = &v[0];

# pragma omp parallel for
for (int i = 0; i < 1000; ++i) {
    ptr[i] = i;
}

Он становится небезопасным при запуске вызова таких методов, как push_back(), pop_back(), insert() и т.д. из нескольких потоков.

Я также добавлю, что этот конкретный пример не подходит для parallelism, так как вряд ли удастся выполнить какую-либо работу. Но я предполагаю, что это просто ошарашенный пример с целью задать этот вопрос.

Ответ 2

Несколько чтения являются безопасными, но я бы рекомендовал избегать нескольких операций записи в один и тот же контейнер. Но вы можете писать в память, которую вы управляете самостоятельно. Разница с вектором заключается в том, что вы можете быть уверены, что память не будет изменена или перераспределена одновременно. В противном случае вы также можете использовать семафор, но это, вероятно, снизит эффективность, и если вы используете несколько, это может даже вызвать взаимоблокировки, если вы не работаете должным образом.