Contar subsequências em centenas de GB de dados

Estou tentando processar um arquivo muito grande e contabilizar a frequência de todas as seqüências de um determinado tamanho no arquivo.

Para ilustrar o que estou fazendo, considere um pequeno arquivo de entrada contendo a sequênciaabcdefabcgbacbdebdbbcaebfebfebfeb

Abaixo, o código lê o arquivo inteiro e pega a primeira substring de comprimento n (abaixo eu defino isso como 5, embora eu queira poder mudar isso) e conta sua frequência:

abcde => 1

Na próxima linha, ele move um caractere para a direita e faz o mesmo:

bcdef => 1

Em seguida, continua pelo restante da string e imprime as 5 sequências mais frequentes:

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

No entanto, gostaria de encontrar uma maneira mais eficiente de conseguir isso. Se o arquivo de entrada tiver 10 GB ou 1000 GB, a leitura da coisa toda em uma string custará muito memória.

Pensei em ler em blocos de caracteres, digamos 100 de cada vez e procedendo como acima, mas aqui, as seqüências que abrangem 2 blocos não seriam computadas corretamente.

Minha idéia, então, é ler apenas n número de caracteres da string e, em seguida, passar para o próximo n número de caracteres e fazer o mesmo, calculando sua frequência em um hash, como acima.

Existem sugestões sobre como eu poderia fazer isso? Eu dei uma olhadaler usando um deslocamento, mas não consigo entender como eu poderia incorporar isso aquiÉsubstr a ferramenta mais eficiente em memória para esta tarefa?

questionAnswers(4)

yourAnswerToTheQuestion