Суть кода - для каждого объекта формируется список соседних, надо создать список пар с этим объектом и найденными соседями, потом это всё объединить в общий список пар. Функция поиска соседей очень медленная и я захотел вызывать её многопоточно, но итоговый список всего один и я не знаю как сделать в него быструю и безопасную вставку.
Код упрощённо:
// collision_pairs - unordered_map<Entity*, Entity*>
// entitys - std::vector<Entity*>
/* найти ближайших соседей и создать
списки пар для проверки пересечений хитбоксов */
#pragma omp parallel for \
schedule(dynamic) \
shared(root, collision_pairs)
for (auto entity: entitys) {
...
Vector<Entity*> list
/* очень тяжёлая функция, которая работает разное
количество времени и вернёт список соседних объектов в list*/
root->find(area, list)
// добавить этих соседей в пары на проверки
for (auto other: list) {
auto addr_a = entity
auto addr_b = other
// сами себя не проверяем
continue_if (addr_a == addr_b)
// эта перестановка сократит число одинаковых пар
if (addr_b > addr_a)
std::swap(addr_a, addr_b)
#pragma omp critical(dataupdate)
collision_pairs.emplace( {addr_a, addr_b} )
}
}
Было бы лучше создать для каждого потока свою локальную копию collision_pairs, а потом объединить её с релизной, но не думаю что в omp есть такая прагма ( shared(collision_pairs) здесь не помогает, нужна синхронизация, а private(collision_pairs) создаст локальные копии, но они в конце не объединятся).