Pregunta

Mi objetivo es asegurar que una matriz asignada en Java se asigne a través de la memoria física contigua. El problema con el que me he encontrado es que las páginas a las que se asigna una matriz tienden a no ser contiguas en la memoria física, a menos que asigne una matriz realmente grande.

Mis preguntas son:

  • ¿Por qué una matriz realmente grande garantiza páginas que son contiguas en la memoria física?
  • ¿Hay alguna manera de garantizar que una matriz se asigne a través de la memoria física, que no implique hacer que la matriz sea realmente grande?
  • ¿Cómo puedo saber en qué página o dirección física existe un objeto / matriz Java, sin medir los aciertos / errores de caché?

No estoy buscando respuestas preguntando por qué estoy haciendo esto en Java. Entiendo que C "resolvería mi problema" y que voy en contra de la naturaleza fundamental de Java. Sin embargo, tengo una buena razón para hacerlo.

No es necesario garantizar que las respuestas funcionen todo el tiempo. Estoy buscando respuestas que funcionen la mayor parte del tiempo. Puntos adicionales para respuestas creativas y listas para usar que ningún programador razonable de Java jamás escribiría. Está bien ser específico de la plataforma (x86 de 32 bits y 64 bits).

¿Fue útil?

Solución

Dado que el recolector de basura mueve objetos en la memoria (lógica), creo que no tendrá suerte.

Lo mejor que puede hacer es usar ByteBuffer.allocateDirect . Eso (por lo general) no se moverá alrededor de la memoria (lógica) por el GC, pero puede moverse en la memoria física o incluso paginarse en el disco. Si desea mejores garantías, tendrá que acceder al sistema operativo.

Dicho esto, si puede configurar el tamaño de página para que sea tan grande como su montón, entonces todas las matrices serán necesariamente contiguas físicamente (o intercambiadas).

Otros consejos

No. La memoria físicamente contigua requiere interacción directa con el sistema operativo. La mayoría de las aplicaciones, JVM incluidas, solo obtienen direcciones prácticamente contiguas. Y una JVM no puede darle lo que no obtiene del sistema operativo.

Además, ¿por qué lo quieres? Si está configurando transferencias DMA, probablemente esté utilizando técnicas además de Java de todos modos.

Fondo:

La memoria física en una PC moderna es típicamente una cantidad flexible, en módulos DIMM reemplazables. Cada byte tiene una dirección física, por lo que el sistema operativo durante el arranque determina qué direcciones físicas están disponibles. Resulta que las aplicaciones están mejor al no usar estas direcciones directamente. En cambio, todas las CPU modernas (y sus cachés) usan direcciones virtuales. Hay una tabla de mapeo a las direcciones físicas, pero no es necesario que esté completa: el intercambio en el disco se habilita mediante el uso de direcciones virtuales no asignadas a direcciones físicas. Se obtiene otro nivel de flexibilidad al tener una tabla por proceso, con asignaciones incompletas. Si el proceso A tiene una dirección virtual que se asigna a la dirección física X, pero el proceso B no, entonces no hay forma de que el proceso B pueda escribir en la dirección física X, y podemos considerar que esa memoria es exclusiva para el proceso A. Obviamente Para que esto sea seguro, el sistema operativo debe proteger el acceso a la tabla de mapeo, pero todos los sistemas operativos modernos lo hacen.

La tabla de mapeo funciona a nivel de página. Una página o un subconjunto contiguo de direcciones físicas se asigna a un subconjunto contiguo de direcciones virtuales. La compensación entre gastos generales y granularidad ha dado como resultado que las páginas de 4KB sean un tamaño de página común. Pero como cada página tiene su propia asignación, no se puede asumir una contigüidad más allá de ese tamaño de página. En particular, cuando las páginas son expulsadas de la memoria física, intercambiadas en el disco y restauradas, es muy posible que terminen en una nueva dirección de memoria física. El programa no se da cuenta, ya que la dirección virtual no cambia, solo lo hace la tabla de mapeo administrada por el sistema operativo.

Creo que desearía utilizar sun.java. inseguro .

Puede haber formas de engañar a una JVM específica para que haga lo que desea, pero probablemente sean frágiles, complicadas y muy probablemente muy específicas de la JVM, su versión, el sistema operativo en el que se ejecuta, etc. En otras palabras, esfuerzo desperdiciado .

Entonces, sin saber más sobre su problema, no creo que nadie pueda ayudarlo. Ciertamente no hay forma de hacerlo en Java en general, a lo sumo en una JVM específica.

Para sugerir una alternativa:

Si realmente necesita almacenar datos en memoria contigua, ¿por qué no hacerlo en una pequeña biblioteca C y llamar a través de JNI?

Como yo lo veo. Todavía tiene que explicar por qué

  • que las matrices primitivas no son continuas en la memoria. No veo por qué no serían continuos en la memoria virtual. (c.f. Las matrices de objetos es poco probable que tengan sus objetos continuos en la memoria)
  • una matriz que no es continua en la memoria física (RAM, es decir, memoria de acceso aleatorio) tendría una diferencia de rendimiento significativa. p.ej. diferencia apreciable en el rendimiento de su aplicación.

Lo que parece es que realmente está buscando una forma de bajo nivel para asignar matrices porque está acostumbrado a hacerlo en C, y el rendimiento es un reclamo por la necesidad de hacerlo.

Por cierto: Acceder a ByteBuffer.allocateDirect () con say getDouble () / putDouble () puede ser más lento que el simple uso de un doble [] ya que el primero implica llamadas JNI y el segundo puede optimizarse para ninguna llamada.

La razón por la que se usa es para intercambiar datos entre los espacios Java y C. p.ej. NIO llama. Solo funciona bien cuando las lecturas / escrituras se mantienen al mínimo. De lo contrario, es mejor usar algo en el espacio Java.

es decir A menos que tenga claro lo que está haciendo y por qué lo está haciendo, puede terminar con una solución que lo haga sentir mejor, pero en realidad es más complicado y tiene un rendimiento peor que la solución simple.

Nota esta respuesta a una pregunta relacionada, que analiza System.identityHashCode () e identificación de la dirección de memoria del objeto. La conclusión es que puede usar la implementación predeterminada de hashCode () de la matriz para identificar la dirección de memoria original de la matriz (sujeto a un ajuste en un int / 32-bit)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top