AVX2 및 FMA3이있는 i5-4250U가 있습니다. 내가 작성한 Linux에서 GCC 4.8.1의 고밀도 행렬 곱셈 코드를 테스트하고 있습니다. 아래는 내가 컴파일하는 세 가지 차이점 목록입니다.
SSE2: gcc matrix.cpp -o matrix_gcc -O3 -msse2 -fopenmp
AVX: gcc matrix.cpp -o matrix_gcc -O3 -mavx -fopenmp
AVX2+FMA: gcc matrix.cpp -o matrix_gcc -O3 -march=native -fopenmp -ffast-math
SSE2와 AVX 버전은 성능이 분명히 다릅니다. 그러나 AVX2 + FMA는 AVX 버전보다 좋지 않습니다. 나는 이것을 이해하지 못한다. FMA가 없다고 가정하면 CPU 피크 플롭의 80 % 이상을 얻었지만 FMA로 훨씬 더 잘 할 수 있다고 생각합니다. 행렬 곱셈은 FMA로부터 직접 이익을 얻을 수 있습니다. AVX에서 본질적으로 한 번에 8 개의 도트 제품을 수행하고 있습니다. 내가
march=native
를 확인할 때
그것은 제공합니다 :
cc -march=native -E -v - </dev/null 2>&1 | grep cc1 | grep fma
...-march=core-avx2 -mavx -mavx2 -mfma -mno-fma4 -msse4.2 -msse4.1 ...
그래서 활성화 된 것을 볼 수 있습니다 (
-mfma
를 추가했는지 확인하십시오)
그러나 그것은 차이가 없습니다).
ffast-math
편안한 부동 소수점 모델 사용 방법 SSE/AVX를 사용한 FMA (Fused Multiply-Add) 지침
수정 :
Mysticial의 의견을 바탕으로 _mm256_fmadd_ps를 사용했으며 이제 AVX2 + FMA 버전이 더 빠릅니다.컴파일러가 왜이 작업을 수행하지 않는지 잘 모르겠습니다.이제 1000x1000 이상의 매트릭스에 대해 약 80GFLOPS (FMA가없는 피크 플롭의 110 %)가 표시됩니다. 내 피크 플롭 계산을 신뢰하지 않는 사람이 여기에 내가 한 일입니다.
peak flops (no FMA) = frequency * simd_width * ILP * cores
= 2.3GHZ * 8 * 2 * 2 = 73.2 GFLOPS
peak flops (with FMA) = 2 * peak flops (no FMA) = 146.2 GFLOPS
두 코어를 모두 사용할 때 터보 모드의 CPU는 2.3GHz입니다. Ivy Bridge는 동시에 하나의 AVX 곱셈과 하나의 AVX 추가를 수행 할 수 있기 때문에 ILP에 대해 2를 얻습니다 (그리고 이것을 보장하기 위해 루프를 여러 번 풀었습니다).
FMA가있는 피크 플롭의 약 55 % 만 얻었습니다. 왜 그런지 모르겠지만 적어도 지금 무언가를보고 있습니다.
한 가지 부작용은 내가 믿는 것으로 알려진 간단한 행렬 곱셈 알고리즘과 비교할 때 작은 오류가 발생한다는 것입니다. FMA는 일반적으로 두 가지가 아닌 하나의 반올림 모드 만 가지고 있기 때문에 (IEEE 부동 소수점 규칙이 더 나은 경우에도 아이러니하게 위반합니다)
수정 :
누군가 다시 실행해야합니다 사이클 당 이론적으로 최대 4 개의 FLOP를 달성하려면 어떻게해야합니까? 그러나 Haswell을 사용하면 사이클 당 8 개의 이중 부동 소수점 FLOPS를 수행하십시오.
수정
실제로 Mysticial은 FMA3를 지원하기 위해 프로젝트를 업데이트했습니다 (위의 링크에서 그의 답변 참조). Linux 버전이 FMA 지원으로 컴파일되지 않았기 때문에 MSVC2012를 사용하여 Windows8에서 그의 코드를 실행했습니다. 결과는 다음과 같습니다.
Testing AVX Mul + Add:
Seconds = 22.7417
FP Ops = 768000000000
FLOPs = 3.37705e+010
sum = 17.8122
Testing FMA3 FMA:
Seconds = 22.1389
FP Ops = 1536000000000
FLOPs = 6.938e+010
sum = 333.309
이중 부동 소수점에 대한 FMA3의 경우 69.38 GFLOPS입니다. 단일 부동 소수점의 경우 138.76 SP GFLOPS가되도록 배가해야합니다. 내 피크는 146.2 SP GFLOPS라고 계산합니다.이것은 피크의 95 %입니다!즉, GEMM 코드를 상당히 개선 할 수 있어야합니다 (이미 Eigen보다 훨씬 빠르지 만).
- 답변 # 1
- 답변 # 2
다음 컴파일러 옵션은
_mm256_add_ps(_mm256_mul_ps(a, b), c)
를 계약하기에 충분합니다. 지금 단일 fma 명령어로 (예 :vfmadd213ps
) ) :GCC 5.3: -O2 -mavx2 -mfma Clang 3.7: -O1 -mavx2 -mfma -ffp-contract=fast ICC 13: -O1 -march=core-avx2
나는
/O2 /arch:AVX2 /fp:fast
를 시도 MSVC와 계약을 맺었지만 여전히 계약되지 않습니다 (놀랍습니다). MSVC는 스칼라 연산을 계약합니다.GCC는 최소한 GCC 5.1부터 시작했습니다.
<시간> 비록 pyzwyz 일부 컴파일러에서이 최적화를 위해충분입니다.항상-O1
이상을 사용하십시오. 전체 성능을 위해, 바람직하게는-O2
프로필 가이드 최적화도 제공합니다.그리고 코드에 문제가 없다면
-O3 -march=native -flto
.-ffast-math
- c++ : 프로그램은 PC의 GCC 7.5에서 작동하지만 온라인 컴파일러에서는 작동하지 않습니다.
- c++ : 인덱싱을 위해 [] 대신 연산자() 오버로딩
- c++ : 종속성이 필요하지만 이미 설치됨
- c++ : GCC 및 MSVS를 사용한
의 벤치마크 기능 - c++ : Raspian Bullseye와 함께 log4cpp와의 연결이 실패함
- java : 오류 ld 1로 인해 CodeBlock의 프로젝트를 빌드할 수 없습니다.
- GCC/ICC를 사용하는 C++에서 템플릿 매개변수를 사용한 이식 가능한 루프 언롤링
- c++ : __POSIX_VISIBLE이 cygwin에서 내 pthreading을 망치고 있습니다.
- c++ : 정적으로 연결된 종속성이 있는 공유 라이브러리
- c++ : Rcpp 및 기타 도구용 Mac M1 Monterey에 컴파일러 설치
여기서 질문의 아주 작은 부분에만 답하십시오.
_mm256_add_ps(_mm256_mul_ps(areg0,breg0), tmp0)
를 쓰면 gcc-4.9는 인라인 asm과 거의 비슷하게 처리하고 많이 최적화하지는 않습니다.areg0*breg0+tmp0
로 교체하면 , gcc와 clang에서 모두 지원되는 구문 인 경우 gcc는 최적화를 시작하고 가능한 경우 FMA를 사용할 수 있습니다. gcc-5,_mm256_add_ps
의 개선 예를 들어, 이제+
를 사용하는 인라인 함수로 구현되었습니다. 내장 함수가있는 코드도 최적화 할 수 있습니다.