[질문] 포트란 컴파일러에 따른 계산결과 차이

hackeryoon의 이미지

안녕하세요.
포트란을 이용하여 유체역학 및 물질순환계산을 하고 있습니다.
지금까지는 윈도우에서 컴팩 비주얼 포트란으로 계산을 해 왔습니다.
그러다 새로 온 연구실에서 유닉스(AIX)의 XL Fortran을 사용하고 있어서
동일한 소스로 계산을 하였습니다만 계산결과가 많이 차이가 나더군요.
그래서 최근 입문하게 된 리눅스(Ubuntu)의 gFortran으로 계산한 결과
이것 역시 계산결과가 다르더군요.
즉, Compaq Visual Fortran 6.6, XL Fortran, gFortran 모두 다른 결과를 보입니다.
특히 컴팩의 경우 나머지 둘과는 엄청난 차이를 보입니다.
포트란 소스에 문제가 있는 것일까요?
아님 컴파일러 차이에 따른 다른 뭔가가 있는 것인가요?
계산 결과를 일치시킬 수 있는 방법은 없을까요?
이런 문제에 경험이 있으시거나 해결책을 아시면 조언 부탁드립니다.
프로그래밍을 전문적으로 배우지 않은 입장이다 보니 앞이 막막합니다.
포트란이라고 해봤자, 코딩되어진 모델을 보고 이해하고 간단히 수정해서 계산할 수 있는 정도입니다.
즉, 정석대로 기초부터 배운 것이 아니라 전공공부를 하면서 하나씩 익혀나간 것 뿐이 없네요.
지금부터라도 차근차근 공부해 보고자 합니다.
직접적인 답이 아니더라도 해결하기 위해 OO가 필요하다던지
제가 공부해야하는 부분이 있다면 알려주시면 감사하겠습니다.

moonend의 이미지

오류가 나는 상황을 최대한 간단히 꾸며주시기 바랍니다.
포트란은 지금도 계속 표준을 수정하고 있는 살아있는 언어이기 때문에 버전 정보나 기타 내용이 있어야 그나마 자료를 찾기 쉽습니다.

hackeryoon의 이미지

moonend님 댓글 감사합니다. 하지만, 댓글을 이해하기엔 제 내공이 부족한가 봅니다..ㅜㅜ
우선 계산을 할 때 오류가 나는 것은 아닙니다.
정상적으로 오류없이 계산 후 Output파일을 보면 출력값이 차이가 나는 것입니다.
따로 확인해봐야 하는 것이 있나요?
버전정보는 컴팩의 경우 비주얼 포트란 6.6이고,
유닉스는 AIX 5.3에서 XL Fortran을 사용합니다만, 버전 확인하는 방법도 모르겠네요.ㅜㅜ
리눅스는 우분투 8.10에서 gfortran 4.3을 사용하고 있습니다.
간단한 소스코드라고 하시면 어떤 걸 말씀하시는지;;
그리고 기타내용이라고 하시면 어떤 걸 말씀하시는지;;
잘 모르겠습니다.
모를 땐 몰랐는데.....
본격적으로 포트란 공부를 해볼려고 하니 제가 아는 게 하나도 없다는 생각이 드는군요.ㅜㅜ

prio의 이미지

계산 결과 달라지는 원인은 아주 많기 때문에 올리신 질문 만으로는 도움을 드리기가 어렵습니다.
위에 분이 간단한 소스코드를 올려달라는 것도 그 때문이구요.
(소스 코드를 다 올리라는 것이 아니라, 똑같은 기능을 하는 한에서 최대한 단순화된 소스를 올려달라는 것이지요)

시스템에 따라 결과가 달라지는 것은 흔히 포팅이 제대로 되지 않았기 때문인 경우가 많구요. (코드 이식에서 오류가 발생)
코드에는 문제가 없어도 시스템에 따라 실수의 정밀도가 다르기 때문에 그럴 수도 있고,
컴파일러가 자동으로 병렬화를 하는 경우에도 계산 순서가 달라져서 정밀도 오차가 다른 순서로 누적되기 때문에 약간 다른 결과가 나올 수도 있습니다.

드물게는 시뮬레이션 모델 자체가 계산 오차를 발산 시키는 경우도 있구요.

hackeryoon의 이미지

proi님 댓글 감사합니다.
포팅이 제대로 되지 않았다 >>> 일딴 포팅이 뭔지부터 공부해야 겠네요.ㅜㅜ
코드 이식에서 오류가 발생 >>> 일딴 무슨 말인지부터 알아봐야겠습니다.ㅜㅜ
실수의 정밀도도 체크해 보도록 하겠습니다.
그리고 모델이 병렬화 되어 있는데...이 과정에서 계산순서가 달아졌는지도 체크해봐야 겠군요.
근데 이건 제가 혼자 가능할까 싶습니다.ㅜㅜ
리눅스랑 유닉스는 약간 다른 결과라고 말할 수 있지만(계산값이 0.1의 오더입니다),
윈도우에서 컴팩은 1000의 오더로 약 10000배 가량 값이 차이가 나버리네요.ㅜㅜ
지금부터 다시 모델을 살펴봐야 겠습니다.
막막했던 차에 댓글이 많이 힘이 되네요. 두 분께 감사드립니다.

wkpark의 이미지

numerical instability가 있는 문제일 수도 있겠죠.

라이브러리와도 관련있고, trajectory와 관련된 거라면 초기값이 조금만 변해도 결과가 많은 차이가 나고,

변수가 너무 많군요.

그리고 리눅스라면 gfortran 말고 인텔 ifort를 써보세요. (이메일 등록만 하면 설치 파일을 받으실 수 있습니다)

온갖 참된 삶은 만남이다 --Martin Buber

hackeryoon의 이미지

wkpark님 댓글 감사합니다.
계산결과를 살펴보니 모든 계산항목에서 큰 차이가 나는 것이 아니라
일부 몇몇 항목에서 차이가 나더군요.
그래서 지금 문제가 발생하는 항목들의 서브루틴을 점검하고 있습니다.
문제없이 사용할 땐 미쳐 몰랐던 것들을 많이 배우게 되네요.
이번 기회에 제대로 공부해야 겠습니다.
그리고 리눅스 인텔 포트란의 경우 30일 평가판이 아닌가요?
한달 쓰고 사용하지 못할 바에야 그냥 쓰지 말자고 생각하고 설치하지 않고 있는데....
리눅스는 그냥 무료로 쭉 사용할 수 있는 건가요?

wkpark의 이미지

평가판으로 받지 마시고 무료로 쓸 수 있는 것 받으세요. 링크 찾아보시면 있습니다~~ 1년 넘게 자알 쓰고 있습니다.
간혹 버전이 올라간다고 무턱대고 올리다간 낭패일 수 있습니다. 제가 쓰고 있는 버전은 9.1인데 최신은 10.1.012 인 것 같습니다.
(10.1.x 버전이 컴파일 속도가 너무 느려서 버전을 내린 기억이...)

온갖 참된 삶은 만남이다 --Martin Buber

hackeryoon의 이미지

비상업적 목적으로 사용하는 포트란이 있더군요.
그걸로 받아서 설치했습니다.
포트란 설치는 문제가 없었는데
의외로 간단한 netcdf 때문에 고생 했습니다.
해결하고 보니 이렇게 간단한 걸 말이죠.ㅜㅜ
아. 제가 설치한 버전은 11입니다. 엄청 빠르군요.^^

mycluster의 이미지

컴파일러나 시스템별로 계산 결과가 차이나는 가장 큰 원인

1. 비트수
- 특별히 정의해주지 않을 경우 REAL로 선언하면 32비트 머신(주로 PC)에서는 4byte로 잡고, 64비트에서는 8byte로 잡으니까, 계산 결과시 소수아래 한참자리에서 오차가 발생하고, 그 결과값이 disturbance를 유발해서 결과가 틀려짐

2. 초기와문제
- 똑같은 32비트 머신이라도 gfortran이나 Visual Fortran의 경우 선언되지 않은 값에 어떤 값을 초기에 넣느냐하는것은 컴파일러에 따라 달라짐
- 예를 들어서 REAL(1:100)을 잡고 계산을 하는데 REAL(0)의 값이 계산에 반영되면 그 값은 0이 될 수도 있고 아닐 수도 있고...

어느 기계에서나 결과값이 똑같이 나오는게 정상인데 다르게 나온다면, 일단 프로그램을 '대충' 짰을 가능성이 크고, 각각의 변수 및 경계조건 값에서 선언되지 않은 변수값이 계산에 참여하는 경우가 발생하는지 부터 체크해볼 필요가 있음

그리고, 컴팩비주얼 포트란은 한물 간거니까, 이왕이면 Windows에서 돌릴때도 Intel Fortran 같은 최신 컴파일러를 사용하세요. Visual Studio 2008 + Intel Fortran 10.1 이 현재 추세임...

--------------------------------
윈도위의 리눅스 윈도위의 윈도우 리눅스위의 익스플로러

--------------------------------
윈도위의 리눅스 윈도위의 윈도우 리눅스위의 익스플로러

hackeryoon의 이미지

mycluster님 답글 감사합니다.
아직 문제를 해결하지 못하고 있네요.ㅜㅜ
현재 확인한 부분은 차이가 나는 결과가 계산되는 서브루틴 분리.
차이가 나지 않는 항목만을 분리해서 계산한 결과
CVFortran, ifort, XLfortran 모두 같은 결과가 나오네요.
이제 mycluster님이랑 다른 분들의 조언을 바탕으로
문제가 발생한 서브루틴을 살펴봐야 겠습니다.

전웅의 이미지

mycoboco@quadr-linux:~$ cat tt.c
#include <stdio.h>
#include <float.h>
 
double sqr(double x)
{
    return x * x;
}
 
int main(void)
{
    double x = 1E308;
    double y = x * x;
    double z;
 
    y = x / (y / x);
    z = x / (sqr(x) / x);
 
    printf("%e\n", y);
    printf("%e\n", z);
}
 
mycoboco@quadr-linux:~$ gcc -O0 tt.c && ./a.out
0.000000e+00
1.000000e+00
mycoboco@quadr-linux:~$ gcc -O1 tt.c && ./a.out
1.000000e+00
0.000000e+00
mycoboco@quadr-linux:~$ gcc -O2 tt.c && ./a.out
1.000000e+00
1.000000e+00

(로그인하기 귀찮은데 이젠 익명으로 글 쓰는게 안 되는군요. --;)

같은 프로그램, 같은 시스템, 같은 컴파일러에서도 이 지경인데, 하물며
다른 시스템, 다른 컴파일러에서는... - 더구나 두 결과 모두 IEEE 754
표준에 부합하는 결과입니다.

단순히 출력된 결과가 차이를 보이는 order 보다는 상대 오차 등을 확인해
진정 기대값에서 지나치게 벗어나는 결과인지 확인해 보시기 바랍니다. 또
계산 중간값에 대해서도 동일한 방법으로 확인해 보시면 좋을 것 같습니다.

예상으로는 extra precision 에 의한 결과 차이로 보입니다만, prio 님
말씀대로 워낙 다양한 변수가 있는 탓에 정확한 원인은 코드와 실행 환경을
알려주시기 전까지는 확신하기 어렵습니다.

floating-point arithmetic 과 관련된 내용을 공부해보시면 원인 파악에
도움이 되시리라 믿습니다 - 개인적으로 Goldberg 의 "What every computer
scientist should know about floating-point arithmetic" 을 starting
point 로 추천합니다. ACM 초기 버전 말고 Sun Numerical Guide 의 부록
버전으로 찾아보시면 도움이 될 겁니다.

기회가 되면 출판 매체를 통해 연재하려고 여유 있을 때마다 부동소수점
연산에 대한 이런 저런 내용들을 정리하고 있습니다. 공부하시다가 나중
에라도 도움이 되었으면 하는 바람입니다.

쌀쌀한 날씨에 건강 조심하세요~

--
Jun, Woong (woong.jun at gmail.com)

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

hackeryoon의 이미지

전웅님 답변 감사합니다.
예로 드신 결과 값의 차이 엄청나군요;;
옵션 사용시 제대로 알고 쓰지 않으면 큰 낭패를 보겠군요.
문제를 해결하기 위해 뭔가를 조금씩 진행해가고 있습니다만
이게 바른 길로 가고 있는지는 잘 모르겠네요.

결과값의 경우 일정 타임 스텝마다 출력되도록 되어 있습니다.
살펴보면 초반에 급속도로 증가하다가 일정값이 되면 증가하지 않고 수렴합니다.
예를들면 정상적인 값이 1과 2사이의 진동값이라고 한다면
컴파일러에 따라 차이가 나는 경우는 초반에 값이 1000정도까지 급속도로 증가한 후
1001에서 1002사이의 진동값으로 나타나는 것입니다.
흠...어렵군요.ㅜㅜ쫌 더 세부적으로 살펴봐야 겠습니다.

그리고 소스는 혹시 아실진 모르겠습니다만
POM이라고 하는 프린스톤 대학에서 개발한 해양물리 모델입니다.
여기에 연구실에서 자체 개발된 ecological model이 추가되는 형식입니다.
지금 문제가 되는 부분은 물론 연구실에서 자체 개발된 부분입니다.
열심히 공부해서 수정해야 겠습니다.ㅜㅜ

부동소수점에 대해서는 약간의 귀동냥으로 주워 들은 것 뿐이라
늘 궁금해 해왔었는데, 이번 기회에 약간의 지식이라도 배워둬야 겠군요.
추천해주신 자료 감사합니다.

여기는 쌀쌀한 날씨가 아니랍니다;; 눈이 수시로 내리네요;;
전웅님도 늘 건강에 유의하세요^^

moonend의 이미지

이야기하고 보니, 최대한 간단히 문제를 정의하면 별 고생할 일이 없죠.
좀 실수한 거 같습니다.

자신이 한 결과에 의문을 갖기 시작했을 때 쓰는 가장 쉬운 방법은 베끼기입니다.
1. 해당 분야에서 논문을 찾습니다.
조건은 인용 횟수가 높고, 좀 유명한 학회에서 평가 좋은 걸로 구합니다. 2~3개 정도.

2. 실 계산은 나중에 해도 됩니다. 우선은 최악의 상황에서 쓸 수 있는 시스템을 구축하는게 최고입니다.
vmware server를 설치해서 운영체제 버전, 라이브러리 버전, 기타 요소를 똑같이 맞춥니다.
가상 머신이라 결과가 나오는 속도는 굉장히 느리지만... 이점이 하나 있습니다.
세상일은 새옹지마라고, 나중에 컴퓨터 날라가는 일이 가끔 생기는데 꼭 그때가 급한 때죠.
설치가 다 끝나면 압축해서 DVD나 다른 곳에 저장하시기 바랍니다.

** vmware server는 무료이고, 개인적으로는 1.0.8 버전을 추천합니다. 2.0은 좀 까다롭더군요.

3. 실제 컴퓨터에 운영체제, 라이브러리를 다시 설치합니다.
번거롭게 두번 하는 이유는 운영체제 설치하다보면 이런저런 이유로 하드 파티션을 잘 날리기 때문입니다.
1~2일 정도 시간을 버릴 수 있기 때문에 반드시 가상머신으로 실습한 후에 설치해보는 것이 좋습니다.

4. 하드 백업하세요.
안전. 안전. 안전이 최고입니다.

hackeryoon의 이미지

moonend님 답변 감사합니다.
그런데 역시 답변을 이해하기는 내공이 부족한가 봅니다.ㅜㅜ
죄송합니다.
우선 말씀드리면 저는 프로그래밍을 전공하는 사람은 아니랍니다.ㅜㅜ
포트란 모델로 해양의 물질순환을 연구하는 학생입니다.
지금까지는 다른 사람이 구축한 모델을 바탕으로 연구를 했다면
이제는 직접 모델을 만들어 보기도 하고..이런 저런 이유로 늦게나마 이렇게
공부를 시작하게 되었습니다.
무지하다 물리치지 마시고 앞으로 많은 조언 부탁드립니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.