>  기사  >  시스템 튜토리얼  >  x86 파이프라인 수준에서 성능 최적화

x86 파이프라인 수준에서 성능 최적화

WBOY
WBOY앞으로
2024-01-03 18:32:261103검색
소개 가지를 마주할 때 올바른 길을 선택하는 방법은 무엇인가요? 명령어 선택이 잘못된 경우 전체 파이프라인은 나머지 명령어가 실행될 때까지 기다렸다가 지운 다음 올바른 위치에서 다시 시작해야 합니다. 파이프라인의 높이가 깊을수록 피해가 커집니다.
머리말

성능 최적화, 핵심은 CPU를 잘 서비스하는 것입니다. 최고의 성능을 추구하는 프로그래머로서 CPU의 내부 메커니즘을 이해하는 것은 피할 수 없는 주제입니다. 이는 시간이 지남에 따라 축적이 필요한 지속적인 프로세스이지만 디지털 회로에 깊이 들어갈 필요는 없습니다. CPU 설계 전문가가 반드시 소프트웨어 설계에 능숙할 필요는 없는 것처럼 CPU 전문가가 될 필요도 없습니다. 고급 성능 소프트웨어를 작성합니다.

소수의 엘리트들이 일반 대중에게 주는 소중한 선물로서 시장에서 마음대로 구입할 수 있는 CPU는 실제로 구입할 수 없는 핵무기와 마찬가지로 인류의 가장 첨단 기술 수준을 나타냅니다. x86 CPU 전문가라도 자신의 전문 분야에 대해서만 자세히 말할 수 있습니다. 우리가 모든 것을 이해하는 것은 불가능하지만 파이프라인, 캐시, 명령어 세트라는 매우 중요한 세 부분이 있습니다. 이 세 부분 중 '조립 라인'이 실행 단서로 활용될 수 있다. 따라서 이전 기사의 예에 따라 먼저 파이프라인을 살펴보겠습니다.
기본 개념

PU의 주요 업무는 지시에 따라 데이터에 대한 연산을 수행하는 것입니다. 이 문장은 기본적으로 조립 라인이 무엇인지 설명합니다. 이 기사를 클릭할 수 있는 사람은 "조립 라인"이라는 개념에 대해 전혀 모르는 사람이라는 것을 알고 있습니다. 처음에 교과서 같은 큰 텍스트를 배치하고 다양한 개념의 정의를 나열하고 싶지 않습니다. 진심으로 기본을 버리고, 열등한 것을 추구합니다. 기술의 발전은 사물의 모순이 움직이는 형태일 뿐입니다. 이번에는 CPU의 역사적 진화의 관점에서 파이프라인의 다양한 구성 요소를 소개하려고 합니다.

40년 전 인텔이 최초의 8086 프로세서를 생산한 때부터 오늘날까지 CPU의 변화로 인해 이전 프로세서는 "단일 칩 컴퓨터"라고만 부를 수 있다는 느낌이 들었습니다. 하지만 Taobao에서 단 몇 센트에 불과한 단일 칩 마이크로컴퓨터라고 해도 여전히 오늘날의 i7 프로세서와 일부 유사점이 있습니다. 8086 프로세서에는 오늘날에도 여전히 사용되고 있는 14개의 레지스터가 있는데, 4개의 범용 레지스터(General Purpose Register), 4개의 세그먼트 레지스터(Segment Register), 4개의 인덱스 레지스터(Index Register), 1개의 플래그 레지스터(EFLAGS Register)가 사용된다. CPU 상태를 표시하기 위해 사용되며 마지막 명령어 포인터 레지스터는 실행해야 할 다음 명령어의 주소를 저장하는 데 사용됩니다. 이 명령 포인터 레지스터는 파이프라인의 작동 프로세스와 직접적으로 관련되어 있으며 계속 존재하는 것은 파이프라인 기본 원리의 시간 일관성을 보여줍니다.

40년 전부터 현재까지 CPU가 실행하는 모든 명령어는 다음과 같은 과정을 따릅니다. CPU는 먼저 명령어 포인터를 기반으로 코드 세그먼트에서 실행될 명령어의 주소를 획득(Fetch)한 다음 디코딩(디코딩)합니다. ) 주소의 지시 사항. 디코딩 후에는 실제 실행(Execute) 단계로 진입한 다음 "Write Back" 단계로 들어갑니다. 여기서 처리의 최종 결과는 메모리나 레지스터에 다시 기록되고 명령 포인터 레지스터는 다음 지점으로 업데이트됩니다. 다음 지시로. 이는 기본적으로 인간의 논리와 완전히 일치하는 설계 솔루션입니다.

처음에는 가장 자연스럽게 CPU가 모든 명령을 차례로 처리합니다. 각 명령어는 위의 과정에 따라 실행되고, 다음 명령어가 실행된다. 당시 가장 큰 모순은 소프트웨어의 성능 요구 사항이 증가하는 것과 뒤떨어지는 CPU 처리 속도 사이의 모순이었습니다. 무어의 법칙의 올바른 지침에 따라 CPU 구성 작업은 역사적인 결과를 달성했으며 주요 모순이 바뀌었습니다. 즉, CPU의 실행 속도가 메모리 읽기 및 쓰기 속도를 천천히 초과했습니다. 그래서 매번 메모리에서 명령을 가져오는 것이 점점 더 견디기 어려워졌습니다. 그래서 1982년에 명령 캐시가 프로세서에 도입되었습니다.

CPU가 점점 더 빨라짐에 따라 충돌하는 두 당사자 간의 절충안으로 데이터 캐시도 프로세서에 도입됩니다. 그러나 이는 영구적인 해결책은 아닙니다. 모순의 주요 측면은 CPU가 포화 상태에서 실행되지 않는다는 것입니다. 그래서 1989년에 i486 프로세서는 5단계 파이프라인을 건설적으로 도입했습니다. CPU의 과잉 용량을 국내 수요를 자극해 소화하겠다는 구상이다. 한 번에 하나의 명령어만 처리하는 대신 한 번에 5개의 명령어를 처리할 수 있다.

x86 파이프라인 수준에서 성능 최적화

x86 파이프라인 수준에서 성능을 최적화하는 방법에 대해 이야기해보겠습니다

여러분은 어떻게 생각하시는지 모르겠지만 저는 이 그림을 항상 이해하는 데 어려움을 겪습니다. 간단한 이해를 제공하기 위해 각 지침을 처리할 제품으로 상상하고 5개의 처리 단계가 있는 조립 라인으로 흘러갑니다. 이를 통해 CPU의 각 프로세스는 항상 포화된 작업 부하를 유지할 수 있어 명령어 처리량과 프로그램 성능이 근본적으로 향상됩니다.
조립라인에서 발생하는 문제

위의 i486 파이프라인 다이어그램에 따라 각 코드 줄을 XOR 명령으로 간단히 추상화하면 첫 번째 명령은 파이프라인의 Fetch 단계로 들어간 다음 D1 단계로 들어가고 이때 두 번째 명령은 Fetch로 들어갑니다. 다음 머신 사이클에서 첫 번째 명령어는 D2로, 두 번째 명령어는 D1로, 세 번째 명령어는 Fetched됩니다. 지금까지는 모든 것이 정상이지만 다음 머신 사이클에서 첫 번째 명령어가 실행 단계에 들어갈 때 두 번째 명령어는 다음 단계로 계속 들어갈 수 없습니다. 왜냐하면 필요한 변수 a의 최종 결과가 첫 번째 단계에 있어야 하기 때문입니다. 명령이 실행된 후에 얻어집니다. 따라서 두 번째 명령은 파이프라인에서 차단되고 첫 번째 명령이 완료될 때까지 계속되지 않습니다. 두 번째 명령어를 실행하는 동안 세 번째 명령어도 비슷한 상황을 겪게 됩니다. 파이프라인 차단이 발생하면 명령의 파이프라인 실행이 개별 실행과 분리되며 이를 파이프라인 "버블"이라고 합니다.

시계 주기: 진동 주기라고도 합니다. 클럭 주파수(주 주파수)와 최소 시간의 역수입니다
머신 사이클: 파이프라인의 각 단계를 기본 작업이라고 하며, 기본 작업을 완료하는 데 걸리는 시간을 머신 사이클이라고 합니다
명령어 주기: 명령어를 실행하는 데 필요한 시간으로, 일반적으로 여러 기계 주기로 구성됩니다

위의 상황 외에도 거품이 발생하는 또 다른 일반적인 이유가 있습니다. 각 명령을 실행하는 데 필요한 시간(명령 주기)이 다릅니다. 간단한 명령 앞에 복잡한 명령이 오면 시간이 오래 걸리므로 간단한 명령은 복잡한 명령을 기다려야 합니다. 게다가 프로그램에 if 같은 브랜치가 있다면 어떨까요? 이러한 상황으로 인해 파이프라인이 전체 용량으로 작동할 수 없게 되어 상대적인 성능 저하가 발생합니다.

문제에 직면했을 때 사람들은 항상 문제를 해결하기 위해 더 복잡한 메커니즘을 도입하는 경향이 있습니다. 다단계 조립 라인이 그 예입니다. 복잡성은 기술 발전을 반영할 수 있지만 "복잡성" 자체는 새로운 문제입니다. 이것이 바로 모순이 결코 사라지지 않고, 기술이 발전을 멈추지 않는 이유일 것입니다. 그러나 "더 많이 배울수록 우리는 타오에게 더 많은 것을 잃게 됩니다." 점점 더 복잡해지는 메커니즘은 항상 특정 시점에 큰 돌파구를 마련하겠지만, 아마도 그 때가 아직 오지 않았을 수도 있습니다. "버블" 문제에 직면한 프로세서는 더 복잡한 솔루션을 도입했습니다. Intel은 1995년에 Pentium Pro 프로세서를 출시했을 때 비순차적 코어(OOO 코어)를 추가했습니다.

비순차 실행 코어(OOO 코어)

사실, 비순차적 실행의 개념은 매우 간단합니다. 다음 명령어가 차단되면 다음 명령어에서 실행 가능한 또 다른 명령어를 찾으면 됩니다. 하지만 이를 완료하는 것은 상당히 복잡합니다. 우선, 프로그램의 최종 결과가 순차적 실행과 일치하는지 확인하는 동시에 다양한 데이터 종속성을 식별해야 합니다. 원하는 효과를 얻으려면 병렬 실행 외에도 원하는 효과를 얻기 위해 두께를 사용하지 않는 효과를 얻기 위해 명령의 세분성도 더욱 구체화해야 합니다. 이러한 방식으로 "마이크로 작업"(마이크로 작업)이 필요합니다. , μ-ops)의 개념이 도입되었습니다. 파이프라인의 디코드 단계에서는 조립 지침이 추가로 분해되고 최종 제품은 일련의 마이크로 작업입니다.

비순차 처리 코어 이후 명령 μ-ops 처리 흐름을 소개합니다. 서로 다른 색상의 모듈은 첫 번째 그림에서 서로 다른 색상의 파이프라인 처리 단계에 해당합니다.

Fetch 단계에서는 큰 변화가 없습니다. Decode 단계에서는 4개의 명령어를 병렬로 디코딩할 수 있으며, 디코딩의 최종 결과물은 위에서 언급한 μ-ops입니다. 다음 Register Alias ​​​​Table과 Reorder Buffer는 비순차 실행 코어의 전처리 단계로 간주 될 수 있습니다.

병렬로 실행되는 마이크로 작업이나 순서 없이 실행되는 작업의 경우 동일한 레지스터를 동시에 읽고 쓸 가능성이 매우 높습니다. 따라서 프로세서 내에서 원래 레지스터는 소프트웨어 엔지니어에게 보이지 않는 내부 레지스터로 "별칭"되어 원래 동일한 레지스터에서 수행된 작업이 읽기 및 쓰기에 관계없이 일시적으로 다른 레지스터에서 수행될 수 있습니다. 기타(참고: 이를 위해서는 두 작업에 데이터 종속성이 없어야 합니다). 해당 마이크로 연산의 피연산자도 임시 앨리어스 레지스터로 변경되었습니다. 이는 공간 대 시간 전략과 동일하며 동시에 마이크로 명령어는 앨리어스 레지스터를 기반으로 변환됩니다.

그런 다음 마이크로 연산이 Reorder Buffer에 들어갑니다. 이제 마이크로명령어가 준비되었습니다. RS(Reservation Station)에 투입되어 병렬로 실행됩니다. 다이어그램에서 꽤 많은 실행 단위(포트 X)를 볼 수 있습니다. 각 실행 단위는 읽기(Load), 쓰기(Store), 정수 계산(ALU, SEE) 등 특정 작업을 수행합니다. 각 관련 마이크로명령어는 필요한 데이터가 준비된 후에 실행될 수 있습니다. 이러한 시간이 오래 걸리는 명령어와 데이터 종속성이 있는 명령어는 자체 관점에서는 아무런 변화가 없지만, 이로 인해 발생하는 차단 오버헤드는 후속 명령어의 병렬성과 잘못된 순서(진행)로 상쇄되어 실행 지점으로 분할됩니다. 부품을 생산하여 전체 처리량을 향상시킵니다.

비순차 실행 코어의 마법은 이 메커니즘의 효율성을 극대화할 수 있다는 점이며, 외부 세계에서는 명령이 순서대로 실행됩니다. 자세한 내용은 이 기사의 범위를 벗어납니다. 그러나 비순차적 실행 코어는 매우 성공적이어서 대규모 작업 부하에서도 이 메커니즘을 도입한 CPU의 비순차적 실행 코어는 여전히 대부분의 시간 동안 유휴 상태이며 포화 상태가 아닙니다. 따라서 μ-ops를 코어에 전달하기 위해 또 다른 프런트엔드(Fetch 및 Decode를 포함한 프런트엔드)가 도입됩니다. 시스템 관점에서 보면 두 개의 처리 코어로 추상화될 수 있는데, 이것이 바로 Hyper-thread입니다. N개의 물리적 코어와 2N개의 논리적 코어.

비순차 실행이 반드시 순차적 코드 실행 효과를 100% 달성하는 것은 아닙니다. 때때로 프로그래머는 실행 순서를 보장하기 위해 메모리 장벽을 도입해야 합니다.

그러나 복잡한 것은 항상 새로운 문제를 야기합니다. 이번에는 모순이 Fetch 단계로 옮겨졌습니다. 가지를 마주할 때 올바른 길을 선택하는 방법은 무엇입니까? 명령어 선택이 잘못된 경우 전체 파이프라인은 나머지 명령어가 실행될 때까지 기다렸다가 지운 다음 올바른 위치에서 다시 시작해야 합니다. 파이프라인의 높이가 깊을수록 피해가 커집니다. 후속 기사에서는 프로그래밍 수준에서 몇 가지 최적화 방법을 소개합니다.
작가 소개

Yunshan 네트워크 엔지니어인 Zhang Pan은 x86 네트워크 소프트웨어의 개발 및 성능 최적화에 중점을 두고 있으며 ONF/OPNFV/ONOS와 같은 조직 및 커뮤니티에 깊이 관여하고 있습니다.

위 내용은 x86 파이프라인 수준에서 성능 최적화의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 linuxprobe.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제