Расширяя ответ от @Ramade:
Проблемный кусок кода:
for (int i = 0; i < n - 1; i++)
{
int min_index = i;
#pragma omp parallel // start OpenMP parallel code block
for (int j = i + 1; j < n; j++)
if (temp[j] < temp[min_index])
min_index = j;
std::swap(temp[i], temp[min_index]); // std swap method
}
Что вам нужно:
a #pragma omp for
для фактического распределения внутреннего цикла
некоторая схема сокращения, чтобы каждый поток не обращался к общей переменной [min_index]
и, желательно, избегать порождения новых потоков на каждой итерации самого внешнего цикла, чтобы уменьшить издержки openmp
Например:
omp_set_num_threads(num_th); // set threads number
// Spawn all threads once
int min_index_all=0;
int min_value_all=INT_MAX;
#pragma omp parallel shared(temp,min_index_all,min_value_all)
{
//these are private variables
int min_index,min_value;
for (int i = 0; i < n - 1; i++)
min_index = i;
min_value = temp[min_index];
// OpenMP distributed loop
// nowait because once the loop is complete the thread can do the reduction part immediately
// static schedule because we don't expect a large unbalance of workload between threads
#pragma omp parallel schedule(static) nowait
for (int j = i + 1; j < n; j++)
if (temp[j] < temp[min_index]){
min_index = j;
min_value = temp[min_index];
}
// reduction part in a critical section
#pragma omp critical
{
if (min_value<min_value_all){
min_index_all = min_index;
min_value_all = min_value;
}
}
// explicit barrier: wait for all threads to have finished the reduction
#pragma omp barrier
// swap done by a single thread
// + initialization of shared variables for next iteration
#pragma omp single
{
std::swap(temp[i], temp[min_index]); // std swap method
min_index_all = i+1;
min_value_all = INT_MAX;
}
// implicit barrier after omp single
// all threads will wait there until the single section is done
// then they will move together to next iteration of the outer loop
}// end for i loop
}
Тем не менее, цикл, который вы пытаетесь распараллелить, очень прост и, вероятно, будет работать очень эффективно в одном потоке до больших значений n
(для которых сортировка выбора не будет эффективным алгоритмом). Распараллеливание OpenMP приносит некоторые накладные расходы и будет проблемой, если существует всего несколько итераций внутреннего цикла.
Возможно, вам придется разделить внешний цикл так, чтобы использовался параллельный код, если имеется много итераций внутреннего цикла, и последовательный, если существует только несколько итераций.
#define SOME_VALUE 20000 // To be tweaked
int i;
for (i = 0; i < n - 1 - SOME_VALUE; i++){
//parallel version of the code
}
i = (n - 1 - SOME_VALUE < 0) ? 0 : n-1-SOME_VALUE;
for (; i < n - 1; i++){
// finish with a serial version of the code
}