Фон
Я работаю над проектом, требующим значительных вычислительных ресурсов для проекта по компьютерной лингвистике, но у меня есть довольно общая проблема, и поэтому я ожидаю, что решение будет интересно и другим.
Требования
Ключевым аспектом этой конкретной программы, которую я должен написать, является то, что она должна:
- Прочитать большой корпус (между 5G и 30G, и потенциально более крупный материал по линии)
- Обработка данных в каждой строке.
- Из этих обработанных данных построить большое количество векторов (размерность некоторых из этих векторов составляет> 4 000 000). Обычно он строит сотни тысяч таких векторов.
- Все эти векторы должны быть сохранены на диск в том или ином формате.
Шаги 1 и 2 нетрудно выполнить эффективно: просто используйте генераторы и используйте конвейер анализа данных. Большая проблема - операция 3 (и при соединении 4)
Скобки: технические данные
В случае, если фактическая процедура построения векторов влияет на решение:
Для каждой строки в корпусе один или несколько векторов должны обновлять свои базовые веса.
Если вы рассматриваете их в терминах списков Python, каждая строка при обработке обновляет один или несколько списков (создавая их при необходимости), увеличивая значения этих списков на один или несколько индексов на значение (которое может отличаться) на основе индекса).
Векторы не зависят друг от друга и не имеет значения, в каком порядке считываются линии корпуса.
Попытки решения
Есть три крайности, когда это нужно сделать:
- Я мог бы построить все векторы в памяти. Затем запишите их на диск.
- Я мог бы построить все векторы прямо на диске, используя полку рассола или какую-нибудь такую библиотеку.
- Я мог бы строить векторы в памяти по одному и записывать их на диск, проходя через корпус один раз за вектор.
Все эти варианты довольно сложны. 1 просто использует всю системную память, и он паникует и замедляется к ползанию. 2 слишком медленный, поскольку операции ввода-вывода не быстрые. 3, возможно, даже медленнее, чем 2 по тем же причинам.
* 1052 1053 ** * Цель * 1054 1055 * **
Хорошее решение будет включать:
- Построение в памяти как можно больше.
- Когда память заполнится, выгрузите все на диск.
- Если биты снова нужны с диска, восстановите их в памяти, чтобы добавить данные в эти векторы.
- Вернитесь к 1, пока все векторы не будут построены.
Проблема в том, что я не совсем уверен, как это сделать. Кажется, что немного беспомощно беспокоиться о системных атрибутах, таких как ОЗУ, но я не понимаю, как подобного рода проблемы могут быть оптимально решены без учета этого. В результате я не знаю, как начать работать с такими вещами.
Вопрос
Кто-нибудь знает, как решить эту проблему? Я питон просто не подходящий язык для такого рода вещей? Или существует простое решение, позволяющее максимизировать, сколько делается из памяти (в пределах разумного), и минимизировать, сколько раз данные должны считываться с диска или записываться на него?
Большое спасибо за ваше внимание. Я с нетерпением жду возможности увидеть, что яркие умы от stackoverflow могут бросить мой путь.
Дополнительные детали
Тип машины, на которой работает эта проблема, обычно имеет 20+ ядер и ~ 70 ГБ ОЗУ. Проблема может быть распараллелена (как MapReduce) в том, что отдельные векторы для одного объекта могут быть построены из сегментов корпуса, а затем добавлены, чтобы получить вектор, который был бы построен из всего корпуса.
Часть вопроса включает определение предела того, сколько памяти может быть встроено в память до того, как должна произойти запись на диск. Предлагает ли python какой-либо механизм для определения объема доступной оперативной памяти?