"flop"의 동일한 비동기식 정의에 따라 플롭 수를 계산하는 대신 코드의 FPU 바인딩 방식 또는 FPU를 얼마나 효율적으로 사용하는지 평가하는 방법이 필요합니다. 다시 말해, 모든 부동 소수점 단위가주기마다 최대 용량으로 실행되는 경우 동일한 피크에 도달하는 메트릭을 원합니다. Intel Sandy Bridge에서이 문제가 어떻게 발생하는지 살펴 보겠습니다.
하드웨어 지원 부동 소수점 연산
이 칩은 AVX 명령어를 지원 하므로 레지스터의 길이는 32 바이트입니다 (4 배를 유지). 슈퍼 스칼라 아키텍처를 사용하면 다음 번 사이클에서 새 명령을 시작할 수 있지만 대부분의 산술 명령을 완료하는 데 몇 사이클이 걸리므로 명령이 겹칠 수 있습니다. 이러한 의미는 일반적으로 대기 시간 / 역 처리량을 쓰면 약어로 표시됩니다. 5/2 값은 명령을 완료하는 데 5주기가 걸리지 만 다른주기마다 새 명령을 시작할 수 있습니다 (피연산자를 사용할 수 있다고 가정하면 데이터가 없음) 의존성 및 메모리를 기다리지 않음).
코어 당 3 개의 부동 소수점 산술 단위가 있지만 세 번째는 우리의 논의와 관련이 없습니다. 주요 함수는 덧셈과 곱셈이므로 관련 두 개를 A와 M 단위라고합니다. 예제 지침 ( Agner Fog의 테이블 참조 )
vaddpd
: 패킹 된 추가, 1주기 동안 단위 A를 차지하고 대기 시간 / 역 처리량은 3/1입니다.
vmulpd
: 압축 곱셈, 단위 M, 5/1
vmaxpd
: 포장 선택 쌍별 최대 값, 단위 A, 3/1
vdivpd
: 패킹 분할, 입력 M에 따라 단위 M (및 일부 A), 21/20 ~ 45/44
vsqrtpd
: 포장 된 제곱근, 일부 A 및 M, 입력에 따라 21/21 ~ 43/43
vrsqrtps
: 단 정밀 입력을위한 압축 정확도가 낮은 역수 제곱근 (8 floats
)
겹칠 수 vdivpd
있고 vsqrtpd
미묘하고 AFAIK에 대한 정확한 의미는 어디에도 문서화되어 있지 않습니다. 대부분의 경우, 중복 가능성이 거의 없다고 생각하지만 매뉴얼의 문구는 여러 스레드 가이 명령에서 중복 가능성을 높일 수 있다고 제안합니다. 우리는 우리가를 시작하면 피크 퍼 칠 수 vaddpd
와 vmulpd
팔의 총 매 사이클에 사이클 당 슬리퍼. 고밀도 행렬-행렬 곱하기 ( dgemm
)는이 피크에 상당히 가깝게 도달 할 수 있습니다.
특별한 지시를 위해 플롭을 세면 FPU가 얼마나 차지하는지 살펴 보겠습니다. 입력 범위 vdivpd
에서 평균 24 사이클이 완료되어 단위 M을 완전히 차지했지만 추가 사이클 (사용 가능한 경우)이 절반 사이클 동안 동시에 실행될 수 있다고 주장하십시오. FPU는 해당 사이클 (24 개 팩)과 24 개 팩 추가 (완전히 인터리브 vaddpd
및 vmulpd
) vdivpd
를 수행 할 수 있지만 , 12 개 추가 팩을 추가하는 것이 최선입니다. 분할을 수행하는 가장 좋은 방법이 하드웨어 (합리적)를 사용하는 것이라고 가정하면 vdivpd
36 개의 팩형 "플롭"으로 계산할 수 있으며, 각 스칼라 분할을 36 "플롭"으로 계산해야 함을 나타냅니다.
왕복 제곱근을 사용하면, 특히 전체 정확도가 필요하지 않거나 입력 범위가 좁은 경우 하드웨어를 이길 수 있습니다. 위에서 언급했듯이, vrsqrtps
명령은 매우 저렴하므로 (단일 정밀도의 경우) vrsqrtps
정리를 위해 하나 또는 두 개의 뉴턴 반복을 수행 할 수 있습니다. 이 뉴턴 반복은 단지
y *= (3 - x*y*y)*0.5;
이러한 작업 중 많은 작업을 수행해야하는 경우 순진한 평가보다 훨씬 빠릅니다 y = 1/sqrt(x)
. 하드웨어에 가까운 역수 제곱근을 사용하기 전에 일부 성능에 민감한 코드는 유명한 정수 연산 을 사용 하여 뉴턴 반복에 대한 초기 추측을 찾았습니다.
라이브러리 제공 수학 함수
라이브러리 제공 수학 함수에 유사한 휴리스틱을 적용 할 수 있습니다. SSE 명령어의 수를 결정하기 위해 프로파일 링 할 수 있지만, 우리가 논의했듯이, 그것은 전체 이야기가 아니며 특수 기능을 평가하는 데 모든 시간을 소비하는 프로그램은 정점에 가깝지 않은 것처럼 보일 수 있습니다. FPU를 제어 할 때 항상 시간을 소비한다고 말하면 유용하지 않습니다.
좋은 벡터 수학 라이브러리를 기준으로 사용하는 것이 좋습니다 (예 : Intel의 VML, MKL의 일부). 각 호출에 대한 사이클 수를 측정하고 해당 사이클 수에 대해 최대 달성 가능 플롭을 곱하십시오. 따라서 패킹 된 지수가 평가하는 데 50주기가 걸리면 레지스터 폭의 100 플롭 횟수로 계산합니다. 불행히도 벡터 수학 라이브러리는 호출하기가 어려우며 모든 특수 함수를 갖지 않으므로 스칼라 수학을 할 수 있습니다.이 경우 가상 스칼라 지수를 100 플롭으로 계산합니다 (아마도 여전히 50을 차지하더라도) 모든 지수를 평가하는 데 소비되는 경우 "피크"의 25 % 만 얻게됩니다.
다른 사람들이 언급했듯이 PAPI 또는 다양한 인터페이스를 사용하여 사이클 및 하드웨어 이벤트 카운터를 계산할 수 있습니다. 간단한 사이클 카운팅을 위해 rdtsc
인라인 어셈블리 스 니펫이 있는 명령어를 사용하여 사이클 카운터를 직접 읽을 수 있습니다 .