Я написал программу на C ++, которая имитирует определенный процесс, который я изучаю. Он выводит дискретные «состояния» на каждом временном шаге симуляции. Например:
a
b
c
b
c
b
будет выводом симуляционного прогона с начальным условием (заданным мной или сгенерированным случайным образом) и b & c будет состояниями, между которыми система продолжает колебаться.
Я хотел бы объединить многие из этих прогонов в цепочку Маркова, чтобы она превратилась в граф со следующими вершинами и ребрами. (Желательно во время выполнения, потому что сохранение выходных данных сначала занимает много места на диске.) Число в скобках указывает, сколько раз встречалась определенная вершина или ребро, так что это также должно быть сохранено.
Vertices: a(1), b(3) and c(2).
Edges: a->b(1), b->c(2), c->b(2).
Реальные состояния содержат 112 бит информации, и я генерирую миллиарды таких переходов. Проблема в том, что я не нашел библиотеку графов или программу для эффективной и быстрой генерации цепочки Маркова. Я играл с:
Я только что заполнил «График разреженных хеш-кодов Google», но оказалось, что на полпути он работает очень медленно. Примерно через день (использование памяти превышает 20 ГБ, что само по себе не является проблемой, поскольку их намного больше), оно замедляется и занимает около трех недель.
У меня есть доступ к компьютерам с 12 или 16 ядрами и 256 или 512 ГБ памяти, и я чувствую, что они должны работать.
Поскольку я не обученный программист и пишу код довольно медленно, я ищу некоторую информацию, прежде чем потратить много времени на работу над другим несовершенным решением.
Я надеюсь, что смог прояснить мою проблему. Заранее спасибо за любую мудрость или ответы.
РЕДАКТИРОВАТЬ:
Основываясь на вопросах и ответах в комментариях, я думаю, что мой вопрос должен был быть таким: какова подходящая быстрая матричная библиотека для C ++?
Вы смотрели на boost :: numeric :: ublas? Он имеет разреженную матрицу-член, которая дает вам матричный доступ, но вместо построения массива NxN в памяти хранит список ребер на узел.
Так что, если N это число узлов вместо NxN
массив в памяти вы храните Nx30
-avg количество ребер на узел-
Однако даже если предположить, что вы можете использовать один байт для подсчета повторения ребер, у вас все еще есть 600M узлов со списком из 30 ребер.
запись списка — это имя ребра uint32, а содержимое — как минимум 1 байт. поэтому минимум 150 байтов для списка. который выходит на минимум 90 ГБ в памяти. вероятно, выше, потому что в списке есть издержки на элемент.
Если вы можете хранить все это в памяти без загрузки операционной системой данных на диск, то нет никаких причин, по которым она не должна работать быстро. Конечно, возможно, что упорядоченная карта выполнит hash_map. Это зависит от реализации и используемой хэш-функции.
Наивно std::map<uint32, std::map<uint32, unint8>>
Если дерево сбалансировано, длина большого дерева составляет 30, а маленькое — крошечное. Так что доступ не должен занимать целую вечность. Вполне возможно, что hash_map будет работать лучше для столбцов, но не точно: hash_map<uint32, std::map<uint32, unint8>>
(карта разреженных хэшей Google настроена на память, а не на скорость, и карта столбцов будет очень большой, что, вероятно, делает ее плохо подходящей)
Наконец, вы должны рассмотреть возможность хранения этой информации на диске, а не в памяти. Фактически вы можете использовать внешнюю службу данных, такую как БД с таблицей для каждого узла (NodeId, NumOfHits) и таблицей для ребра (NodeId, NodeId, NumOfHits) {это представление занимает гораздо больше места}
Я бы попробовал что-то вроде Cassandra, которое может управлять диском и кешем памяти для вас и может легко масштабироваться для нескольких компьютеров. И вам не нужно накладывать расходы на сложные модели транзакций и т. Д.
Других решений пока нет …