CPU time, wall clock time (포트란) by 바죠

병렬 컴퓨팅이 일반화 되지 않은 상황에서는 주로 CPU time을 비교하곤 했다. 하지만, 포트란77의 경우 CPU 시간을 측정하는 방법이 언어에서 지원되질 않았다. 유닉스 명령어 time을 활용하면 그럭저럭 데이터를 얻을 수 있으나, 반드시 시스템을 혼자 사용하고 있다는 확신이 서야한다. 아니 감시를 해야만 한다.

병렬 계산의 경우 CPU시간은 의미가 있기는 하지만, speedup을 계산하는데는 사용되지 않는다. 소위 wall-clock (벽걸이) 시간만이 의미가 있다. 모든 계산이 끝났을 때 기준으로 외부에서 측정한 시간만이 의미가 있다는 말씀. 결국, observed speedup 도 그렇게 wall-clock 시간 기준으로 계산된다.

노드 하나를 사용하여 모든 계산이 종료될 때 걸린 시간, wall-clock 시간 기준을 계산한다. 그 다음 여러 개의 노드들을 활용하여 모든 계산이 종료될 때 걸린 시간들을 역시 wall-clock 시간 기준으로 계산한다. 물론, 계산 결과들은 동일해야 한다.

요즈음은 PBS를 이용해서 사용자가 독점적으로 여러 대의 노드들을 사용하기 때문에 계산이 종료 될 때 찍히는 wall-clock 시간을 직접 이용해도 좋다. 다시 말해서 다른 사용자들과 나누어서 노드들을 활용하지 않았다.

사실 병렬 계산의 주요 목적: wall clock time을 줄이자(계산을 좀 빨리 끝내자). 더 큰 문제를 풀자.

MPI_WTIME(), double precision으로 선언된것이다. 초단위로 지나간 시간을 반환한다. 물론, MPI_INIT를 부른 다음에야 사용할 수 있다.
t1=MPI_WTIME()
..........
.............
t2=MPI_WTIME()
t2-t1형식으로 시간을 계산할 수 있다.

http://en.wikipedia.org/wiki/Speedup
http://www.llnl.gov/computing/tutorials/parallel_comp/
http://en.wikipedia.org/wiki/Wall_clock_time

     implicit none
     integer j, k,i
     real*8 tmp
  real cpu_diff
  real cpu_time1
  real cpu_time2
  real ( kind = 8 ) real_diff
  real ( kind = 8 ) real_time1
  real ( kind = 8 ) real_time2

       call cpu_time (cpu_time1 )   ! 사실은 포트란95에 속한다.
       call real_time ( real_time1 )
          tmp=0.0d0
          do i=1,1000
          do j=1,1000
          do k=1,100
          tmp=tmp+sin(float(j*i))*cos(float(i*j))
          enddo
          enddo
          enddo

      call cpu_time ( cpu_time2 )
      call real_time ( real_time2 )
          cpu_diff = cpu_time2 - cpu_time1
          real_diff = real_time2 - real_time1
       write(6,*) cpu_diff
       write(6,*) real_diff
        stop
        end

---------------------------------------
유닉스 명령어 time, 보다 자세한 정보는 man time
 time - run programs and summarize system resource usage
 time a.out
    16.00000   
    16.02400000000000    
FORTRAN STOP
real    0m16.026s
user    0m16.021s
sys     0m0.001s

---------------------------------------

http://people.scs.fsu.edu/~burkardt/f_src/memory_test/memory_test.f90




subroutine real_time ( seconds )

!*******************************************************************************
!
!! REAL_TIME returns the real time in seconds.
!
!  Modified:
!
!    07 November 2006
!
!  Author:
!
!    John Burkardt
!
!  Parameters:
!
!    Output, real ( kind = 8 ) SECONDS, a reading of the real time clock,
!    in seconds.
!
  implicit none

  integer clock_count
  integer clock_max
  integer clock_rate
  real ( kind = 8 ) seconds

  call system_clock ( clock_count, clock_rate, clock_max )

  seconds = real ( clock_count, kind = 8 ) &
    / real ( clock_rate, kind = 8 )

  return
end

컴퓨터 구간별로 실행시간을 찍어 보는 것은 때때로 매우 의미있는 것이다. 실제 가장 시간이 많이 걸리는 부분을 파악할 수 있다는 것은 향후 보다 좋은 프로그램을 만들 수 있는 중요한 정보가 된다. OPENMP 방식으로 간단하게 해당부분에 스크립트 양식의 처리를 통해서 병렬계산을 수행할 수도 있다.


거의 10년 동안 내가 스탬프와 계산 시간 계산을 측정해온 방식:

       character*8 fnnd ; character*10 fnnt
       integer itemp,itemq,irate

       call system_clock(itemp,irate)
       call date_and_time(date=fnnd,time=fnnt)
       write(6,'(a10,2x,a8,2x,a10)') 'date,time:', fnnd,fnnt
       if(nproc > 1) print *,  nproc," processes are alive"
       if(nproc ==1) print *,  nproc," process is alive"

...................
........................
................................

       call system_clock(itemq)
       write(6,'(a1,x,e15.8,2x,a4,2x,e15.8,2x,a4,2x,a24,i8)') '#',float(itemq-itemp)/float(irate)/60.,  &
         ' min',float(itemq-itemp)/float(irate)/3600.,' hrs','the number of processors',nproc

-----------------------------------
병렬 계산에서 speedup 계산하기 (observed speedup)
입력; CPU 시간을 측정한 것이 아니고,  wall-clock 시간을 측정한 것이다.
당연히, 계산 결과는 '같은 입력에 같은 출력'의 형식을 가지고 있어야 한다.
프로세서들의 숫자에 관계없이. 두 말하면 잔소리.
특히, 랜덤 넘버들을 활용하는 계산의 경우, 프로세서별로 랜덤 넘버를 처리하는 데 신중을 기해야한다.
물론, 랜덤 넘버 시드를 확보한 상태에서 정확히 계산이 리프로듀스되어야 한다.
프로세서들의 숫자에 따라서 결과가 다르면 안된다. 

아래 예제의 경우, 계산시간은 분(min) 단위이다.
       1   0.80745361E+03
        2   0.41382486E+03
        6   0.14425520E+03
        12  0.80999985E+02
        26  0.33641682E+02
        51  0.18515484E+02


!234567890
       program speedup
       implicit none
       integer i,jnode(100)
       integer npoints
       real*8 walltime(100)
       real*8 tmp
       npoints=6
       do i=1,npoints
       read(5,*) jnode(i), walltime(i)
       enddo
       tmp=walltime(1)
       do i=1,npoints
       walltime(i)= tmp/walltime(i)
       enddo
       do i=1,npoints
       write(6,'(i8,f20.9)') jnode(i),walltime(i)
       enddo
       stop
       end program speedup

            출력                                                                                                                          
       1         1.000000000
       2         1.951196480
       6         5.597396905
      12         9.968564932
      26        24.001582620
      51        43.609640990



51개의 프로세서들에서 약 85 %의 병렬효율성을 보이고 있습니다.



병렬 컴퓨터를 가지고 처음 작업을 하다 보면 정말 별의 별이 다 생긴다. 특히, 여러 사람들과 동시에 컴퓨터를 사용할 때에는 그야 말로 예기치 못한 사회문제가 발생한다. 한 유저가 병렬 프로그램을 잘 못하여 생길 수 있는 일이 매우 많이 있다.  정말 본의 아니게 여러 사람들 괴롭힐 수 있다. 자신이 사용하는 프로그램이 어떠한 프로세서들에 들어가서 작업을 하고 있는지를 확인할 줄 알아야 한다. 그래야, 다른 사람들을 괴롭히지 않을 수 있다. 초보자라면 꼭 알아 두자.  여러 사람들과 동시에 일을 할 때에는 위의 데이터를 얻는 것도 매우 오래 기다려야 할지도 모른다. 많은 사람들이 동시에 일을 하기 때문에 당장 내가 사용할 빈 프로세서들이 없을 수도 있다.

PBS시스템을 사용하여 job을 컴퓨터에 제출할 경우:

qstat -an

명령어를 사용하면 아래와 같이 어떠한 프로세서들에 병렬 job이 널려있는지를 가르켜 준다.

6652.cetus0     ihlee    default  HFB1         3312  12  --    --    --  R 12:31
   hpf127/0+hpf126/0+hpf125/0+hpf124/0+hpf123/0+hpf122/0+hpf121/0+hpf120/0
   +hpf119/0+hpf118/0+hpf18/0+hpf17/0
실제로 rsh hpf127에 로그인을 해볼 수 있다. 그곳에서top을 실행시켜서 병렬 계산의 일부가 어떻게 진행되고 있는지를 실제로 관측할 수 있다. 사용하는 모든 노드들에서 실행 프로그램 이름은 같다.

pbsnodes -a

pbsnodes -a > temp_file ; grep free temp_file |wc

병렬 프로그래밍 과정도 순차적 프로그램밍의 그것과 비교하면 훨씬 더 어렵다. 각 프로세서들의 입장에서 생각을 해야하기 때문이다. 일반적으로 알고리듬의 주요 컴포넌트들이 확실히 움직인다는 확신이 있을 때에만 병렬화 작업을 추가적으로 진행하는 것이 타당하다. 보통 병렬화라는 말을 사용한다. 이는 순차적 프로그램이 완전하게 돌아가는데, 다만 계산시간을 단축시키자는 뜻을 내포하고 있다. 일에도 순서가 있다. 한꺼번에 할 수는 없다.

다른 프로세서가 데이터를 건낼 생각도 없는데, 이쪽의 한 프로세서가 데이터를 안 준다고 기다린다. 영원히, 이게 데드락이다. 초보자들이 쉽게 범하는 병렬 컴퓨팅 프로그램 상의 에러이다. 닭이 먼저냐 계란이 먼저냐?로 싸우고 있다. 아무것도 진행되질 않는다. 형님 먼저 아우 먼저의 상황이 쉽게 일어 날 수 있다. 각 프로세서들은 일할 수 있는 능력이 동등하다고 생각하는 것은 좋은 생각이고 그렇게 해야하나, 이들 사이에 반드시 편의상의 서열, 순번은 있어야 한다. 현실적으로 꼭 필요한 개념이다. 이것이 없으면 늘 형님 먼저, 아우 먼저의 상황이 존재할 수밖에 없다.

-----------------------------------
1    9744.6140460968018
4    2494.5749859809875    
8    1269.6613759994507     
12    859.02333688735962 
16    659.41267299652100  
24    444.62729310989380    

       1         1.000000000
       4         3.906322360
       8         7.674970847
      12        11.343829239
      16        14.777717270
      24        21.916365003

-----------------------------------
GAMS Module STOPWATCH in STOPWATCH

http://gams.nist.gov/serve.cgi/Module/STOPWATCH/STOPWATCH/13021/

STOPWATCH

 A Fortran 90 module for measurement of execution time. 
It supports four clocks --wall clock, CPU clock, user CPU clock and system CPU clock
-- and returns all timesin seconds.
It provides a simple means of determining which clocks are availableand the precision of those clocks.
Examples of operations are start_watch,stop_watch, read_watch, and reset_watch.
Classes : R . Service routines S3 .
Dynamic program analysis tools Type : Fortran90 subroutine in STOPWATCH package.
Access : Public domain.
Portable.Precision: Single.Note : Fullsource is provided as a Unix gzipped tar file.
Details : Fullsource ReadmeSites : (1) ITL
cf.
타임스탬프(timestamp) 프로그램 소개:
http://incredible.egloos.com/3047077






  --------------------------------------------------------------------------------------------------------------------
http://www.personal.psu.edu/faculty/h/d/hdk/fortran.html
Fortran Resources
and
Fortran 77/90/95 Compilers for Windows and Linux
--------------------------------------------------------------------------------------------------------------------
http://flash.uchicago.edu/~tomek/htmls/num_meth.html
Numerical methods for Fortran programmers


핑백

덧글

댓글 입력 영역

최근 포토로그



MathJax