Pergunta

Antecedentes: Estou escrevendo um programa em C ++ trabalhar com grandes quantidades de dados geográficos, e desejo para carregar grandes pedaços de processo em um único movimento. Sou obrigado a trabalhar com um aplicativo compilado para máquinas de 32 bits. A máquina que eu estou testando em está executando um sistema operacional de 64 bits (Windows 7) e tem 6 giga de ram. Usando MS VS 2008.

Eu tenho o seguinte código:

byte* pTempBuffer2[3];
try
{
    //size_t nBufSize = nBandBytes*m_nBandCount;
    pTempBuffer2[0] = new byte[nBandBytes];
    pTempBuffer2[1] = new byte[nBandBytes];
    pTempBuffer2[2] = new byte[nBandBytes];
}
catch (std::bad_alloc)
{
    // If we didn't get the memory just don't buffer and we will get data one
    // piece at a time.
    return;
}

Eu estava esperando que eu seria capaz de alocar a memória até que o aplicativo atingiu o limite de 4 gigabytes de 32 bits de endereçamento. No entanto, quando nBandBytes é 466.560.000 a nova lança std :: bad_alloc na segunda tentativa. Nesta fase, o valor do conjunto de trabalho (memória) para o processo é 665.232 K Então, eu não parecem ser capazes de obter até mesmo um giga de memória alocada.

Tem havido alguma menção de um limite de 2 giga para aplicações em 32 bits do Windows que pode ser estendido para 3 show com a opção / 3GB para win32. Este é um bom conselho sob esse ambiente, mas não é relevante para este caso.

Quanto memória você deve ser capaz de alocar sob o sistema operacional de 64 bits com uma aplicação de 32 bits?

Foi útil?

Solução

Por mais que o OS quer lhe dar. Por padrão, o Windows permite que um processo de 32 bits tem 2 GB de espaço de endereço. E este é dividido em vários pedaços. Uma área é reservada para a pilha, outros para cada executável e DLL que é carregada. O que resta pode ser alocada dinamicamente, mas não há nenhuma garantia de que ele vai ser um grande bloco contíguo. Pode haver vários pequenos pedaços de um par de centenas de MB cada.

Se você compilar com a bandeira LARGEADDRESSAWARE, 64-bit Windows permitirá que você use o espaço de endereço de 4GB completo, que deve ajudar um pouco, mas em geral,

  • Você não deve presumir que a memória disponível é contíguo. Você deve ser capaz de trabalhar com múltiplas alocações menores em vez de alguns grandes, e
  • Você deve compilá-lo como um aplicativo de 64 bits, se você precisa de uma grande quantidade de memória.

Outras dicas

no Windows de 32 bits, o processo normal pode levar 2 GB no máximo, mas com / 3GB ligá-lo pode chegar a 3 GB (para Windows 2003).

mas no seu caso eu acho que você está alocando memória contígua, e assim a exceção ocorreu.

Você pode alocar mais memória do que o seu arquivo de página vai deixar você - mesmo sem a opção / 3GB, você pode alocar 4 GB de memória sem muita dificuldade.

Leia este artigo para uma boa visão geral de como pensar em memória física, memória virtual e espaço de endereço (todos os três são coisas diferentes). Em poucas palavras, você tem exatamente a quantidade de memória física que você tenha RAM, mas a sua aplicação tem realmente nenhuma interação com que a memória física em tudo - é apenas um local conveniente para armazenar os dados que em sua memória virtual. Sua memória virtual é limitado pelo tamanho do seu arquivo de paginação e da quantidade seu aplicativo pode usar é limitado por quanto outros aplicativos estão usando (embora você pode alocar mais, proporcionando-lhe realmente não usá-lo). Seu espaço de endereço no mundo dos 32 bits é de 4 GB. Destes, 2 GB são alocados para o kernel (ou 1GB se você usar a opção / 3BG). Do 2GB, que ficaram, alguns vai ser usado pelo seu stack, alguns pelo programa que está em execução no momento, (e todas as DLLs, etc ..). Vai ficar fragmentado, e você só vai ser capaz de obter tanto espaço contíguo - este é o lugar onde sua alocação está falhando. Mas, uma vez que o espaço de endereço é apenas uma maneira conveniente de acessar a memória virtual que você reservou para você, é possível alocar mais memória, e trazer pedaços dele em seu espaço de endereços de um pouco de cada vez.

Raymond Chen tem um exemplo de como para alocar 4 GB de memória e mapa de parte dela em uma seção do seu espaço de endereço.

Em Windows de 32 bits, o allocatable máxima é de 16 TB e 256TB em 64 bits do Windows.

E se você está realmente em como funciona o gerenciamento de memória no Windows, leia este artigo .

Durante o projeto ElephantsDream a Fundação Blender com o Blender 3D teve problemas semelhantes (embora no Mac). não pode incluir o link, mas google:. blender3d problema de alocação de memória e será o primeiro item

A solução de mapeamento de arquivos envolvidos. Não tentei isso sozinho, mas você pode ler sobre ele aqui: http://msdn.microsoft.com/en-us/library/aa366556 (VS.85) .aspx

Com nBandBytes em 466560000, você está tentando alocar 1,4 GB. Um aplicativo de 32 bits normalmente só tem acesso a 2 GB de memória (mais se você arrancar com / 3 GB eo executável é marcado como espaço de endereço grande ciente). Você pode ter dificuldade para descobrir que muitos blocos de espaço de endereçamento contíguo para os seus grandes blocos de memória.

Se você deseja alocar gigabytes de memória em um SO de 64 bits, use um processo de 64 bits.

Você deve ser capaz de alocar um total de cerca de 2 GB por processo. Este artigo (PDF) explica os detalhes. No entanto, você provavelmente não será capaz de obter um único bloco, contígua que está sequer perto de tão grande.

Mesmo se você alocar em pedaços menores, você não poderia obter a memória que você precisa, especialmente se o programa circundante tem comportamento da memória imprevisível, ou se você precisa para rodar em diferentes sistemas operacionais. Na minha experiência, o espaço de pilha em um processo de 32 bits tampas em torno de 1.2GB.

Neste quantidade de memória, eu recomendaria manualmente gravar no disco. Enrole suas matrizes em uma classe que gerencia a memória e grava arquivos temporários quando necessário. Esperemos que as características de seu programa são tais que você poderia efetivamente peças de cache de que os dados sem bater o disco muito.

Sysinternals VMMap é ótimo para investigar endereço espaço fragmentação virtual, que provavelmente está limitando a quantidade de contíguo memória que você pode alocar. Eu recomendo definindo-o para exibir o espaço livre, então a classificação por tamanho para encontrar as maiores áreas livres, em seguida, classificar por endereço para ver o que está separando as maiores áreas livres (DLLs provavelmente rebased, regiões de memória compartilhada, ou outros amontoados).

Evitando extremamente grandes alocações contíguos é provavelmente para o melhor, como já foi sugerido.

Configuração LARGE_ADDRESS_AWARE=YES (como jalf sugerido) é bom, desde que as bibliotecas que a sua aplicação depende são compatíveis com ele. Se você fizer isso, você deve testar seu código com o AllocationPreference registro conjunto de chaves para ativar top-down de alocação de endereço virtual.

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