대규모 선형 프로그래밍 문제를보다 정확하게하기 위해 수치 최적화 문제 클래스를 해결하기 위해 Java 응용 프로그램을 개발 중입니다. 단일 문제는 더 작은 하위 문제로 나뉘어 병렬로 해결할 수 있습니다. CPU 코어보다 하위 문제가 더 많으므로 ExecutorService를 사용하고 각 하위 문제를 ExecutorService에 제출되는 Callable로 정의합니다. 하위 문제를 해결하려면이 경우 선형 프로그래밍 솔버 인 기본 라이브러리를 호출해야합니다.
문제
최대 44 개의 물리적 코어와 최대 256g 메모리를 가진 Unix 및 Windows 시스템에서 응용 프로그램을 실행할 수 있지만 Windows의 계산 시간은 큰 문제의 경우 Linux보다 훨씬 빠릅니다. Windows는 실질적으로 더 많은 메모리를 필요로 할뿐만 아니라 시간이 지남에 따라 CPU 사용률이 처음에는 25 %에서 몇 시간 후에 5 %로 감소합니다. 다음은 Windows에서 작업 관리자의 스크린 샷입니다.
관찰
- 전체 문제의 큰 인스턴스에 대한 솔루션 시간은 몇 시간에서 며칠까지이며 최대 32g의 메모리를 소비합니다 (Unix에서). 하위 문제의 해결 시간은 ms 범위입니다.
- 해결하는 데 몇 분 밖에 걸리지 않는 작은 문제에서는이 문제가 발생하지 않습니다.
- Linux는 기본적으로 두 소켓을 모두 사용하지만 Windows는 응용 프로그램이 두 코어를 모두 사용하도록 BIOS에서 메모리 인터리빙을 명시 적으로 활성화해야합니다. 내가하지 않더라도 시간이 지남에 따라 전체 CPU 사용률이 저하되지는 않습니다.
- VisualVM에서 스레드를 볼 때 모든 풀 스레드가 실행 중이며 대기중인 스레드가 없습니다.
- VisualVM에 따르면 90 % CPU 시간은 기본 함수 호출에 사용됩니다 (작은 선형 프로그램 해결).
- 가비지 콜렉션은 애플리케이션이 많은 오브젝트를 작성 및 역 참조하지 않기 때문에 문제가되지 않습니다. 또한 대부분의 메모리는 힙에 할당 된 것으로 보입니다. 가장 큰 인스턴스의 경우 Linux에서는 4g, Windows에서는 8g이면 충분합니다.
내가 시도한 것
- 모든 종류의 JVM 인수, 높은 XMS, 높은 메타 스페이스, UseNUMA 플래그, 기타 GC
- 다른 JVM (Hotspot 8, 9, 10, 11).
- 다른 선형 프로그래밍 솔버 (CLP, Xpress, Cplex, Gurobi)의 서로 다른 기본 라이브러리.
질문
- 네이티브 호출을 많이 사용하는 대규모 멀티 스레드 Java 애플리케이션의 Linux와 Windows 간의 성능 차이는 무엇입니까?
- 예를 들어 수천 개의 Callable을 수신하는 ExecutorService를 사용하지 않고 대신 수행해야하는 경우 Windows 구현에 도움이되는 변경 사항이 있습니까?
ForkJoinPool
경우 수동 예약보다 효율적입니다.
ForkJoinPool
대신 사용해 보셨습니까ExecutorService
? 문제가 CPU 바운드 인 경우 25 % CPU 사용률이 실제로 낮습니다.