Я новичок в использовании OpenMP 2.0 вместе с MSVC++ 2017. Я работаю с большой структурой данных (обозначенной как bigMap), поэтому мне нужно распределять рабочую нагрузку при итерации наилучшим возможным способом. Моя попытка сделать это:
std::map<int, std::set<std::pair<double, double>>> bigMap;
///thousands of values are added here
int k;
int max_threads = omp_get_max_threads();
omp_set_num_threads(max_threads);
#pragma omp parallel default(none) private(k)
{
#pragma omp for
for(k = kMax; k > kMin; k--)
{
for (auto& myPair : bigMap[k])
{
int pthread = omp_get_thread_num();
std::cout << "Thread " << pthread << std::endl;
for (auto& item : myPair)
{
#pragma omp critical
myMap[k-1].insert(std::make_pair(item, 0));
}
}
}
Вывод для "pthread" всегда равен "0", а время выполнения такое же, как и для одиночного потока (поэтому я предполагаю, что новые потоки не создаются).
Почему этот код не работает и какой omp Директивы <7> / пункты / Разделы <4593510783>
ОБНОВЛЕНИЕ: OMP теперь работает, но приведенный ниже код работает не так, как ожидалось: Я ожидаю, что 3 элемента из bigMap[1] будут вставлены во все записи bigMap, вместо этого они вставлены только один раз, для bigMap[2], почему??#pragma omp parallel for schedule(static,1)
for (int i = 0; i < map_size; ++i) {
#pragma omp critical
bigMap[i] = std::set<int>();
}
bigMap[1] = { 10, 100, 1000 };
int i;
#pragma omp parallel for schedule(static) num_threads(8)
for (i = thread_num; i < map_size; i += thread_count)
{
for (auto it = bigMap[i].begin(); it != bigMap[i].end(); ++it)
{
int elem = *it;
bigMap[i + 1].insert(elem);
}
}
Вы пробовали тот же код под clang или gcc? На данный момент я бы с осторожностью относился к реализации MSVC. Он старый, и М.С. об этом необычно молчит даже для них.
std::cout будет сериализован, и вы сериализовали внутренний цикл, добавив критический, так что вы не можете ожидать параллельного ускорения. Если бы вы изменили направление внешнего omp, не было бы причин, по которым Microsoft OpenMP должен отставать (хотя он не обновлялся с VS2005).
@zzxyz, я этого не делал, потому что для этого я привязан к MSVC, в противном случае я был бы рад использовать материалы, доступные для версий OMP> 3, такие как задачи и пользовательские сокращения. Поэтому я должен выяснить, как заставить его работать на MSVC...
@ tim18 Я не заметил, что std::cout будет сериализован, но на самом деле это так, даже если он добавлен только для проверки. Что касается реверсирования внешнего omp для , я не понял вашей точки зрения, вы имеете в виду, что если я реверсирую его обратно, он будет работать лучше? Спасибо
У MS есть собственная библиотека. Я бы, вероятно, использовал это для MS и использовал последнюю версию для всего остального. parallel_for и еще много чего на стороне MS. Тем не менее, может быть что-то не так с вашим кодом, который я пропустил.
@zzxyz Сначала я попробовал библиотеку параллелизма Microsoft <ppl.h>, но она у меня не работает, потому что я создаю внутреннюю библиотеку CLR («параллелизм не поддерживается при компиляции с /clr»). Удивительно, но OMP работает с /clr (MS запрещает использование PPL, но разрешает OMP...). Теперь OMP работает, но не так, как хотелось бы, я обновил свой вопрос текущим кодом.