Определенно.
Большая проблема с распараллеливанием этих проблем перестановки заключается в том, что для того, чтобы правильно распараллелить, вам нужно «проиндексировать» произвольную перестановку. Короче говоря, вам нужно найти k-ю перестановку. Вы можете воспользоваться некоторыми интересными математическими свойствами, и вы найдете это:
std::vector<int> kth_perm(long long k, std::vector<int> V) {
long long int index;
long long int next;
std::vector<int> new_v;
while(V.size()) {
index = k/fact(V.size() - 1);
new_v.push_back(V.at(index));
next = k % fact(V.size() - 1);
V.erase(V.begin() + index);
k = next;
}
return new_v;
}
Итак ваша логика может выглядеть примерно так:
long long int start = (numperms*threadnum)/ numthreads;
long long int end = threadnum == numthreads-1 ? numperms : (numperms*(threadnum+1))/numthreads;
perm = kth_perm(start, perm); // perm is your list of permutations
for (int j = start; j < end; ++j){
if (is_valid_tour(adj_list, perm, startingVertex, endingVertex)) {
isValidTour=true;
return perm;
}
std::next_permutation(perm.begin(),perm.end());
}
isValidTour = false;
return perm;
Очевидно, что есть много кода, но идея распараллеливать его можно захватить небольшим кодом, который я опубликовал. Вы можете визуализировать «индексацию», как это:
|--------------------------------|
^ ^ ^
t1 t2 ... tn
Найти ю перестановку и пусть нить вызов std::next_permutation
до тех пор, пока не найдет начальную точку следующего потока.
Обратите внимание, что вы хотите, чтобы обернуть функцию, которая содержит нижний код #pragma omp parallel
Большое спасибо! Теперь он отлично работает, я узнал больше об OpenMP от вашего ответа и ответа на вопрос, чем в течение 1,5-часовой лекции в моем Uni. – Siemko