Pergunta

Meu objetivo é garantir que uma matriz alocada em java é alocado em memória física contígua.O problema que eu tenho é que as páginas de uma matriz é alocado em que tendem a não ser contíguos na memória física, a menos que eu alocar realmente uma grande matriz.

Minhas perguntas são:

  • Por que faz realmente um grande matriz de garantir páginas que são contíguos na memória física?
  • Existe alguma maneira de garantir uma matriz é alocado em memória física, que não envolvem a matriz realmente grande?
  • Como posso saber qual a página ou do endereço físico de um objeto Java/matriz existe, sem medição de acertos do cache/cache misses?

Eu não estou à procura de respostas, se perguntando porque eu estou fazendo isso em java.Eu entendo que o " C " iria "resolver o meu problema", e que eu estou indo contra a natureza fundamental do java.No entanto, eu tenho uma boa razão para fazer isso.

As respostas não precisam ser garantidos para trabalhar o tempo todo.Estou procurando por respostas que trabalham a maior parte do tempo.Pontos extras para os criativos, out-of-the-box respostas que não razoável programador Java jamais iria escrever.É OK para ser específico de plataforma(x86 de 32-bits, 64-bits).

Foi útil?

Solução

Dado que o coletor de lixo move objetos na memória (lógica), acho que você ficará sem sorte.

Sobre o melhor que você pode fazer é usar BYTEBUFFER.ALLOCATEDIRECT. Isso (normalmente) não será movido pela memória (lógica) pelo GC, mas pode ser movida na memória física ou até mesmo no disco. Se você quiser garantir melhor, terá que acertar o sistema operacional.

Dito isto, se você puder definir o tamanho da página para ser tão grande quanto a sua pilha, todas as matrizes serão necessariamente fisicamente contíguas (ou trocadas).

Outras dicas

Não. A memória fisicamente contígua requer interação direta com o sistema operacional. Na maioria dos aplicativos, a JVM incluiu apenas endereços praticamente contíguos. E uma JVM não pode dar a você o que não recebe do sistema operacional.

Além disso, por que você quer? Se você estiver configurando transferências de DMA, provavelmente está usando técnicas além do Java de qualquer maneira.

Um pouco de fundo:

A memória física em um PC moderno é tipicamente uma quantidade flexível, em módulos DIMM substituíveis. Cada byte possui um endereço físico, portanto, o sistema operacional durante a inicialização determina quais endereços físicos estão disponíveis. Acontece que os aplicativos estão melhor ao não usar esses endereços diretamente. Em vez disso, todas as CPUs modernas (e seus caches) usam endereços virtuais. Há uma tabela de mapeamento para endereços físicos, mas isso não precisa ser completo - a troca para o disco é ativada pelo uso de endereços virtuais não mapeados para endereços físicos. Outro nível de flexibilidade é obtido com uma tabela por processo, com mapeamentos incompletos. Se o processo A tiver um endereço virtual que mapas para o endereço físico X, mas o processo B não, não há como o processo que B possa escrever no endereço físico X, e podemos considerar que a memória é exclusiva para processar A. Obviamente Para que isso seja seguro, o sistema operacional precisa proteger o acesso à mesa de mapeamento, mas todos os oses modernos.

A tabela de mapeamento funciona no nível da página. Uma página ou subconjunto contíguo de endereços físicos é mapeado para um subconjunto contíguo de endereços virtuais. A troca entre as despesas gerais e granularidade resultou em páginas de 4 KB sendo um tamanho de página comum. Mas, como cada página tem seu próprio mapeamento, não se pode assumir a contiguidade além do tamanho da página. Em particular, quando as páginas são despejadas da memória física, trocadas para o disco e restauradas, é bem possível que o acabamento em um novo endereço de memória física. O programa não percebe, pois o endereço virtual não muda, apenas a tabela de mapeamento gerenciada pelo OS faz.

Eu pensaria que você gostaria de usar Sun.java.unsfe.

Pode haver maneiras de enganar uma JVM específica para fazer o que você deseja, mas provavelmente seriam frágeis, complicados e provavelmente muito específicos para a JVM, sua versão, o sistema operacional em que ele funciona etc. Em outras palavras, desperdiçará o esforço.

Portanto, sem saber mais sobre o seu problema, acho que ninguém poderá ajudar. Certamente não há como fazer isso em Java em geral, no máximo em uma JVM específica.

Para sugerir uma alternativa:

Se você realmente precisa armazenar dados em memória contígua, por que não fazê -lo em uma pequena biblioteca C e chamar isso via JNI?

Como eu vê-lo.Você ainda tem que explicar por que

  • que matrizes primitivos não são contínuas na memória.Eu não vejo por que não seria contínuo, em memória virtual.c.f.Matrizes de Objeto são susceptíveis de ter seus Objetos contínua na memória)
  • uma matriz que não é contínua na memória física (RAM i.e.Memória de Acesso aleatório) teria uma diferença significativa de desempenho.exemplo:diferença mensurável no desempenho de sua aplicação.

Qual a sua parece é que você está realmente procurando por um baixo nível de forma a alocar matrizes, porque você está acostumado a fazer isso em C, e o desempenho é um pedido de uma necessidade de fazer isso.

BTW:Acessando ByteBuffer.allocateDirect() com dizer getDouble()/putDouble() pode ser mais lenta do que usando apenas um double[] como o primeiro envolve chamadas JNI e o último pode ser otimizados para não chamar a todos.

A razão pela qual ele é usado para troca de dados entre o Java e o C espaços.exemplo:NIO chamadas.Ele só funciona bem quando lê/escreve são mantidos a um mínimo.Caso contrário, você é melhor fora de usar algo em Java espaço.

i.e.A menos que você esteja claro o que você está fazendo e por você está fazendo isso, você pode acabar com uma solução que pode fazer você se sentir melhor, mas, na verdade, é mais complicado e com desempenho pior do que o simples solução.

Observação esta resposta a uma pergunta relacionada, que discute o sistema.IdentityHashCode () e a identificação do endereço de memória do objeto. A linha inferior é que você pode usar a implementação padrão de matriz hashcode () para identificar o endereço de memória original da matriz (sujeito a ajuste em um Int/32 bits)

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