Pergunta

OK, por isso estou escrevendo um programa que infelizmente precisa usar uma enorme estrutura de dados para concluir seu trabalho, mas está falhando com um "erro fora da memória" durante sua inicialização. Embora eu entenda completamente o que isso significa e por que é um problema, estou tendo problemas para superá -lo, já que meu programa precisa usar essa grande estrutura e não conheço outra maneira de armazená -lo.

O programa primeiro indexa um grande corpus de arquivos de texto que eu forneço. Isso funciona bem.

Em seguida, ele usa esse índice para inicializar uma grande matriz 2D. Essa matriz terá entradas N², onde "n" é o número de palavras únicas no corpus do texto. Para o pedaço relativamente pequeno, estou testando -o (cerca de 60 arquivos), ele precisa fazer aproximadamente 30.000x30.000 entradas. Provavelmente isso será maior quando eu o executar no meu corpus completo também.

Ele falha sempre sempre, depois de indexar, enquanto inicializa a estrutura de dados (a ser trabalhada posteriormente).

As coisas que fiz incluem:

  • renovar meu código para usar um primitivo int[] em vez de um TreeMap
  • eliminar estruturas redundantes, etc ...
  • Além disso, eu administrei o programa com-Xmx2g Para maximizar minha memória alocada

Estou bastante confiante de que não será uma linha simples de solução de código, mas provavelmente exigirá uma abordagem muito nova. Estou procurando qual é essa abordagem, alguma idéia?

Obrigado, B.

Foi útil?

Solução

Parece (fazer algumas suposições sobre o que você está usando sua matriz) a maioria das entradas será 0. Se sim, considere usar um matriz esparsa representação.

Se você realmente tenho que muitas entradas (sua matriz atual está em algum lugar Mais de 3 gigabytes já, mesmo assumindo sem sobrecarga), você terá que usar algum tipo de armazenamento no disco ou um sistema de carga/descarga preguiçoso.

Outras dicas

Existem várias causas de problemas fora da memória.

Em primeiro lugar, o caso mais simples é que você simplesmente precisa de mais heap. Você está usando uma pilha máxima de 512m quando seu programa puder operar corretamente com 2G. O aumento é com -Xmx2048m Como uma opção JVM e você está bem. Também esteja ciente do que as VMs de 64 bits usarão até o dobro da memória de VMs de 32 bits, dependendo da composição desses dados.

Se o seu problema não for tão simples, você pode observar a otimização. Substituindo objetos por primitivos e assim por diante. Isso pode ser uma opção. Eu realmente não posso dizer com base no que você postou.

Em última análise, porém, você chega a uma estrada cruzada onde você deve fazer uma escolha entre virtulização e partição.

Virtualizando Nesse contexto, significa simplesmente alguma forma de fingir que há mais memória do que existe. Os sistemas operacionais usam isso com espaços de endereço virtuais e usando o espaço do disco rígido como memória extra. Isso pode significar apenas manter parte da estrutura de dados na memória por vez e persistir no restante do armazenamento secundário (por exemplo, arquivo ou banco de dados).

Partição está dividindo seus dados em vários servidores (real ou virtual). Por exemplo, se você estivesse acompanhando as negociações de ações no NASDAQ, poderá colocar códigos de estoque começando com "A" no servidor1, "B" no Server2, etc. Você precisa encontrar uma abordagem razoável para cortar seus dados, de modo que reduza ou eliminar a necessidade de comunicação cruzada porque essa comunicação cruzada é o que limita sua escalabilidade.

Caso tão simples, se o que você está armazenando é de 30 mil palavras e combinações de 30k x 30k de palavras, você pode dividi -lo em quatro servidores:

  • Am x am
  • Am X NZ
  • NZ X Am
  • NZ X NZ

Essa é apenas uma ideia. Novamente, é difícil o toque sem conhecer detalhes.

Este é um problema comum que lida com grandes conjuntos de dados. Você pode otimizar o quanto quiser, mas a memória nunca será suficiente (provavelmente) e, assim que o conjunto de dados crescer um pouco mais, você ainda será fumado. A solução mais escalável é simplesmente manter menos na memória, trabalhar em pedaços e persistir a estrutura no disco (banco de dados/arquivo).

Se você não precisar de 32 bits completos (tamanho de número inteiro) para cada valor em sua matriz 2D, talvez um tipo menor, como um byte, faria o truque? Além disso, você deve dar o máximo de espaço possível - 2 GB ainda é relativamente pequeno para um sistema moderno. A RAM é barata, especialmente se você espera fazer muito processamento na memória.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top