Question

Mon objectif est de faire en sorte qu'un tableau alloué en java soit alloué dans une mémoire physique contiguë. Le problème que j'ai rencontré est que les pages d'un tableau sont allouées ont tendance à ne pas être contiguë en mémoire physique, à moins que je n'alloue un très grand tableau.

Mes questions sont les suivantes:

  • Pourquoi un très grand tableau garantit-il pages contiguës dans la mémoire physique?
  • Existe-t-il un moyen de s’assurer qu’un tableau est alloué dans la mémoire physique sans que le tableau soit vraiment grand?
  • Comment savoir en quelle page ou en quelle adresse physique se trouve un objet / un tableau Java sans mesurer les résultats et les échecs de cache?

Je ne cherche pas de réponses me demandant pourquoi je fais cela en java. Je comprends que C "réglerait mon problème" et que je vais à l’encontre de la nature fondamentale de Java. Néanmoins, j’ai une bonne raison de le faire.

Il n’est pas nécessaire de garantir que les réponses fonctionnent tout le temps. Je cherche des réponses qui fonctionnent la plupart du temps. Des points supplémentaires pour des réponses créatives et prêtes à l'emploi qu'aucun programmeur Java raisonnable ne pourrait écrire. C'est bien d'être spécifique à la plate-forme (x86 32 bits 64 bits).

Était-ce utile?

La solution

Étant donné que le ramasse-miettes déplace les objets dans la mémoire (logique), je pense que vous n'aurez pas de chance.

Le mieux que vous puissiez faire est d'utiliser ByteBuffer.allocateDirect . Cela ne (généralement) pas être déplacé dans la mémoire (logique) par le CPG, mais il peut être déplacé dans la mémoire physique ou même déplacé vers le disque. Si vous souhaitez de meilleures garanties, vous devrez utiliser le système d’exploitation.

Cela dit, si vous pouvez définir une taille de page aussi grande que votre segment de mémoire, tous les tableaux seront nécessairement physiquement contigus (ou remplacés).

Autres conseils

Non. La mémoire physiquement contiguë nécessite une interaction directe avec le système d'exploitation. La plupart des applications, y compris la JVM, n'obtiennent que des adresses pratiquement contiguës. Et une machine virtuelle Java ne peut pas vous donner ce qu'elle ne récupère pas du système d'exploitation.

D'ailleurs, pourquoi le voudriez-vous? Si vous configurez des transferts DMA, vous utilisez probablement d'autres techniques que Java.

Bit d'arrière-plan:

La mémoire physique d’un PC moderne est généralement flexible, sur des modules DIMM remplaçables. Chaque octet ayant une adresse physique, le système d'exploitation détermine les adresses physiques disponibles au démarrage. Il s'avère que les applications sont mieux loties en n'utilisant pas ces adresses directement. Au lieu de cela, tous les processeurs modernes (et leurs caches) utilisent des adresses virtuelles. Il existe une table de mappage avec des adresses physiques, mais celle-ci n'est pas nécessairement complète. L'échange sur disque est activé par l'utilisation d'adresses virtuelles non mappées sur des adresses physiques. Un autre niveau de flexibilité est obtenu par le fait d’avoir une table par processus, avec des mappages incomplets. Si le processus A a une adresse virtuelle qui mappe sur l'adresse physique X mais que le processus B ne le fait pas, il n'y a aucun moyen pour que le processus B puisse écrire à l'adresse physique X et nous pouvons considérer que la mémoire est exclusive au processus A. pour que cela soit sûr, le système d'exploitation doit protéger l'accès à la table de mappage, contrairement à tous les systèmes d'exploitation modernes.

La table de mappage fonctionne au niveau de la page. Une page ou un sous-ensemble contigu d'adresses physiques est mappé sur un sous-ensemble contigu d'adresses virtuelles. Le compromis entre les frais généraux et la granularité a abouti à une taille de page commune de 4 Ko. Mais comme chaque page a son propre mappage, on ne peut pas supposer une contiguïté au-delà de cette taille de page. En particulier, lorsque des pages sont expulsées de la mémoire physique, permutées sur un disque et restaurées, il est tout à fait possible qu'elles aboutissent à une nouvelle adresse de mémoire physique. Le programme ne le remarque pas, comme l'adresse virtuelle ne change pas, seule la table de mappage gérée par le système d'exploitation le fait.

Je pense que vous voudriez utiliser sun.java. non sécurisé .

Il y a peut-être moyen de faire en sorte que telle machine virtuelle soit amenée à faire ce que vous voulez, mais elle serait probablement fragile, compliquée et très probablement très spécifique à la machine virtuelle Java, à sa version, à son système d'exploitation, etc. En d'autres termes, effort gaspillé .

Donc, sans en savoir plus sur votre problème, je ne pense pas que quiconque puisse nous aider. Il n’ya certainement aucun moyen de le faire en Java en général, tout au plus sur une machine virtuelle spécifique.

Pour suggérer une alternative:

Si vous avez vraiment besoin de stocker des données dans une mémoire contiguë, pourquoi ne pas le faire dans une petite bibliothèque C et l'appeler via JNI?

Comme je le vois. Vous devez encore expliquer pourquoi

  • que les tableaux primitifs ne sont pas continus en mémoire. Je ne vois pas pourquoi ils ne seraient pas continus dans la mémoire virtuelle. (c.f. Les tableaux d'objets sont peu susceptibles d'avoir leurs objets continus en mémoire)
  • un tableau qui n’est pas continu dans la mémoire physique (RAM, c’est-à-dire une mémoire à accès aléatoire) aurait une différence de performances significative. par exemple. différence mesurable dans les performances de votre application.

Il semble que vous recherchiez vraiment un moyen simple d’allouer des tableaux, car vous êtes habitué à le faire en C, et les performances sont une prétention à la nécessité de le faire.

BTW: L'accès à ByteBuffer.allocateDirect () avec say getDouble () / putDouble () peut être plus lent qu'en utilisant un double [] car le premier implique des appels JNI et que le dernier peut être optimisé pour ne pas appeler du tout.

Il est utilisé pour l'échange de données entre les espaces Java et C. par exemple. NIO appelle. Il ne fonctionne bien que lorsque les lectures / écritures sont réduites au minimum. Sinon, vous feriez mieux d’utiliser quelque chose dans l’espace Java.

i.e. Si vous n'êtes pas certain de ce que vous faites et de la raison , vous pouvez vous retrouver avec une solution qui pourrait vous aider à vous sentir mieux, mais qui est en réalité plus compliquée et moins performante que la solution simple.

Notez la cette réponse à une question connexe traitant de System.identityHashCode. () et identification de l'adresse mémoire de l'objet. En bout de ligne, vous pouvez utiliser l'implémentation hashCode () du tableau par défaut pour identifier l'adresse de mémoire d'origine du tableau (sous réserve de l'ajustement dans un int / 32 bits)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top