У меня довольно большой проект, и я захожу в тупик. Я хотел посмотреть, есть ли у великого сообщества какие-либо предложения.
У меня большой набор данных, и я пытаюсь построить социальный график. Данные содержат более 9,5 миллионов отображений координат в значение Short. Для значений ключа в ConcurrentHashMap я использую строку, то есть координаты, объединенные с ',' между ними.
По сути, я нахожу общее количество групп между пользователями. У меня есть начальная хэш-карта, которая создается довольно легко, которая сопоставляет GroupID с вектором AvatarID. Эта часть работает нормально. Затем у меня есть 12 потоков, которые отвечают за собственный набор GroupID и обработку (добавление + 1 к количеству пользователей в каждом groupID), причем весь доступ осуществляется из ConcurrentHashMap.
После обработки около 8000 групп возникает проблема с доступом. Только один поток за раз кажется активным, и я не уверен, что это из-за огромного размера или другого фактора. Это проблема, поскольку у меня есть 300 000 групп, которые должны быть обработаны в общей сложности (и своевременно).
Есть ли какой-нибудь совет относительно того, как я это реализую, и какие ярлыки я могу использовать? Чтение и запись, на мой взгляд, одинаково важны, поскольку я должен прочитать координату, если значение существует (если не создать его), а затем добавить ее к значению и записать обратно.
Я готов предоставить код по мере необходимости, я просто не знаю, какие части будут иметь отношение к обсуждению.
Спасибо за ваше время,
-mojavestorm
Дальнейшее объяснение:
Две реализации и их ограничения:
1) У меня есть предварительная карта HashMap (Integer, Vector (Integer)), которая содержит GroupID в качестве ключа и вектор userID. Потоки разделяют групповые идентификаторы между собой и, используя каждый возвращенный вектор (целое число), каждый поток сохраняет короткое значение в соответствии с координатой (говоря, что UserID x и UserID y принадлежат (коротким) n группам вместе) в TLongShortHashMap threadMap и каждый поток имеет свой собственный ThreadMap. Координаты отображаются в длинные значения. После завершения каждого потока значения соответствующих ключей в каждой из нитокMap добавляются к одному и тому же ключу в комбинированной карте, которая покажет, как много групп UserID x и UserID y принадлежат друг другу во всей системе.
Проблема с этой реализацией состоит в том, что между потоками существует сильное перекрытие, поэтому создаются чрезмерные короткие значения. Например, Пользователь 1 и Пользователь 2 принадлежат к различным группам вместе. Поток A и Поток B отвечают за свой собственный диапазон групп, включая принадлежащие Пользователю 1 и Пользователю 2, поэтому как Поток A, так и Поток B сохраняют в своей копии threadMap длинное значение для координаты (1, 2) и короткое значение. Если происходит чрезмерное перекрытие, тогда требования к памяти могут быть невыполненными. В моем случае все 46 ГБ ОЗУ, которые я выделяю для Java, израсходованы, и тоже довольно быстро.
2) Используя тот же preMap в этой реализации, каждому потоку присваивается диапазон пользовательских координат, за которые он отвечает. Каждый поток выполняется и получает каждую имеющуюся у него координату и выполняет итерацию по preMap, проверяя каждый groupID и проверяя, принадлежат ли UserID x и UserID y к вектору, возвращенному из preMap. Эта реализация устраняет наложение, которое произойдет между threadMaps.
Проблема с этим - время. Прямо сейчас программа работает с потрясающей скоростью 1400 лет, чтобы закончить. Объем используемой памяти колеблется от 4 до 15 ГБ, но, похоже, остается «низким». Не совсем уверен, что он будет оставаться в рамках, однако, я думаю, что это будет. Для меня нет очевидных улучшений.
Надеюсь, эти описания понятны и помогут понять мою проблему. Спасибо.