Подсчет подпоследовательностей в сотнях ГБ данных

Я пытаюсь обработать очень большой файл и подсчитать частоту всех последовательностей определенной длины в файле.

Чтобы проиллюстрировать, что я делаю, рассмотрим небольшой входной файл, содержащий последовательностьabcdefabcgbacbdebdbbcaebfebfebfeb

Ниже код считывает весь файл и получает первую подстроку длины n (ниже я установил это значение на 5, хотя я хочу иметь возможность изменить это) и подсчитывает его частоту:

abcde => 1

Следующая строка перемещает один символ вправо и делает то же самое:

bcdef => 1

Затем он продолжается для остальной части строки и печатает 5 наиболее часто встречающихся последовательностей:

open my $in, '<', 'in.txt' or die $!; # 'abcdefabcgbacbdebdbbcaebfebfebfeb'

my $seq = <$in>; # read whole file into string
my $len = length($seq);

my $seq_length = 5; # set k-mer length
my %data;

for (my $i = 0; $i <= $len - $seq_length; $i++) {
     my $kmer = substr($seq, $i, $seq_length);
     $data{$kmer}++;
}

# print the hash, showing only the 5 most frequent k-mers
my $count = 0;
foreach my $kmer (sort { $data{$b} <=> $data{$a} } keys %data ){
    print "$kmer $data{$kmer}\n";
    $count++;
    last if $count >= 5;
}
ebfeb 3
febfe 2
bfebf 2
bcaeb 1
abcgb 1

Однако я хотел бы найти более эффективный способ достижения этого. Если входной файл был 10 ГБ или 1000 ГБ, тогда чтение всего этого в строку было бы очень дорогостоящим.

Я думал о чтении по блокам символов, скажем, по 100 за раз, и продолжал, как описано выше, но здесь последовательности, охватывающие 2 блока, не будут правильно подсчитаны.

Моя идея тогда состоит в том, чтобы читать только n символов из строки, а затем переходить к следующему n символам и делать то же самое, подсчитывая их частоту в хэше, как указано выше.

Есть какие-нибудь предложения о том, как я мог это сделать? Я посмотрелчитать используя смещение, но не могу понять, как я могу включить это здесьЯвляетсяsubstr самый эффективный инструмент памяти для этой задачи?

Ответы на вопрос(4)

Ваш ответ на вопрос