Параллельная вставка на карту - PullRequest
0 голосов
/ 15 января 2019

Я хотел создать карту, описывающую пары целых векторов целых чисел. Моя цель - сделать это параллельно. Чтобы убедиться, что я не пытаюсь одновременно push_back к одному и тому же объекту памяти (несколькими потоками), вторая координата пар ключей карты отвечает за текущий номер потока. Однако я столкнулся с проблемами. Кажется, что некоторые значения вставляются неправильно. Вместо того, чтобы собрать все 10 значений, я получаю всегда меньше (иногда 9, иногда 8, 6 и т. Д.)

map<pair<int, int>, vector<int> > test;
#pragma omp parallel num_threads(8)
{
    #pragma omp for
    for (int i = 0;i < 10;i++)
    {
        test[make_pair(i % 3, omp_get_thread_num())].push_back(i);
    }
}

Я также попробовал test.at(make_pair(i % 3, omp_get_thread_num())).push_back(i), и это тоже не сработало. Однако в этом случае выполнение прерывается с исключением.

Я думал, что #pragma omp for распределяет цикл for в непоследовательные подпоследовательности (0, ..., 9), чтобы не было проблем с моим кодом ... Я немного запутался. Может ли кто-нибудь объяснить мне эту проблему?

Ответы [ 2 ]

0 голосов
/ 15 января 2019

Как уже говорилось, контейнеры стандартной библиотеки не являются поточно-ориентированными. Подходящим решением для этого случая является инициализация n-карт (по одной для каждого потока), а затем их объединение в конце.

Как указывалось ранее, использование мьютекса (и обеспечение безопасного доступа к карте) будет правильным решением, однако это также приведет к снижению производительности. Поскольку каждый раз, когда к карте будет осуществляться доступ, каждому потоку придется ждать, пока мьютекс разблокирует данные.

Следует отметить, что размер 10 недостаточен для того, чтобы многопоточность стоила того, поскольку использование нескольких потоков здесь, скорее всего, приведет к снижению производительности.

map<pair<int, int>, vector<int> > test[8];
#pragma omp parallel num_threads(8)
{
    #pragma omp for
    for (int i = 0;i < large_number; i++)
    {
        int thread_id = omp_get_thread_id();
        test[thread_id][make_pair(i % 3, omp_get_thread_num())].push_back(i);
    }
}
#pragma omp barrier 

map<pair<int,int>, vector<int>> combined; 
for (int i = 0; i < 8; ++i) 
    combined.insert(test[i].begin(), test[i].end());
0 голосов
/ 15 января 2019

Это потому, что карта не является поточно-ориентированной (и не является вектором, но эта часть не является резьбовой). Вы должны добавить мьютекс, использовать контейнеры без блокировки или сначала подготовить карту.

В этом случае начните с одной темы, создав все свои записи.

#pragma omp single
for (int i = 0;i < 3;++i)
{
for (int j = 0;i < 8;++j)
{
    test.insert(make_pair(make_pair(i, j), vector<int>()));
}
}

Затем проведите параллель для (добавьте барьер).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...