이 기사는 원래 Ampere Computing에서 출판되었습니다
새로운 GNU 성능 분석 도구 인 GPROFNG에 대한 최근 블로그 게시물을 보았습니다. 이 블로그는 C 언어로 작성된 매트릭스 벡터 곱셈 프로그램을 예로 들어 사용합니다. 저는 Java ™ 프로그래머이며 정적으로 컴파일 된 C 프로그래밍을 위해 설계된 도구를 사용하는 것은 Java 프로그램이 런타임에 컴파일되기 때문에 Java 응용 프로그램을 분석하기가 어렵습니다. 이 블로그 게시물에서 GPROFNG는 사용하기 쉽고 Java 응용 프로그램의 동적 동작을 탐구하는 데 매우 유용하다는 것을 보여줍니다.
첫 번째 단계는 매트릭스 곱셈 프로그램을 작성하는 것입니다. 매트릭스 곱셈 벡터보다 단단하지 않기 때문에 완전한 행렬 곱셈 행렬 프로그램을 작성했습니다. 세 가지 주요 방법이 있습니다. 하나의 방법은 가장 안쪽 곱셈 및 첨가 작업을 계산하고, 하나의 방법은 곱셈 및 첨가 작업을 결과의 단일 요소로 결합하고, 하나의 방법은 결과의 각 요소에 반복합니다.
나는 간단한 테스트 프로그램에서 계산을 랩핑하여 행렬 제품을 반복적으로 계산하여 시간을 반복 할 수 있도록합니다. (참고 1 참조) 프로그램은 각 매트릭스 곱셈이 시작되는 시간 (Java Virtual Machine이 시작된 시간에 비해)과 각 행렬 곱셈에 걸리는 시간을 인쇄합니다. 여기서 나는 2 개의 8000 × 8000 행렬을 곱하기 위해 테스트 프로그램을 실행했습니다. 테스트 프로그램은 계산을 11 번 반복하고 후속 동작을 더 잘 강조하기 위해 반복 사이에 920 밀리 초의 수면 :
그림 1 : 매트릭스 곱셈 프로그램 실행
두 번째 반복은 첫 번째 반복 시간의 92%를 차지하는 반면, 마지막 반복은 첫 번째 반복 시간의 89% 만 소요됩니다. 이러한 실행 시간의 이러한 변경 사항은 Java 프로그램이 워밍업하는 데 약간의 시간이 필요하다는 것을 확인합니다.
<:> 질문은 : GPROFNG를 사용하여 첫 번째 반복과 마지막 반복 사이에 어떤 일이 발생하는지 확인하여 성능 향상을 초래할 수 있습니까?
이 질문에 답하는 한 가지 방법은 프로그램을 실행하고 GPROFNG가 실행중인 정보를 수집하게하는 것입니다. 다행히도, 이것은 쉬운 일입니다. GPROFNG가 "실험적"정보를 수집하기 위해 명령 줄을 접두어 만 접두하면됩니다.
$ numactl --cpunodebind=0 --membind=0 -- \
java -XX:+UseParallelGC -Xms31g -Xmx31g -Xlog:gc -XX:-UsePerfData \
MxV -m 8000 -n 8000 -r 11 -s 920
로그인 후 복사
그림 2 : gprofng 에서 매트릭스 곱셈 프로그램 실행
가장 먼저 주목해야 할 것은 성능 분석 도구와 마찬가지로 성능 분석 정보를 수집하면 응용 프로그램에 비용이들 수 있다는 것입니다. 이전의 비정상적인 실행과 비교하여 GPROFNG는 상당한 오버 헤드를 유발하지 않는 것으로 보입니다.
그런 다음 전체 응용 프로그램을 GPROFNG에서 어떻게 소비하는지 물어볼 수 있습니다. (참고 2 참조) 전체 달리기의 경우 GPROFNG의 가장 인기있는 24 가지 방법은 다음과 같습니다.
그림 3 : 24 가장 인기있는 gprofng를 보여주는 방법
위에 표시된 함수보기는 초의 백분율 및 총 CPU 시간으로 표현 된 각 방법에 대한 독점 및 포함 CPU 시간을 제공합니다. 명명 된 함수는 GPROFNG에 의해 생성 된 의사 기능이며 다양한 지표의 총 값입니다. 이 경우 전체 응용 프로그램의 총 CPU 시간은 1.201 초입니다.
응용 프로그램 (MXV 클래스의 응용 프로그램) 메소드는 모두 CPU 시간의 대부분을 차지하고 있지만 JVM 런타임 컴파일러 (Compilation :: Compilation) 및 다른 기능을 포함한 다른 방법이 있습니다. 매트릭스 곱셈 프로그램. 전체 프로그램 실행 의이 표시는 할당 (MXV.ALLOTE) 및 초기화 (MXV.INITIALIZE) 코드를 캡처합니다. 테스트 프로그램의 일부이기 때문에 관심이없고 시작 중에만 사용되며 곱합니다. 매트릭스를 사용하면 거의 중요하지 않습니다.
나는 GPROFNG를 사용하여 관심있는 응용 프로그램의 일부를 따라갈 수 있습니다. GPROFNG의 가장 큰 특징은 실험을 수집 한 후 수집 된 데이터에 필터를 적용 할 수 있다는 것입니다. 예를 들어, 특정 시간 간격 동안 발생하는 일 또는 특정 메소드가 통화 스택에있을 때 발생하는 일을 살펴보십시오. 데모 목적과 필터링을보다 쉽게하기 위해 프로그램 단계 (1 초 간격으로 나뉘어 있음)를 기반으로 필터를 쉽게 작성할 수 있도록 전략적 호출을 추가했습니다. 이것이 각 행렬 곱셈이 약 0.1 초만 걸리더라도 위의 그림 1의 프로그램 출력이 각 반복 사이에 약 1 초인 이유입니다.
GPROFNG는 스크립트가 가능하므로 GPROFNG 실험에서 1 초를 추출하기 위해 스크립트를 썼습니다. 첫 번째 두 번째는 Java Virtual Machine Startup에 관한 것입니다.
그림 4 : 첫 번째 초를 필터링하는 가장 인기있는 방법. 이 두 번째 내에, 매트릭스 곱셈은 수동으로 지연되어 JVM 스타트 업 를 보여줄 수 있습니다.
응용 프로그램의 어떤 방법이 아직 실행되지 않았더라도 컴파일러가 런타임 (예 : Compilation :: Compile_java_Method, CPU 시간의 16%)에서 시작하는 것을 알 수 있습니다. (매트릭스 곱셈 호출은 내가 삽입 한 수면 호출에 의해 지연되었습니다.)
첫 번째 순간은 1 초이며,이 기간 동안 할당 및 초기화 메소드는 다양한 JVM 방법으로 실행되지만 매트릭스 곱셈 코드는 아직 시작되지 않았습니다.
그림 5 : 두 번째 초에 가장 인기있는 방법. 매트릭스 할당 및 초기화는 JVM startup
와 경쟁합니다
이제 JVM 스타트 업과 배열의 할당 및 초기화가 완료되었으므로 그림 6과 같이 세 번째 초에 매트릭스 곱셈 코드의 첫 번째 반복이 있습니다. 그러나 행렬 곱셈 코드는 행렬 곱셈 코드가 뜨거워지기 때문에 메소드를 컴파일하는 메소드를 컴파일하는 Java 런타임 컴파일러 (예 : CompileBroker :: invoke_compiler_on_method, 그림 6의 8%)와 경쟁하고 있습니다. 그럼에도 불구하고, 매트릭스 곱셈 코드 (예 : MXV.Main 방법의 "시간 포함, 91%)는 여전히 대부분의 CPU 시간을 얻습니다. 포함 시간은 매트릭스 곱셈 (예 : mxv. multiply)이 0.100 cpu 초에 걸리며, 이는 그림 2의 응용 프로그램에 의해보고 된 실제 시간과 일치한다는 것을 나타냅니다. (실제 시간을 수집하고보고하는 데 약간의 시간이 걸리며, CPU 시간 외부에있는 Gprofng는 MXV. multiply에 포함됩니다.) .
그림 6 : 런타임 컴파일러가 매트릭스 곱셈 방법
와 경쟁하고 있음을 나타냅니다.
이 특정 예에서, 행렬 곱셈은 CPU 시간과 실제로 경쟁하지 않습니다. 테스트는 많은 유휴 사이클이 있고 런타임 컴파일러가 별도의 스레드로 실행되는 멀티 프로세서 시스템에서 실행되기 때문입니다. 하중이 많은 공유 기계와 같은보다 제한적인 경우 런타임 컴파일러가 소비하는 시간의 8%가 문제가 될 수 있습니다. 반면에, 런타임 컴파일러에 소비 된 시간은보다 효율적인 메소드 구현을 초래하므로 많은 행렬 곱셈을 계산하면 기꺼이 투자 할 것입니다.
5 초까지 행렬 곱셈 코드에는 Java Virtual Machine이 있습니다.
그림 7 : 5 초 동안 실행되며 행렬 곱셈 방법 만 활성화되어 있음을 나타냅니다.
독점적 인 CPU 초의 MXV.Onecell, MXV.MultiplyAdd 및 MXV. 간의 60%/30%/10%할당에 유의하십시오. mxv.multiplyadd 방법은 곱셈과 추가 만 계산합니다. 그러나 그것은 매트릭스 곱셈에서 가장 내면의 방법입니다. mxv.onecell에는 mxv.multiplyadd를 호출하는 루프가 있습니다. 루프 오버 헤드 및 호출 (평가 조건 및 제어 전송)이 MXV.multiplyAdd에서 직접 산술 작업보다 상대적으로 더 작동하는 것을 볼 수 있습니다. (MXV.Onecell은 0.060 cpu 초인 반면 MXV.MXV.MULTIPLYADD는 0.030 CPU 초입니다.이 차이를 반영합니다.) MXV의 외부 루프 실행 주파수는 런타임 컴파일러가 아직 컴파일하지 않았을 정도로 높지 않습니다. 그러나이 방법은 0.010 CPU 초를 사용하고 있습니다.
행렬 곱셈은 JVM 런타임 컴파일러가 다시 시작하여 MXV. Multiply가 매우 뜨거워 졌다는 것을 알게되면 9 초까지 계속됩니다.
마지막 반복에서 행렬 곱셈 코드는 Java Virtual Machine을 최대한 활용합니다.
그림 9 : 매트릭스 곱셈 프로그램의 마지막 반복, 코드의 최종 구성
결론
나는 성능 분석을 위해 gprofng를 사용하여 Java 응용 프로그램의 런타임에 쉽게 접근 할 수 있음을 보여주었습니다. GPROFNG의 필터링 기능을 사용하여 시간 슬라이스로 실험을 확인하면 관심있는 프로그램 단계를 확인할 수있었습니다. 예를 들어, 애플리케이션의 할당 및 초기화 단계를 제외하고 런타임 컴파일러가 Magic을 실행할 때 프로그램의 한 번만 표시하면 핫 코드가 점차 컴파일 될 때 개선되는 성능을 강조 할 수 있습니다.
추가 읽기
GPROFNG에 대해 알고 싶어하는 독자의 경우 GPROFNG에 대한 소개 비디오가있는 블로그 게시물, Oracle Linux에 설치 방법에 대한 지침을 포함하여 다음과 같습니다.
승인
조언과 기술 지원에 대한 Ruud van der Pas, Kurt Goebel 및 Vladimir Mezentsev와 Elena Zannoni, David Banman, Craig Hardy 및 Dave Neary 에게이 블로그 게시물을 작성하도록 격려했습니다.
노트
프로그램 명령 줄 구성 요소의 동기는 다음과 같습니다.
numactl --cpunodebind = 0 --membind = 0-. Java Virtual Machines에서 사용하는 메모리를 NUMA 노드의 핵심 및 메모리로 제한합니다. JVM을 하나의 노드로 제한하면 실행되는 프로그램 간의 차이가 줄어들 수 있습니다.
<.> Java. Aarch64의 JDK-17.0.4.1의 OpenJDK 버전을 사용하고 있습니다.
<: :> -xx : useparallelgc. 이용 가능한 수집기에서 최소한의 배경 작업을 수행하므로 병렬 쓰레기 수집기를 활성화하십시오.
-xms31g -xmx31g. 충분한 Java 객체 힙 공간을 제공하며 쓰레기 수집이 필요하지 않습니다.
-xlog : gc. 실제로 수집 할 필요가 없는지 확인하기 위해 GC 활동을 기록하십시오. ( "신뢰하지만 확인하십시오.")
<: :> -xx : -useperfdata. Java 가상 머신의 오버 헤드를 줄입니다.
-
gprofng 옵션에 대한 설명은 다음과 같습니다
-limit 24. 처음 24 가지 방법 만 표시됩니다 (여기에서는 독점 CPU 시간으로 정렬). 24 가지 방법을 보여주는 것은 시간을 거의 사용하지 않는 사람들에 대한 좋은 아이디어를 제공한다는 것을 알 수 있습니다. 나중에 일부 장소에서는 16 개의 방법이 16 가지를 사용하여 16 가지 방법이 사소한 CPU 시간을 기여하는 방법으로 줄일 수 있습니다. 일부 예에서, GPROFNG 자체는 시간을 축적하는 방법이 많지 않기 때문에 디스플레이를 제한합니다. -
-뷰 모드 전문가. JVM 자체를 포함한 Java 방법뿐만 아니라 모든 누적 CPU 시간을 표시하는 방법. 이 플래그를 사용하면 런타임 컴파일러 메소드 등을 볼 수 있습니다.
| 위 내용은 Java Virtual Machine은 하루 종일 무엇을합니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!