gawk не хватает памяти при просмотре больших файлов: могу ли я оптимизировать свой код?

Я использую gawk для просмотра большого текстового корпуса (около 3-4 ГБ, сборник электронных книг), чтобы распечатать каждую ассоциацию из 3 слов, которые встречаются не менее 3 раз, для получения лингвистической статистики. Вот код:

содержимое файла .awk:

BEGIN { RS="[^[:alnum:]]+" } 

{ w1 = w2; w2 = w3; w3 = $0 } 

NR > 2 { count[tolower(w1 " " w2 " " w3)]++ } 

END { 
     for (phrase in count) {
         if (count[phrase] >= 3) { 
             print phrase, count[phrase] 
         } 
     } 
} 

команда: gawk -f file.awk mytxtfile > вывод

Он отлично работает с небольшими файлами (несколько сотен МБ), но я не могу заставить его работать с файлами размером более 1 ГБ: gawk съедает всю мою оперативную память (8 ГБ) менее чем за минуту, затем начинает есть мой своп и всю систему. в итоге замерзает.

Знаете ли вы, как я мог бы оптимизировать код, даже если в конечном итоге это заняло бы гораздо больше времени?

Большое тебе спасибо


person bobylapointe    schedule 25.06.2012    source источник
comment
в то время как решение для всех gawk было бы элегантным, возможно, конвейеры unix могут вам помочь, то есть awk '{print all 3 wrd sets}' | sort | uniq -c | awk '$1>2{print}' или подобное. Удачи.   -  person shellter    schedule 26.06.2012
comment
Другой подход заключается в том, чтобы хранить ключи в базе данных, поэтому вам не нужно хранить их в памяти. Однако это выходит за рамки того, что вы можете удобно сделать с помощью awk; но, возможно, переход к, например. Python не был бы непреодолимым усложнением.   -  person tripleee    schedule 26.06.2012
comment
Неплохая идея, попробую, спасибо Шелтер   -  person bobylapointe    schedule 26.06.2012
comment
Спасибо, Tripleee, я посмотрю на это   -  person bobylapointe    schedule 26.06.2012
comment
bobylapointe, прошу вас опубликовать образец Input_file и ожидаемый результат. Я почти уверен, что мы могли бы помочь больше, увидев это.   -  person RavinderSingh13    schedule 23.12.2016
comment
Может, вместо этого попробовать более легкий mawk? Я считаю, что единственное изменение, которое потребуется вашему коду, это RS="[^a-zA-Z0-9]+". Скорее всего, это сработает только в том случае, если вы чуть превысили лимит памяти, но это, по крайней мере, очень легко проверить. (Кроме того, я очень сомневаюсь, что sort будет работать, учитывая этот размер.)   -  person Adam Katz    schedule 18.09.2018


Ответы (2)


Пока вам нужно сохранять информацию до самого конца, ваша потребность в памяти составляет O(количество упорядоченных комбинаций из трех слов) примерно 200 000 слов означает 8 000 000 000 000 000 комбинаций...

Даже если общий словарный запас ваших книг намного меньше — скажем, всего 50 тысяч слов — это все равно 50 тысяч ^ 3 или 1,25 * 10 ^ 14. Затем, даже если ваша реализация awk использует только 16 байтов на запись (невозможно), это все равно 2 000 000 000 000 000 байтов или 2000 ТБ.

Это наихудший сценарий, но вы видите, с какими порядками величин вы играете.

Может быть, вам не нужно, чтобы слова-сочетания были упорядочены? В этом случае вы уменьшите количество элементов массива в 6 раз, сначала отсортировав слова. Но я сомневаюсь, что это поможет вам либо...

person Mikhail T.    schedule 01.11.2018

Ваше решение не очень эффективно с точки зрения строк: оно выделяет по одной для каждой уникальной триграммы, а в большом корпусе их много. Вместо этого вы можете создать таблицу с индексами дерева и выполнить count[w1][w2][w3]++. Это требует немного больше работы в конце, но теперь есть только одна строка для каждого уникального токена.

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

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

Блин, отвечаю на вопрос шестилетней давности.

person Community    schedule 20.05.2019