프로그램의 한 data dependency chain
에 포함된 Latency
의 합이 T
라면, 프로그램은 실행하는 데 적어도 T
사이클 소요
프로그램 실행에 특정 연산이 N
번 필요할 때, 프로그램 실행에 적어도 N / (throughput bound) = N * I / C
만큼의 사이클 소요
프로그램이 사용 가능한 레지스터 수를 넘어서는 병렬성을 가지면 컴파일러는 메모리에 임시값을 저장하고 읽어오게 됨 (보통 런타임 스택에 지역변수 형태로 저장)
프로세서가 조건 분기를 잘못 예측했을 때 상당한 Misprediction Penalty
가 발생함
프로세서는 speculative execution
을 수행 (일단 예측한 브랜치 타겟을 실행하고, 레지스터와 메모리 변경은 분기가 확정될 때까지 미룸, 만약 분기 예측에 실패하면 연산 결과를 모두 버리고 알맞은 명령어를 다시 실행)
conditional move (conditional data transfers)
를 사용하면 잘못된 분기 예측의 위험으로부터 벗어날 수 있음
예측 가능한 분기에 대해 너무 걱정하지 말자
분기 패턴이 단순하거나 long-term trend
가 있는 경우 프로세서는 분기를 잘 예측함
Conditional Move
구현에 적합한 코드를 작성하자
조건문
보다는 삼항 연산자
와 같은 형태로 작성하면 GCC
가 conditional move
형태로 코드를 변환한다.
load, store unit
은 각각 pending request
를 저장할 수 있는 버퍼
를 가지고, 매 clock cycle
마다 연산 하나를 시작 가능
Load
명령어도 Latency
가 존재 (reference machine의 L1 cache access time
= 4 cycles)