라이브러리 함수에 대한 FLOP 카운팅


13

간단한 함수에서 FLOP의 수를 평가할 때 종종 기본 산술 연산자를 계산하는 식으로 내려갈 수 있습니다. 그러나 짝수 나누기가 포함 된 수학적 진술의 경우이를 수행 할 수 없으며 덧셈과 곱셈 만있는 함수의 FLOP 카운트와 비교할 수있을 것으로 기대합니다. 작업이 라이브러리에서 구현되면 상황이 더욱 악화됩니다. 따라서 특수 기능의 성능에 대한 합리적인 개념을 갖는 것이 필수적입니다.

특별한 기능으로 우리는 다음과 같은 것을 의미합니다.

  • exp ()
  • sqrt ()
  • sin / cos / tan ()

일반적으로 시스템 라이브러리에서 제공합니다.

이들의 복잡성을 결정하는 것은 이들 중 다수가 적응적이고 입력 의존적 복잡성을 갖는다는 사실에 의해 더욱 혼란스러워진다. 예를 들어, 숫자 적으로 안정적인 exp () 구현 은 종종 적응 적으로 크기를 조정하고 조회를 사용합니다. 나의 첫인상은이 경우에 최선의 방법은 함수의 평균 행동을 확인하는 것입니다.

물론이 전체 토론은 아키텍처에 크게 의존합니다. 이 논의를 위해 우리는 전통적인 범용 아키텍처로 제한하고 특수 기능 단위 (GPU 등)가있는 아키텍처를 제외 할 수 있습니다

시스템 대 시스템 비교를 위해 특정 아키텍처에 대해 이들을 표준화 하려는 상당히 간단한 시도를 찾을 수 있지만, 방법 대 방법 성능에 관심이있는 경우 이는 허용되지 않습니다. 이러한 기능의 FLOP 복잡성을 결정하기위한 어떤 방법론이 수용 가능한 것으로 간주됩니까? 주요 함정이 있습니까?


피터, 간단히 말해 수학 라이브러리에서 제공하는 몇 가지 유용한 함수 예제를 제공하지만 부동 소수점 나누기는 일반적으로 부동 소수점 단위로 구현됩니다.
Aron Ahmadia

감사! 나는 명확하지 않았다. 더 나은 대비를 제공하기 위해 방금 편집했습니다.
Peter Brune

sin, cos 및 sqrt가 모두 x86 명령어의 x87 부동 소수점 하위 집합에서도 실제로 구현되어 있다는 사실에 놀랐습니다. 나는 당신의 요점을
얻는다고

@AronAhmadia 10 년 이상 x87을 사용할 이유는 없었습니다. 나누고 sqrt()SSE / AVX에 있지만 더하기 및 곱하기보다 훨씬 오래 걸립니다. 또한 Sandy Bridge AVX에서 벡터화가 제대로되지 않아 SSE 명령어보다 두 배 (폭의 절반)가 소요됩니다. 예를 들어, 배정 밀도 AVX (4 배의 폭)는주기 당 8 개 플롭 인주기마다 8 배의 팩을 곱하고 팩을 추가 할 수 있습니다 (메모리에 종속성 또는 중단이 없다고 가정). 이러한 "4 플롭"을 수행하기 위해서는 20에서 44 사이클 사이의 간격이 필요합니다.
Jed Brown

sqrt ()는 PowerPC에서 선택 사항입니다. 이 아키텍처의 많은 임베디드 칩은 명령을 구현하지 않습니다 (예 : Freescale MPC5xxx 시리즈).
Damien

답변:


10

"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에 대한 정확한 의미는 어디에도 문서화되어 있지 않습니다. 대부분의 경우, 중복 가능성이 거의 없다고 생각하지만 매뉴얼의 문구는 여러 스레드 가이 명령에서 중복 가능성을 높일 수 있다고 제안합니다. 우리는 우리가를 시작하면 피크 퍼 칠 수 vaddpdvmulpd팔의 총 매 사이클에 사이클 당 슬리퍼. 고밀도 행렬-행렬 곱하기 ( dgemm)는이 피크에 상당히 가깝게 도달 할 수 있습니다.

특별한 지시를 위해 플롭을 세면 FPU가 얼마나 차지하는지 살펴 보겠습니다. 입력 범위 vdivpd에서 평균 24 사이클이 완료되어 단위 M을 완전히 차지했지만 추가 사이클 (사용 가능한 경우)이 절반 사이클 동안 동시에 실행될 수 있다고 주장하십시오. FPU는 해당 사이클 (24 개 팩)과 24 개 팩 추가 (완전히 인터리브 vaddpdvmulpd) vdivpd를 수행 할 수 있지만 , 12 개 추가 팩을 추가하는 것이 최선입니다. 분할을 수행하는 가장 좋은 방법이 하드웨어 (합리적)를 사용하는 것이라고 가정하면 vdivpd36 개의 팩형 "플롭"으로 계산할 수 있으며, 각 스칼라 분할을 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인라인 어셈블리 스 니펫이 있는 명령어를 사용하여 사이클 카운터를 직접 읽을 수 있습니다 .


7

하드웨어 카운터 및 간단한 테스트 프로그램에 대한 액세스 권한을 부여 하는 PAPI를 사용하여 실제 시스템에서이를 계산할 수 있습니다. 내가 가장 좋아하는 PAPI 인터페이스 / 래퍼는 IPM (Integrated Performance Monitor)이지만 다른 솔루션이 있습니다 ( 예 : TAU ). 이것은 상당히 안정적인 방법-방법 비교를 제공해야합니다.


4

나는 당신이 묻는 것처럼이 질문에 대답 할 것입니다.

"숫자 선형 대수에서 나온 전통적인 곱하기 추가 캐리 FLOP 카운트 대신 특수 함수에 크게 의존하는 알고리즘의 성능을 분석적으로 비교하거나 예측하는 방법"

첫 번째 전제에 동의합니다. 많은 특수 함수의 성능은 아키텍처에 따라 다르며 일반적으로 이러한 각 함수를 일정한 비용으로 처리 할 수 ​​있지만 상수의 크기는 동일한 프로세서에서 두 프로세서 사이에서도 달라질 수 있습니다 회사는 다르지만 아키텍처가 다릅니다 (참조 : Agner Fog의 명령 타이밍 표 참조).

그러나 비교의 초점이 개별 부동 소수점 연산의 비용에 있어야한다는 데 동의하지 않습니다. FLOP 계산은 여전히 ​​어느 정도 유용하지만 두 가지 잠재적 알고리즘을 비교할 때 특수 함수의 비용을 덜 관련시킬 수있는 훨씬 더 중요한 고려 사항이 있다고 생각합니다.이를 비교하기 전에 먼저 명시 적으로 검사해야합니다. 부동 소수점 연산 :

  1. 확장 성-병렬 아키텍처에서 효율적으로 구현할 수있는 작업을 특징으로하는 알고리즘은 가까운 미래의 과학 컴퓨팅 분야를 지배 할 것입니다. 더 나은 "확장 성"을 가진 알고리즘, 더 낮은 통신, 더 적은 동기화 요구 또는 더 나은 자연로드 밸런스를 통한 알고리즘은 더 느린 특수 기능을 사용할 수 있으므로 소수의 프로세스에 대해서는 느려질 수 있지만 결국에는 그 수를 따라 잡을 것입니다 프로세서 수가 증가합니다.

  2. 시간의 지역적 참조 – 알고리즘이 작업간에 데이터를 재사용하여 프로세서가 불필요한 메모리 트래픽을 피할 수 있습니까? 알고리즘이 통과하는 각 수준의 메모리 계층 구조는 각 메모리 액세스에 다른 크기의 비용을 추가합니다. 결과적으로, 밀도가 높은 특수 연산을 갖는 알고리즘은 더 큰 메모리 영역에서 동일한 수의 간단한 함수 연산을 갖는 알고리즘보다 훨씬 빠를 것입니다.

  3. 메모리 공간-이전 지점과 밀접한 관련이 있지만 컴퓨터가 점점 커짐에 따라 코어 당 메모리 양은 실제로 하향 추세입니다. 작은 메모리 공간에는 두 가지 이점이 있습니다. 첫 번째는 소량의 프로그램 데이터가 프로세서 캐시 내에 완전히 들어갈 수 있다는 것입니다. 두 번째는 매우 큰 문제의 경우 더 작은 메모리 공간을 가진 알고리즘이 프로세서 메모리에 적합 할 수있어 컴퓨터의 성능을 초과하는 문제를 해결할 수 있다는 것입니다.


FLOPS / sec를 알면 어느 병목 현상 (메모리, 통신)을 상당히 잘 구분할 수 있다고 주장합니다. 예를 들어, Matvecs를 수행하는 데 많은 시간을 소비하는 Newton-Krylov 방법을 고려하십시오. Matvecs는 매트릭스 엔트리 당 FLOP 또는 2 개를 수행합니다. 조립되지 않은 스무더는 더 잘 할 수있는 잠재력이 있습니다. Jed와 나는 이것에 대해서도 이야기하고 있으며, 대체 개념은 FLOP 바운드 계산에 얼마나 많은 사이클을 소비하는지 보는 것입니다. 그러나이를 위해서는 아주 세밀한 모니터링이 필요할 수 있으며 총 FLOPS / sec가 더 실용적 일 수 있습니다.
Peter Brune

Aron,이 답변의 대부분은 다른 질문에 대답하기 위해 Peter의 질문을 우회하는 것 같습니다 : scicomp.stackexchange.com/questions/114
Jed Brown

@JedBrown, 나는 훨씬 더 확실한 답변을 모아 주셔서 감사합니다.
Aron Ahmadia

0

왜 퍼를 세는가? 모든 작업에 대한 사이클을 계산하면 보편적 인 것이 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.