지점 예측 변수에 지점을 따를 가능성을 알려줄 수 있습니까?
확실히 하기 위해서라면, 휴대성을 추구하지 않기 때문에, 특정의 박스에 묶는 솔루션이라면 어떤 것이든 상관없습니다.
기본적으로 99%의 시간이 true로 평가되는 if 스테이트먼트를 가지고 있습니다.또한 퍼포먼스의 마지막 클럭을 모두 해결하려고 합니다.브런치 프레딕터에 대해 캐시해야 한다고 지시하기 위해 (중요한 경우 GCC 4.1.2와 x86 ISA를 사용하여) 일종의 컴파일러 명령어를 발행할 수 있습니까?
네, 하지만 효과가 없을 거예요.Netburst 이전의 오래된(구식) 아키텍처는 예외이며, 그 경우에도 측정 가능한 기능이 없습니다.
Netburst 아키텍처에 인텔이 도입한 「브런치 힌트」opcode와 콜드 점프에 관한 디폴트 스태틱브런치 예측(역방향 예측 테이크, 전방 예측 비테이크)이 있습니다.GCC는 이 기능을__builtin_expect (x, prediction)
여기서 prediction은 보통 0 또는 1입니다.컴파일러에 의해 출력되는 opcode는 새로운 모든 프로세서아키텍스(>= Core 2)에서는 무시됩니다.이것이 실제로 도움이 되는 작은 코너 케이스는 오래된 Netburst 아키텍처의 콜드 점프 케이스입니다.인텔에서는 코드 사이즈의 증가가 한계 속도의 증가보다 더 해롭다고 생각하기 때문에 정적 브랜치 힌트를 사용하지 않는 것이 좋습니다.
예측자를 위한 쓸모없는 분기 힌트 말고도__builtin_expect
를 사용하면 컴파일러는 캐시 사용률을 개선하거나 메모리를 절약하기 위해 코드를 재정렬할 수 있습니다.
예상대로 작동하지 않는 이유는 여러 가지가 있습니다.
- 프로세서는 작은 루프(n<64)를 완벽하게 예측할 수 있습니다.
- 이 프로세서는 작은 반복 패턴(n~7)을 완벽하게 예측할 수 있습니다.
- 프로세서 자체는 컴파일러/프로그래머보다 실행 시 분기 확률을 더 잘 추정할 수 있습니다.
- 분지의 예측 가능성(= 분지가 올바르게 예측될 확률)은 분지가 취할 확률보다 훨씬 더 중요합니다.안타깝게도 이는 아키텍처에 크게 의존하며 지점의 예측 가능성을 예측하는 것은 매우 어렵습니다.
분기 예측의 내부 작업에 대한 자세한 내용은 Agner Fogs 설명서를 참조하십시오.gcc 메일링 리스트도 참조해 주세요.
네. http://kerneltrap.org/node/4705
그
__builtin_expect
는 프로그래머가 컴파일러에 분기 예측 정보를 나타내기 위해 gcc(parameter > = 2.96)가 제공하는 메서드입니다.의 반환값__builtin_expect
는 전달된 첫 번째 인수(정수만 가능)입니다.
if (__builtin_expect (x, 0))
foo ();
[This] would indicate that we do not expect to call `foo', since we
expect `x' to be zero.
Pentium 4(일명 Netburst 마이크로아키텍처)는 jcc 명령의 접두사로서 브랜치 프레딕터의 힌트를 가지고 있었지만, P4만이 그것들을 사용해 어떠한 조작을 실시했습니다.http://ref.x86asm.net/geek32.html 를 참조해 주세요.또한 Agner Fog의 우수한 ASM 옵트 가이드 섹션 3.5를 http://www.agner.org/optimize/에서 제공합니다.C++로 최적화하는 가이드도 가지고 있습니다.
이전 x86 CPU와 이후 x86 CPU는 이러한 프리픽스바이트를 무시합니다.가능성이 있는 힌트나 다른 힌트 사용법에 대한 퍼포먼스 테스트 결과가 있습니까?파워에 대해 언급하고 있습니다.PC에는 부호화의 일부로서 분기 예측 힌트가 있는 점프 명령이 있습니다.이것은 매우 드문 건축적 특징입니다.컴파일 시에 지사를 정적으로 예측하는 것은 매우 어렵기 때문에 일반적으로 하드웨어에 맡기는 것이 좋습니다.
최신 인텔 및 AMD CPU의 브랜치 프레딕터와 브랜치 타깃 버퍼의 동작에 대해서는 공식적으로 알려진 바가 많지 않습니다.최적화 매뉴얼(AMD 및 인텔 웹사이트에서 쉽게 찾을 수 있음)은 몇 가지 조언을 제공하지만 특정 동작을 문서화하지는 않습니다.Core2에 몇 개의 BTB 엔트리가 있는지 등 구현을 확인하기 위해 테스트를 실행한 사람도 있습니다.어쨌든, (현재로서는) 예측 변수를 명시적으로 암시하는 생각은 포기되었다.
예를 들어 Core2에는 루프가 항상 짧은 횟수(<8 또는 16 IIRC)의 반복을 실행할 경우 루프의 출구를 잘못 예측하는 것을 방지할 수 있는 분기 이력 버퍼가 있습니다.64바이트(또는 펜린에서는 19uops)에 맞는 루프는 버퍼에서 재생되므로 명령 가져오기 병목 현상이 발생하지 않으므로 너무 빨리 풀지 마십시오.애그너 포그의 PDF를 읽어보렴 아주 훌륭해
또, 「인텔은 왜 최근 몇년간 정적 브랜치 예측 메커니즘을 변경했는가」를 참조해 주세요.Sandybridge 이후 인텔에서는 정적 예측을 전혀 사용하지 않습니다.CPU의 기능을 리버스 엔지니어링하려고 하는 퍼포먼스 실험으로부터 알 수 있습니다.(많은 오래된 CPU는 동적 예측이 빗나갔을 때의 폴백으로서 정적 예측을 하고 있습니다.통상적인 정적 예측은 순방향 브랜치는 취득되지 않고 역방향 브랜치는 취득됩니다(후방향 브랜치는 루프 브랜치인 경우가 많기 때문입니다).
(Drakosha의 답변 설명과 같은) GNU C를 사용하는 /unlikely()
매크로의 효과는 BP 힌트를 asm에 직접 삽입하지 않습니다.(그럴 가능성이 있습니다.gcc -march=pentium4
(단, 컴파일 할 때는 제외합니다).
그 결과, 고속 패스에 취득한 브랜치가 적어지고, 명령의 합계수가 적어지는 경우가 있습니다.이를 통해 정적 예측이 실행되는 경우(예: 동적 예측 변수가 콜드 상태이며, 예측 캐시에 브랜치가 서로 에일리어스하도록 하는 것이 아니라 정적 예측으로 폴백되는 CPU) 분기 예측에 도움이 됩니다.
기타 문장에서 GCC의 __builtin_expect의 장점은 무엇입니까?를 참조하십시오.예를 들어 코드겐의 특정 예를 나타냅니다.
가지치기 비용은 가지치기보다 조금 더 비쌉니다. 완벽하게 예측되더라도 말입니다.CPU가 병렬로 디코딩하기 위해 16바이트의 청크로 코드를 가져올 때, takeed 브랜치는 해당 fetch 블록의 이후 명령이 실행되는 명령 스트림의 일부가 아님을 의미합니다.프런트 엔드에 거품이 생겨 높은 처리량 코드의 병목 현상이 발생할 수 있습니다(캐시 미스 백엔드에서 중단되지 않고 명령 레벨의 병렬화가 높음).
또한 서로 다른 블록 사이를 이동하면 더 많은 캐시 행의 코드에 영향을 미쳐 L1i 캐시 설치 공간이 증가하고 콜드 상태일 경우 명령 캐시 누락이 더 많이 발생할 수 있습니다(또한 uop-cache 설치 공간도 증가할 수 있습니다.즉, 고속 경로가 짧고 직선적인 또 다른 장점입니다.
GCC의 프로파일 가이드 최적화에서는 일반적으로 매크로가 불필요해집니다.컴파일러는 코드 레이아웃 결정을 위해 각 브랜치가 어느 방향으로 진행되었는지에 대한 런타임 데이터를 수집하여 핫 블록/함수와 콜드 블록/함수를 식별합니다.(예: 핫 기능에서는 루프를 풀지만 콜드 기능에서는 풀지 않습니다.)봐-fprofile-generate
그리고.-fprofile-use
를 참조하십시오.g++에서 프로파일 가이드 최적화를 사용하는 방법
그렇지 않으면 GCC는 매크로를 사용하지 않고 PGO를 사용하지 않은 경우 다양한 휴리스틱을 사용하여 추측해야 합니다. -fguess-branch-probability
는 디폴트로 유효하게 되어 있습니다.-O1
그 이상입니다.
https://www.phoronix.com/scan.php?page=article&item=gcc-82-pgo&num=1 는, Xeon 스케일러블 서버 CPU의 gcc8.2 를 사용한 PGO 와 통상의 비교에 관한 벤치마크 결과를 나타내고 있습니다(Skylake-AVX512).모든 벤치마크에서 최소 약간의 속도 향상 효과를 얻었으며, 일부 벤치마크에서는 최대 10%의 이점을 얻기도 했습니다.(대부분은 핫루프에서의 루프 언롤링에 의한 것일 수 있지만, 그 중 일부는 브랜치레이아웃이나 기타 효과의 향상으로 생각됩니다).
지점 예측을 걱정하지 말고 코드를 프로파일링하고 최적화하여 지점 수를 줄이는 것이 좋습니다.하나의 예로는 루프 언롤링을 들 수 있으며, 다른 예로는 부울 프로그래밍 기술을 사용하여if
진술들.
대부분의 프로세서는 문장의 프리페치를 좋아합니다.일반적으로 브랜치 스테이트먼트는 프로세서 내에서 장애를 생성하여 프리페치 큐를 플래시합니다.여기가 가장 큰 벌칙입니다.이 패널티 시간을 단축하려면 사용 가능한 브랜치 수가 줄어들도록 코드를 다시 작성합니다(및 설계).또, 일부의 프로세서는, 분기하지 않고, 조건부로 명령을 실행할 수 있습니다.
루프 언롤링과 대용량 I/O 버퍼를 사용하여 프로그램을 실행 시간 1시간에서 2분으로 최적화했습니다.이 경우 지점 예측으로는 시간을 크게 절약할 수 없습니다.
SUN C Studio에는 이 경우에 대해 정의된 몇 가지 플러그마가 있습니다.
#subma_called()는 거의 없습니다.
이것은 조건식의 일부가 함수 호출이거나 함수 호출로 시작하는 경우에 기능합니다.
단, 일반적인 if/while 스테이트먼트에 태그를 붙일 방법은 없습니다.
아니요, 분기 예측 변수를 알려주는 어셈블리 명령이 없기 때문입니다.걱정 마, 지점 예측자는 꽤 똑똑해.
또, 섣부른 최적화와 그것이 얼마나 나쁜지에 대한 의무적인 코멘트.
편집: Drakosha가 GCC용 매크로를 몇 가지 언급했습니다.다만, 이것은 코드 최적화이며, 브랜치 예측과는 전혀 관계가 없다고 생각합니다.
이것은 과잉으로 들립니다.이러한 최적화를 통해 시간을 절약할 수 있습니다.예를 들어 최신 버전의 gcc를 사용하면 최적화에 훨씬 더 큰 영향을 미칩니다.또한 모든 최적화 플래그를 활성화 및 비활성화해 보십시오. 모든 플래그가 성능을 향상시키지는 않습니다.
기본적으로, 이것이 다른 많은 알찬 길과 비교했을 때 큰 차이를 만들지는 않을 것 같습니다.
EDIT: 코멘트 감사합니다.이 커뮤니티 위키를 만들었는데 다른 사람들이 댓글을 볼 수 있도록 남겨뒀어요.
언급URL : https://stackoverflow.com/questions/1851299/is-it-possible-to-tell-the-branch-predictor-how-likely-it-is-to-follow-the-branc
'source' 카테고리의 다른 글
매개 변수화된 테스트 이름 변경 (0) | 2022.08.19 |
---|---|
laravel-vujs 프로젝트의 루트/베이스 URL을 설정하려면 어떻게 해야 합니까? (0) | 2022.08.19 |
Vue CLI를 사용하여 여러 Vue.js 컴포넌트를 네이티브 웹 컴포넌트에 한 번에 빌드하려면 어떻게 해야 합니까? (0) | 2022.08.19 |
vue.filename: 와의 차이점vue.filename: 와의 차이점?? (0) | 2022.08.19 |
NuxtServerInit을 올바르게 호출하려면 어떻게 해야 합니까? (0) | 2022.08.19 |