Как упомянуто в комментариях, сокращение предполагает, что операция ассоциативна и коммутативна.Значения могут быть вычислены в любом порядке и «накоплены» посредством любых частичных результатов, и конечный результат будет таким же.
Нет гарантии, что цикл OpenMP for будет распределять непрерывные итерации для каждого потокаесли расписание цикла явно не запрашивает это.Также нет гарантии, что непрерывные блоки будут распределены путем увеличения номера потока (т. Е. Поток № 0 может пройти итерации 1000–1999, а поток № 1 - 0–999).Если вам нужно такое поведение, вы должны определить свое собственное расписание.
Что-то вроде:
int N=1000;
std::string globalString("initial value");
#pragma omp parallel shared(N,stringType)
{
std::string localString; //Empty string
// Set schedule
int iterTo, iterFrom;
iterFrom = omp_get_thread_num() * (N / omp_get_num_threads());
if (omp_get_num_threads() == omp_get_thread_num()+1)
iterTo = N;
else
iterTo = (1+omp_get_thread_num()) * (N / omp_get_num_threads());
// Loop - concatenate a number of neighboring values in the right order
// No #pragma omp for: each thread goes through the loop, but loop
// boundaries change according to the thread ID
for (int ii=iterTo; ii<iterTo ; ii++){
localString += get_some_string(ii);
}
// Dirty trick to concatenate strings from all threads in the good order
for (int ii=0;ii<omp_get_num_threads();ii++){
#pragma omp barrier
if (ii==omp_get_thread_num())
globalString += localString;
}
}
Лучшим способом было бы иметь общий массив std::string
, каждый поток используетодин как местный аккумулятор.В конце один поток может выполнить конкатенационную часть (и избежать подвоха и всех его чрезмерных вызовов barrier
).