Эффективный способ организовать используемые и неиспользуемые элементы в большом параллельном массиве - PullRequest
2 голосов
/ 16 января 2011

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

В настоящее время ElementManager использует Intel TBB concurrent_bounded_queue с именем mAllAvailableElements. Существует также другой контейнер (TBB concurrent_vector), который содержит все элементы независимо от того, доступны ли они для использования или нет, который называется mAllElements. Класс A запрашивает следующий доступный элемент, менеджер пытается извлечь следующий доступный элемент из очереди. Выскочивший элемент сейчас используется.

Теперь, когда класс A сделал то, что должен, управление передается классу B, который теперь должен перебирать все элементы in use и создавать сетки (чтобы использовать преимущества параллелизма , массив разбивается на несколько меньших массивов для создания подсетей, которые масштабируются в зависимости от количества доступных потоков - причина этого заключается в том, что создание сетки должно выполняться последовательно) . Для этого я в настоящее время перебираю контейнер mAllElements (это также одновременно) и собираю любой элемент, который используется . Элементы, как упоминалось выше, содержат многоугольную информацию для создания сеток. Итерация в этом случае занимает много времени, так как она должна проверять каждый элемент и запрашивать, используется ли он или нет, потому что, если он не используется , то он не должен быть частью сетки.

Теперь представьте, что только 1 миллион из возможных 18 миллионов элементов был в использовании (но более 5-6 миллионов было переработано). Что еще хуже, из-за постоянных обновлений только части сетки (что происходит одновременно) означает, что используемые элементы фрагментированы по всему контейнеру mAllElements.

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

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

1 Ответ

0 голосов
/ 16 января 2011

Как насчет использования битового вектора, чтобы указать, какие из ваших элементов используются?Его легко разделить для параллельной обработки при построении полной сетки, и вы можете использовать атомарные операции над словами в векторе и, таким образом, избежать блокировок.

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