gfortran 또는 ifort 컴파일러는 두 배열의 곱을 합산할 때 SIMD 명령어를 현명하게 사용합니까?

StackOverflow https://stackoverflow.com//questions/21050913

문제

numpy로 작성된 코드가 있는데 더 나은 성능을 위해 Fortran으로 이식하는 것을 고려하고 있습니다.

제가 여러 번 수행하는 작업 중 하나는 두 배열의 요소별 곱을 합하는 것입니다.

sum(A*B)

융합된 곱셈-덧셈 명령어가 도움이 될 것 같습니다.현재 프로세서가 이러한 지침을 지원하지 않으므로 아직 테스트할 수 없습니다.그러나 FMA3(Intel Haswell 프로세서)를 지원하는 새 프로세서로 업그레이드할 수 있습니다.

"-march=native"(또는 ifort와 동등한 것)를 사용하여 프로그램을 컴파일하는 것이 컴파일러(gfortran 또는 ifort)가 SIMD 명령을 현명하게 사용하여 해당 코드를 최적화하도록 하는 데 충분한지 아는 사람이 있습니까? 아니면 제가 그렇게 생각합니까? 컴파일러나 코드를 잘 다루어야 합니까?

도움이 되었습니까?

해결책 3

Xiaolei Zhu 팁 덕분에 Gfortran은 sum(A*B)를 최적화하기 위해 융합 된 곱하기 추가를 사용한다는 것을 알고 있습니다. 예를 들어,이 코드로 :

프로그램 테스트 암시 적 없음

실제, 치수 (7) :: A, B

a= (/ 2.0, 3.0, 5.0, 7.0, 11.0, 13.0, 17.0 /)

b= (/ 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0 /)

인쇄 *, 합 (A * B)
ENDPROGRAM

i f95 sum.f95 -o sum -O3 -march=core-avx2로 컴파일 할 수 있으며 objdump -d sum | grep vfmadd 디스플레이

40088B : C4 E2 71 99 44 24 30 VFMADD132SS 0x30 (% rsp), % xmm1, % xmm0

400892 : C4 E2 69 B9 44 24 VFMADD231SS 0x34 (% rsp), % xmm2, % xmm0

400899 : C4 E2 61 B9 44 24 38 VFMADD231SS 0x38 (% rsp), % xmm3, % xmm0

4008A0 : C4 E2 59 B9 44 24 3C VFMADD231SS 0x3C (% RSP), % xmm4, % xmm0

4008a7 : C4 E2 51 B9 44 24 40 VFMADD231SS 0x40 (% RSP), % xmm5, % xmm0

4008ae : C4 E2 49 B9 44 44 VFMADD231SS 0x44 (% rsp), % xmm6, % xmm0

4008b5 : C4 E2 41 B9 44 24 48 VFMADD231SS 0x48 (% RSP), % xmm7, % xmm0

그래서 gottrran은 루프를 풀고 7 개의 융합 된 곱하기 추가 지침을 넣습니다. 더 큰, 무작위, 다중 차원 배열을 생성하는 경우 여전히 vfmadd231s가 한 번 팝업 (그래서 루프를 unroll unroll) 팝업합니다.

다른 팁

당신이 사용하는 경우 -march=native 컴퓨터에서 사용 가능한 컴파일러,컴파일러에서 생성 SIMD 지침,지만 나는 항상 사용 -xHost 프로 ifort.

하지만 난 그렇지 않은지 어떻게 그들이 그것을 할 수 있도록"현명하게".나의 느낌에 -O3 레벨 ifort 및 하드웨어를 모두 하는 경향이 지나치게 적극적인에 벡터화(즉,사용 SIMD 기능을 보다 더 자주 그들은 한다).매우 자주를 끄는 벡터화를 얻는 가장 효율적인 코드.이것은 물론,수 있습니다 또는 사실이되지 않을 수 있습니다.

그것은 일반적으로 사용하는 것이 더 좋을 벡터는 라이브러리는 최적화 이 작업입니다.당신이 사용할 수 있는 vdmul 에 MKL 나 gsl_vector_mul 에 GSL 니다.

-march=NEWARCH 에 코드를 조정한 아키텍처 NEWARCH 지만에서 실행할 수 없습니다 이전 건물입니다.사용할 수 있습니다 -mtune=NEWARCH 국가 NEWARCH 는 아키텍처의 새로운 프로세서입니다.이 코드를 생성하고 튜닝을 위한 새로운 아키텍처 그러나 아직도 실행 파일이 오래된 하나입니다.지 않기 때문에 당신은 아직 새로운 기계, -mtune 아마 당신은 무엇이 필요합니다.

와 ifort 사용할 수 있는 벡터화 보고서는 플래그를 표시하는 프로그램의 일부가되었습 벡터화.예를 들어, ifort 플래그 -vec-report=1 을 줄 것이다 당신은 그러한 정보를 컴파일하는 동안.나는 확실히 있을 것이 상응하는 플래그에 추가.

gfortran 버전 sum(a*b) 것보다 더 나은 벡터화를 제공했습니다. dot_product(a,b) 오래되어 쓸모가 없습니다.표시되는 코드는 직렬 AVX2 fma 명령어를 사용하고 있습니다.

구현에 dot_product 간접 인덱싱이나 기타 복잡함(단순 루프 자체) 없이 fma는 simd 병렬 곱셈과 덧셈 명령어의 조합보다 느릴 가능성이 높습니다. 왜냐하면 곱셈은 지연 시간이 중요한 경로에서 수행될 수 있기 때문입니다.dot_product에 대한 병렬 simd fma의 gfortran 사용은 더 복잡한 경우에 매우 효과적일 수 있습니다.

다음 중 하나가 필요합니다. -O2 -ftree-vectorize -ffast-math -march=native or -O3 -ffast-math -march=native (적절한 벡터 길이도 포함) 이를 벡터화하면 gfortran이 OpenMP 병렬 영역 내에서 벡터화하지 못할 수 있습니다.

gfortran 4.9에서는 -ftree-Vectorizer-verbose 옵션이 삭제된 것으로 보입니다.-fdump-tree-vect는 다양한 주요 gcc 버전에 대해 선택된 다른 이름을 사용하여 벡터화 패스의 세부 정보를 .vect 파일에 기록합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top