문제

저의 목표는 Java에 할당 된 배열이 인접한 물리적 메모리에 할당되도록하는 것입니다. 내가 겪는 문제는 배열에 배정 된 페이지가 실제로 큰 배열을 할당하지 않는 한 물리적 메모리에 인접하지 않은 경향이 있다는 것입니다.

내 질문은 다음과 같습니다.

  • 실제로 큰 배열이 물리적 메모리에 인접한 페이지를 보장하는 이유는 무엇입니까?
  • 배열이 물리적 메모리에 배정되도록 할 수있는 방법이 있습니까? 배열을 실제로 크게 만들지 않는 것은 무엇입니까?
  • 캐시 히트/캐시 누락을 측정하지 않고 어떤 페이지 나 물리 주소가 존재하는지 어떻게 알 수 있습니까?

나는 왜 내가 Java 에서이 일을하고 있는지 묻는 답을 찾고 있지 않습니다. 나는 C가 "내 문제를 해결"하고 Java의 근본적인 특성에 반대한다는 것을 이해합니다. 그럼에도 불구하고 나는 이것을 할 충분한 이유가 있습니다.

답을 항상 보장 할 필요는 없습니다. 나는 대부분의 시간에 맞는 답을 찾고 있습니다. 합리적인 Java 프로그래머가 글을 쓸 수없는 창의적이고 상자가없는 답변을위한 추가 포인트. 플랫폼 특정 (x86 32 비트 64 비트)이해도 괜찮습니다.

도움이 되었습니까?

해결책

쓰레기 수집가가 (논리적) 메모리에서 물체를 움직이기 때문에 운이 좋지 않을 것이라고 생각합니다.

당신이 할 수있는 최선은 사용하는 것입니다 Bytebuffer.allocatedirect. (일반적으로) GC에 의해 (논리적) 메모리가 움직이지 않지만 물리적 메모리로 이동하거나 디스크로 이동할 수도 있습니다. 더 나은 보증을 원한다면 OS에 도달해야합니다.

그러나 페이지 크기를 힙만큼 커질 수 있으면 모든 배열이 반드시 물리적으로 인접하게 (또는 교체)를 설정할 수 있습니다.

다른 팁

아니요. 물리적으로 인접한 메모리는 OS와 직접적인 상호 작용이 필요합니다. 대부분의 응용 프로그램 인 JVM은 사실상 연속 주소 만 얻을 수 있습니다. 그리고 JVM은 OS에서 얻지 못하는 것을 줄 수 없습니다.

게다가, 왜 그것을 원하십니까? DMA 전송을 설정하는 경우 어쨌든 Java 외에 기술을 사용하고있을 것입니다.

약간의 배경 :

최신 PC의 물리적 메모리는 일반적으로 대체 가능한 DIMM 모듈에서 유연한 양입니다. 각 바이트에는 물리적 주소가 있으므로 부팅 중 운영 체제는 사용 가능한 물리적 주소를 결정합니다. 이러한 주소를 직접 사용하지 않으면 응용 프로그램이 더 나은 것으로 나타났습니다. 대신, 모든 최신 CPU (및 캐시)는 가상 주소를 사용합니다. 물리적 주소에 대한 매핑 테이블이 있지만 이는 완전 할 필요가 없습니다. 디스크로 스왑은 물리적 주소에 매핑되지 않은 가상 주소를 사용하여 활성화됩니다. 불완전한 매핑으로 프로세스 당 하나의 테이블을 갖추면 또 다른 수준의 유연성이 얻어집니다. 프로세스 A가 물리적 주소 X에 매핑되는 가상 주소가 있지만 프로세스 B는 그렇지 않으면 프로세스 B가 물리적 주소 X에 쓸 수있는 방법이 없으며, 해당 메모리가 프로세스 A에만 독점적이라고 생각할 수 있습니다. 이를 위해서는 OS가 매핑 테이블에 대한 액세스를 보호해야하지만 모든 최신 OS는 그렇습니다.

매핑 테이블은 페이지 레벨에서 작동합니다. 물리적 주소의 페이지 또는 연속적인 하위 집합은 가상 주소의 연속 하위 집합에 매핑됩니다. 오버 헤드와 세분화 사이의 절충으로 4KB 페이지가 일반적인 페이지 크기가되었습니다. 그러나 각 페이지에는 자체 매핑이 있으므로 해당 페이지 크기를 넘어서 연속성을 가정 할 수 없습니다. 특히, 페이지가 물리적 메모리에서 퇴거되고 디스크로 교체되고 복원되면 새로운 물리적 메모리 주소에서 끝날 가능성이 상당히 높습니다. 가상 주소가 변경되지 않으므로 OS 관리 맵핑 테이블 만 표시됩니다.

나는 당신이 사용하고 싶다고 생각합니다 Sun.java.unsafe.

특정 JVM이 원하는 작업을 수행하도록 속이는 방법이있을 수 있지만, 이는 아마도 깨지기 쉽고 복잡하며 JVM, 버전, OS가 실행되는 경우에 매우 구체적 일 것입니다. 다시 말해서, 낭비 된 노력.

따라서 귀하의 문제에 대해 더 많이 알지 못하면 아무도 도울 수 없을 것이라고 생각합니다. 일반적으로 Java에서는 대부분의 특정 JVM에서 할 수있는 방법이 없습니다.

대안을 제안하려면 :

실제로 데이터를 연속 메모리로 저장 해야하는 경우 작은 C 라이브러리에서 수행하지 말고 JNI를 통해 호출하지 않겠습니까?

내가 알듯이. 당신은 아직 이유를 설명하지 않았습니다

  • 그 원시 배열은 메모리에서 연속적이지 않습니다. 왜 그들이 가상 메모리에서 연속적이지 않을지 모르겠습니다. (객체의 CF 배열은 메모리에 객체가 연속적이지 않을 것입니다)
  • 물리적 메모리에서 연속적이지 않은 배열 (즉, RAM IE Random Access Memory)은 상당한 성능 차이를 갖습니다. 예를 들어 애플리케이션 성능의 측정 가능한 차이.

그것이 나타나는 것은 C 에서이 작업을 수행하는 데 익숙하기 때문에 배열을 할당하는 낮은 레벨 방법을 찾고 있다는 것입니다. 성능은이를 수행 해야하는 요구입니다.

btw : getDouble ()/putdouble ()을 사용하여 Bytebuffer.allocatedirect ()에 액세스하는 것은 전자가 JNI 호출과 관련하여 두 배 []을 사용하는 것이 느리게 진행되고 후자는 전혀 전화가 없도록 최적화 될 수 있습니다.

사용되는 이유는 Java와 C 공간간에 데이터를 교환하기위한 것입니다. 예를 들어 NIO는 전화를합니다. 읽기/쓰기가 최소한으로 유지 될 때만 잘 수행됩니다. 그렇지 않으면 자바 공간에서 무언가를 사용하는 것이 좋습니다.

즉, 당신이 무엇을하고 있는지 명확하지 않는 한 당신은 그것을하고 있습니다. 당신은 기분이 나아질 수있는 솔루션으로 끝날 수 있지만 실제로는 더 복잡하고 간단한 솔루션보다 더 나빠집니다.

메모 이 답변 System.identityHashCode () 및 객체의 메모리 주소 식별을 논의하는 관련 질문에. 결론은 기본 배열 hashcode () 구현을 사용하여 배열의 원래 메모리 주소를 식별 할 수 있다는 것입니다 (int/32 비트에 맞는 주제).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top