2014-11-04 2 views
0

OS를 Ubuntu 14.04로 업데이트하고 Gfortran 4.8.2로 재구성 한 후 병렬 포트란 프로그램이 두 배 이상 느리게 실행됩니다. 이전 OS에서 컴파일 할 때 gprof에 대한 프로파일 링 정보를 저장하지 않았기 때문에 코드의 어느 부분이 느려지는지 측정하는 것은 불행히도 더 이상 가능하지 않습니다 (OS를 다운 그레이드하지 않고).Ubuntu 14.04로 업데이트 한 후 재 작성된 Fortran 코드가 두 번 느립니다.

프로그램이 많은 행렬 반전을하기 때문에 모든 프로그램의 속도가 느려지는 방식으로 우분투 12와 14 사이에서 하나의 라이브러리 (LAPACK?) 또는 프로그래밍 인터페이스 (OpenMP?)가 업데이트되었다고 생각합니다. 나는 이것이 이미 누군가에게 알려진 일반적인 문제라고 생각한다. 우분투 12 또는 13으로 다시 다운 그레이드하는 것 외에도 빠른 포트란 코드로 돌아갈 수있는 해결책은 무엇입니까?

모든 라이브러리는 apg-get을 사용하는 저장소에서 설치되었으므로 시스템을 apt-get dist-upgrade으로 업그레이드 할 때 업그레이드해야합니다. 그러나 실제로 최신 버전인지 확인하고 빌드 할 수는 있습니다. 기스로부터.

나는 Steabert의 조언에 따라 현재 코드를 프로파일 링했다 : gfortran -pg으로 다시 컴파일하고 gprof으로 성능을 점검했다. 이 프로그램은 성능 향상없이 ​​f90으로 변환 된 일부 오래된 F77 서브 루틴을 호출 할 때 의심 스러웠습니다. 나는 제안 된 플래그로 플레이하고 하나의 프로그램 반복의 시간을 비교했다 : 플래그 -fno-aggressive-loop-optimizations, -llapack-lblas은 중요한 성능 향상을 가져 오지 않았다. Flags -latlas, -llapack_latlas-lf77blas은 라이브러리가 존재하고 올바른 경로에 있더라도 컴파일되지 않습니다 (/usr/bin/ld: cannot find -lf77blas 등). 컴파일러 플래그 재생과 성능 분석 모두 내 첫 번째 추측 (매트릭스 반전, LAPACK 등과 관련된 속도 저하가 잘못 되었음)이 잘못되었음을 암시합니다. 오히려 무거운 선형 대수학이 수행되지 않는 코드의 일부에서 느려지는 것 같습니다. objdump my_exec -s 사용하기 OS 업그레이드 전에 내 프로그램이 원래 gfortran 4.6.3으로 컴파일되었음을 알았습니다. 현재 gfortran (4.8.2)을 사용하는 대신. 이전 컴파일러로 코드를 컴파일하려고 시도 할 수있었습니다.

+2

을이 대답하기 어려울 것이다. 병목 지점과 코드의 어느 부분이 느려졌는지 측정 했습니까? 그렇지 않다면 지금하십시오. –

+2

물론 LAPACK과 BLAS를 직접 만들지 못하게하는 것은 없습니다. ATLAS 또는 OpenBLAS와 같은 최적화 된 BLAS 라이브러리를 사용해야합니다. 그들은 심지어 당신의 저장소에 존재할 수도 있습니다. –

+0

편집 내용 : ** 어떤 ** 라이브러리를 사용하십니까? 무엇보다 BLAS 구현을 사용합니까? 패키지 관리자에서 "BLAS"를 검색하면 더 많은 패키지가 있습니다. –

답변

1

아마 100 % 만족스러운 대답은 아니지만 성능 문제가 해결되었을 것입니다. 그래서 여기에 :

나는 GDB를 사용하기로 결정했다. (Valgrid가 나에게 도움이 안된다.) "gdb myprogramname"으로 실행되고, GDB 프롬프트에 "run"을 입력하여 프로그램을 실행했다. ctr + C로 일시 중지되었으며 스레드가 "정보 스레드"로 수행중인 작업을 확인한 후 "계속 진행"을 계속 진행했습니다. 나는이 프로그램을 무작위로 여러 번 사용하여 프로그램이 대부분의 시간을 소비하는 일종의 통계를 만들었습니다. 곧 gprof가 찾은 것, 즉 내 프로그램이 f90으로 번역 된 기능에 많은 시간을 투자하고 있음을 확인했습니다. 그러나 이제는이 함수 내부에서 특히 오랜 시간이 걸리는 수학 연산이 C 함수 e_powf.c에 대한 호출에서 제안한 것처럼 지수 연산임을 알게되었습니다. 내 함수 (해수 상태 방정식)는 T**3, T**4과 같은 용어로 구성된 다항식을 많이 포함하고 있습니다. e_powf.c를 호출하지 않고 코드의 성능이 향상되었는지 확인하려면 T**2의 모든 조건을 T*T으로 변경했습니다. T*T*T 등이 여기에 T**3는 그것이 얼마나 함수의 추출하기 전에 :

!   RW =  999.842594 + 6.793952E-2*T - 9.095290E-3*T**2+ 1.001685E-4*T**3 - 1.120083E-6*T**4 + 6.536332E-9*T**5 

어떻게 지금 : (결과

RW =  999.842594 + 6.793952E-2*T - 9.095290E-3*T*T+ 1.001685E-4*T*T*T - 1.120083E-6*T*T*T*T + 6.536332E-9*T*T*T*T*T 

, 내 프로그램은 다시 배 빠른 실행 즉, , OS를 업그레이드하기 전과 같음). 이 방법으로 성능 문제를 해결할 수 있지만 OS 업그레이드 또는 4.6.3에서 4.8.2 로의 컴파일러 변경과 관련이 있다면 100 % 확신 할 수는 없습니다.비록 현재의 성능이 pre-OS-upgrade와 비슷하지만 실제로는 그렇게해야한다고 제안하고 있습니다.

불행히도 "locate e_powf"는 내 시스템에서 결과를 얻지 못합니다. gfortran 컴파일러의 바이너리 부분 인 것처럼 보이지만 소스 코드는 제공되지 않습니다. 인터넷 검색에 따르면, e_powf.c 자체가 최근에 업데이트 된 것 같지 않습니다. (아마도 http://koala.cs.pub.ro/lxr/#glibc/sysdeps/ieee754/flt-32/e_powf.c과 같은 인터넷에서 발생합니다) 우분투 12에서 14로 변경되거나 gfortran 4.6.3에서 4.8.2로 변경된 것 같습니다. 이 함수가 사용되는 방식에 다소 미묘한 것처럼 보입니다.

나는 약간의 성능 향상 및 대부분의 사람들이 그것에 대해 의심 보인다 데려 와야한다 T*T 대신 T**2 등을 사용하는 경우에 대해 인터넷에서 몇 가지 토론을 찾을 수 있기 때문에 (예 : http://computer-programming-forum.com/49-fortran/6b042075d8c77a4b.htm를 또는 유래 닫힌 질문 : Tips and tricks on improving Fortran code performance) I double은 내 결과를 확인했기 때문에 변수의 제품을 사용하는 것이 (적어도 e_powf.c를 호출하는 것을 피하는 것) 적어도 gfortran 4.8.2 (이유가 무엇인지)와 비교하여 지수보다 빠르다고 확신 할 수 있다고 말할 수 있습니다.

댓글을 달아 주신 모든 분들께 고마워요. 제게 많은 도움이되었습니다. 당신은 당신이 같은 선 위에 쓸 수 있습니다 더 개선해야 할 경우

+1

이것은 매우 이상합니다. 컴파일러는이를 최적화해야합니다.어떤 최적화를 사용하셨습니까? http://goo.gl/T5Fm0p을 참조하십시오. –

+0

다음과 같이 컴파일했습니다 :'gfortran -v -g -fbounds-check -folder -o .f90 ahoi_paralind.f90 woa_basis.f90 ahoi_eta.f90 ahoi_dist.f90 ahoi_inverse.f90 ahoi_opest.f90 ahoi_corrclim.f90 ahoi_freezt.f90 ahoi_mapping.f90 ahoi_chnetcdf.f90 woa_adjust.f90 densitychange.f90 dgradcheck.f90 findsal.f findtemp.f ptemptotemp.f roundoff.f90 salest.f -I/usr/include/-lnetcdff -lnetcdf' – nukimov

+1

전혀 최적화하지 않습니다! 즉시 https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html 및 http://en.wikipedia.org/wiki/Optimizing_compiler를 읽어보십시오! '-O1'에서'-O5'까지 모든 레벨을 시도하십시오! –

0
RW =  999.842594 + 6.793952E-2*T - 9.095290E-3*T*T+ 1.001685E-4*T*T*T - 1.120083E-6*T*T*T*T + 6.536332E-9*T*T*T*T*T 

: 손에 코드없이

T2=T*T 
T3=T2*T 
T4=T3*T 
T5=T4*T 
RW=999.842594 + 6.793952E-2*T - 9.095290E-3*T2+ 1.001685E-4*T3 - 1.120083E-6*T4 + 6.536332E-9*T5