dc_clock.f90
Go to the documentation of this file.
1 != CPU 時間の計測
2 != Monitor of CPU TIME
3 !
4 ! Authors:: Yasuhiro MORIKAWA
5 ! Version:: $Id: dc_clock.F90,v 1.1 2009-03-20 09:09:53 morikawa Exp $
6 ! Tag Name:: $Name: $
7 ! Copyright:: Copyright (C) GFD Dennou Club, 2006. All rights reserved.
8 ! License:: See COPYRIGHT[link:../../COPYRIGHT]
9 !
10 module dc_clock
11  !
12  != CPU 時間の計測
13  != Monitor of CPU TIME
14  !
15  ! プログラムの処理に要した CPU 時間を計測して表示します.
16  !
17  !== Tutorial
18  !
19  ! * gtool5 オフィシャルチュートリアル:
20  ! {CPU 時間の計測}[link:../tutorial/dc_clock.htm]
21  !
22  !== Procedures list
23  !
24  ! DCClockCreate :: CLOCK 型変数の初期設定
25  ! DCClockStart :: 計測の開始
26  ! DCClockStop :: 計測の一時停止
27  ! DCClockClose :: 構造型 CLOCK 変数の終了処理
28  ! DCClockGet, DCClockEvalSec :: CPU 時間 (単位: 秒) の取得
29  ! DCClockToChar :: CPU 時間を適当に整形して文字型変数に変換
30  ! DCClockPutLine :: 構造型 CLOCK 変数の情報を表示
31  ! DCClockResult :: CPU 時間に関する総合的な情報を表示
32  ! DCClockPredict :: プログラムが終了するまでの予測 CPU 時間,
33  ! および日時を表示
34  ! DCClockSetName :: 名称の再設定
35  ! #operator(+) :: 加算 (dc_clock#CLOCK 型同士)
36  ! #operator(-) :: 減算 (dc_clock#CLOCK 型同士)
37  !
38  !== Usage
39  !
40  ! 始めに, 構造型 CLOCK の変数を定義し, DCClockCreate で初期化します.
41  ! プログラム中の計測開始地点で DCClockStart を呼び出し,
42  ! 計測を一時停止する地点で DCClockStop を呼び出します.
43  ! DCClockResult によって経過時間を表示します.
44  ! DCClockPredict を使用することでプログラムが終了するまでの残り CPU 時間
45  ! の予測値を表示することが可能です.
46  !
47  ! program dc_clock_sapmle1
48  ! use dc_clock, only: CLOCK, DCClockCreate, DCClockClose, &
49  ! & DCClockStart, DCClockStop, DCClockResult, DCClockPredict, &
50  ! & operator(+)
51  ! implicit none
52  ! type(CLOCK):: clock1, clock2
53  ! integer:: i, j
54  ! integer, parameter:: loop_num = 8
55  ! real:: a, b
56  !
57  ! call DCClockCreate( clk = clock1, & ! (out)
58  ! & name = 'exponential' ) ! (in)
59  ! call DCClockCreate( clk = clock2, & ! (out)
60  ! & name = 'four-operations' ) ! (in)
61  ! a = 2.0
62  ! b = 1.0
63  ! do i = 1, loop_num
64  ! call DCClockStart( clk = clock1 ) ! (inout)
65  ! do j = 1, 1000000
66  ! a = (a**2)**0.3 + 1.0
67  ! enddo
68  ! call DCClockStop( clk = clock1 ) ! (inout)
69  ! call DCClockStart( clk = clock2 ) ! (inout)
70  ! do j = 1, 1000000
71  ! b = b / 3.0 * 2.0 + 1.0 - 1.0e-1
72  ! enddo
73  ! call DCClockStop( clk = clock2 ) ! (inout)
74  ! call DCClockPredict( &
75  ! & clk = clock1 + clock2, & ! (in)
76  ! & progress = real(i)/real(loop_num) ) ! (in)
77  ! enddo
78  ! call DCClockResult( &
79  ! & clks = (/clock1, clock2/), & ! (in)
80  ! & total_auto = .true. ) ! (in)
81  ! call DCClockClose( clk = clock1 ) ! (inout)
82  ! call DCClockClose( clk = clock2 ) ! (inout)
83  !
84  ! write(*,*) 'a = ', a
85  ! write(*,*) 'b = ', b
86  ! end program dc_clock_sapmle1
87  !
88  !== Note
89  !
90  ! CPU 時間はシステム CPU 時間とユーザ CPU 時間とに分けることが
91  ! できます. dc_clock では CPU 時間の計測に *cpu_time* サブルーチン
92  ! (Fortran 95 規格で導入された組込みサブルーチン) を使用しているため,
93  ! 計測された CPU 時間がシステム CPU 時間なのかユーザ CPU 時間なのか,
94  ! もしくは両方の合計なのかどうかは処理系の *cpu_time* に依存しています.
95  ! (大抵は両方の合計である場合が多いようです).
96  !
97  !=== 後方互換
98  !
99  ! バージョン 20071009 以前に利用可能だった以下の手続きは,
100  ! 後方互換のため, しばらくは利用可能です.
101  !
102  ! * Create, Close, Start, Stop, PutLine, Result, Set_Name
103  ! Get, EvalSec, toChar, Predict
104  use dc_types, only: string, dp
105  use dc_trace, only: beginsub, endsub, dbgmessage
107  implicit none
108  private
109  public:: clock
112  public:: operator(+), operator(-)
114  !-----------------------------------------------
115  ! 後方互換用
116  ! For backward compatibility
117  public:: create, Close, start, stop, putline, result, set_name
118  public:: get, evalsec, tochar, predict
119  type clock
120  !
121  ! CPU 時刻計測用の構造体です.
122  ! 初期化には Create を, 終了処理には Close を用います.
123  !
124  ! 詳しい使い方は dc_clock の Usage を参照ください.
125  !
126  private
127  character(STRING):: name
128  real(DP):: start_time ! 計測を開始した時間
129  ! (計測の一時停止中には負の値が設定される)
130  real(DP):: elapsed_time ! 経過時間の累計値
131  type(dc_datetime):: start_date ! 計測を開始した日時
132  logical:: initialized = .false. ! CLOCK 構造体の初期化チェック用フラグ
133  end type clock
134  interface dcclockcreate
135  module procedure dcclockcreate0
136  end interface
137  interface dcclockclose
138  module procedure dcclockclose0
139  end interface
140  interface dcclockstart
141  module procedure dcclockstart0
142  end interface
143  interface dcclockstop
144  module procedure dcclockstop0
145  end interface
146  interface dcclockputline
147  module procedure dcclockputline0
148  end interface
149  interface dcclockget
150  module procedure dcclockgetr
151  module procedure dcclockgetd
152  end interface
153  interface dcclockevalsec
154  module procedure dcclockevalsecd
155  end interface
156  interface dcclocktochar
157  module procedure dcclocktochar0
158  end interface
159  interface dcclockresult
160  module procedure dcclockresult0
161  end interface
162  interface operator(+)
163  module procedure dcclockadd
164  end interface
165  interface operator(-)
166  module procedure dcclocksubtract
167  end interface
168  interface dcclocksetname
169  module procedure dcclocksetname0
170  end interface
171  interface dcclockpredict
172  module procedure dcclockpredict0
173  end interface
174  !-----------------------------------------------
175  ! 後方互換用
176  ! For backward compatibility
177  interface create
178  module procedure dcclockcreate0
179  end interface
180  interface close
181  module procedure dcclockclose0
182  end interface
183  interface start
184  module procedure dcclockstart0
185  end interface
186  interface stop
187  module procedure dcclockstop0
188  end interface
189  interface putline
190  module procedure dcclockputline0
191  end interface
192  interface get
193  module procedure dcclockgetr
194  module procedure dcclockgetd
195  end interface
196  interface evalsec
197  module procedure dcclockevalsecd
198  end interface
199  interface tochar
200  module procedure dcclocktochar0
201  end interface
202  interface result
203  module procedure dcclockresult0
204  end interface
205  interface set_name
206  module procedure dcclocksetname0
207  end interface
208  interface predict
209  module procedure dcclockpredict0
210  end interface
211  character(*), parameter:: version = &
212  & '$Name: $' // &
213  & '$Id: dc_clock.F90,v 1.1 2009-03-20 09:09:53 morikawa Exp $'
214 contains
215  subroutine dcclockcreate0(clk, name)
216  !
217  !=== CLOCK の初期化用サブルーチン
218  !
219  ! CLOCK 型の変数を利用する際にはまずこのサブルーチンによって
220  ! 初期化を行ってください. *name* には計測内容を与えてください.
221  !
222  use dc_message, only: messagenotify
223  use dc_date, only: dcdatetimecreate
224  implicit none
225  type(clock), intent(out):: clk
226  character(*), intent(in):: name
227  character(*), parameter:: subname = 'DCClockCreate'
228  continue
229  call beginsub(subname, 'name=%c', c1=trim(name), version=version)
230  if (clk % initialized) then
231  call messagenotify('W', subname, 'This argument (type CLOCK) is already initialized.')
232  call dbgmessage('already initialized')
233  goto 999
234  end if
235  clk % name = name
236  clk % elapsed_time = 0.0
237  clk % start_time = - 1.0
238  clk % initialized = .true.
239  call dcdatetimecreate(clk % start_date)
240  call dbgmessage('normal initialized')
241 999 continue
242  call endsub(subname)
243  end subroutine dcclockcreate0
244  subroutine dcclockclose0(clk)
245  !
246  !=== CLOCK の終了サブルーチン
247  !
248  ! CLOCK 型の変数をクローズします.
249  !
250  implicit none
251  type(clock), intent(inout):: clk
252  character(*), parameter:: subname = 'DCClockClose'
253  continue
254  call beginsub(subname)
255  if (clk % initialized) then
256  clk % initialized = .false.
257  clk % name = ''
258  end if
259  call endsub(subname)
260  end subroutine dcclockclose0
261  subroutine dcclockstart0(clk, err)
262  !
263  !=== 計測の開始
264  !
265  ! このサブルーチンを呼んだ時点で計測を開始します.
266  !
267  ! 第一引数 *clk* に対して DCClockCreate による初期化が行われていない場合,
268  ! エラーを発生させます. *err* を与える場合には *err* に .true. が返り,
269  ! プログラムは続行されます.
270  !
271  use dc_message, only: messagenotify
272  use dc_string, only: tochar
273  use dc_types, only: dp
275  use dc_date, only: evalsec
276  implicit none
277  type(clock), intent(inout):: clk
278  logical, intent(out), optional:: err
279  character(STRING):: cause_c
280  integer:: stat
281  character(*), parameter:: subname = 'DCClockStart'
282  continue
283  call beginsub(subname)
284  stat = dc_noerr
285  cause_c = 'CLOCK'
286  if (.not. clk % initialized) then
287  call messagenotify('W', subname, 'Call Create before Start in dc_clock.')
288  call dbgmessage('Ignored because input argument was not initialized.')
289  stat = dc_enotinit
290  goto 999
291  end if
292  call cpu_time(clk % start_time) ! (out)
293  call dbgmessage('name=%c, cpu_time=%f', &
294  & c1=trim(clk % name), d=(/clk % start_time/) )
295 999 continue
296  call storeerror(stat, subname, err, cause_c)
297  call endsub(subname)
298  end subroutine dcclockstart0
299  subroutine dcclockstop0(clk, err)
300  !
301  !=== 計測の一時停止
302  !
303  ! このサブルーチンを呼んだ時点で計測を一時停止します.
304  !
305  ! 第一引数 *clk* に対して DCClockCreate による初期化が行われていない場合,
306  ! エラーを発生させます. *err* を与える場合には *err* に .true. が返り,
307  ! プログラムは続行されます.
308  !
309  use dc_message, only: messagenotify
310  use dc_string, only: tochar
312  use dc_date, only: evalsec, operator(+), operator(-)
313  use dc_date_types, only: dc_difftime
314  use dc_types, only: dp
315  implicit none
316  type(clock), intent(inout):: clk
317  logical, intent(out), optional:: err
318  character(STRING):: cause_c
319  real:: stop_time
320  integer:: stat
321  character(*), parameter:: subname = 'DCClockStop'
322  continue
323  call beginsub(subname)
324  stat = dc_noerr
325  cause_c = 'CLOCK'
326  if (.not. clk % initialized) then
327  call messagenotify('W', subname, 'Call Create before Stop in dc_clock.')
328  call dbgmessage('Ignored because input argument was not initialized.')
329  stat = dc_enotinit
330  goto 999
331  elseif (clk % start_time < 0.0_dp) then
332  call messagenotify('W', subname, 'Call Start before Stop in dc_clock.')
333  call dbgmessage('Ignored because input argument was not started.')
334  goto 999
335  end if
336  call cpu_time(stop_time)
337  clk % elapsed_time = clk % elapsed_time + stop_time - clk % start_time
338  clk % start_time = - 1.0
339  call dbgmessage('name=%c, cpu_time=%r, elapsed_time=%f', &
340  & c1=trim(clk % name), r=(/stop_time/), d=(/clk % elapsed_time/))
341 999 continue
342  call storeerror(stat, subname, err, cause_c)
343  call endsub(subname)
344  end subroutine dcclockstop0
345  subroutine dcclockgetr(clk, sec, err) !:doc-priority 40:
346  !
347  !=== CPU 時間 (単位: 秒) の取得
348  !
349  ! CPU 時間 (単位: 秒) を *sec* に取得します.
350  !
351  ! 第一引数 *clk* に対して DCClockCreate による初期化が行われていない場合,
352  ! エラーを発生させます. *err* を与える場合には *err* に .true. が返り,
353  ! プログラムは続行されます.
354  !
355  use dc_types, only: dp
356  use dc_message, only: messagenotify
357  use dc_date, only: evalsec
358  use dc_string, only: cprintf
360  implicit none
361  type(clock), intent(in):: clk
362  real, intent(out):: sec
363  logical, intent(out), optional:: err
364  character(STRING):: cause_c
365  integer:: stat
366  character(*), parameter:: subname = 'DCClockGetR'
367  continue
368  call beginsub(subname)
369  stat = dc_noerr
370  cause_c = 'CLOCK'
371  if (.not. clk % initialized) then
372  call messagenotify('W', subname, 'Call Create before Get in dc_clock.')
373  call dbgmessage('Ignored because input argument was not initialized.')
374  stat = dc_enotinit
375  goto 999
376  end if
377  sec = clk % elapsed_time
378  call dbgmessage('name=%c, return sec=<%r>', &
379  & c1=trim(clk % name), r=(/sec/))
380 999 continue
381  call storeerror(stat, subname, err, cause_c)
382  call endsub(subname)
383  end subroutine dcclockgetr
384  subroutine dcclockgetd(clk, sec, err) !:doc-priority 60:
385  !
386  !=== CPU 時間 (単位: 秒) の取得
387  !
388  ! CPU 時間 (単位: 秒) を *sec* に取得します.
389  !
390  ! 第一引数 *clk* に対して DCClockCreate による初期化が行われていない場合,
391  ! エラーを発生させます.
392  ! 第二引数 *err* を与える場合には *err* に .true. が返り,
393  ! プログラムは続行されます.
394  !
395  use dc_types, only: dp
396  use dc_string, only: cprintf
397  use dc_message, only: messagenotify
398  use dc_date, only: evalsec
400  implicit none
401  type(clock), intent(in):: clk
402  real(DP), intent(out):: sec
403  logical, intent(out), optional:: err
404  character(STRING):: cause_c
405  integer:: stat
406  character(*), parameter:: subname = 'DCClockGetD'
407  continue
408  call beginsub(subname)
409  stat = dc_noerr
410  cause_c = 'CLOCK'
411  if (.not. clk % initialized) then
412  call messagenotify('W', subname, 'Call Create before Get in dc_clock.')
413  call dbgmessage('Ignored because input argument was not initialized.')
414  stat = dc_enotinit
415  goto 999
416  end if
417  sec = clk % elapsed_time
418  call dbgmessage('name=%c, return sec=<%f>', &
419  & c1=trim(clk % name), d=(/sec/))
420 999 continue
421  call storeerror(stat, subname, err, cause_c)
422  call endsub(subname)
423  end subroutine dcclockgetd
424  function dcclockevalsecd(clk) result(result)
425  !
426  !=== CPU 時間 (単位: 秒) の取得
427  !
428  ! CPU 時間 (単位: 秒) を返します.
429  !
430  ! 第一引数 *clk* に対して DCClockCreate
431  ! による初期化が行われていない場合, -1.0 が返ります.
432  !
433  use dc_types, only: dp
434  implicit none
435  type(clock), intent(in):: clk
436  real(DP):: result
437  logical:: err
438  continue
439  call dcclockgetd(clk, result, err)
440  if (err) result = -1.0_dp
441  end function dcclockevalsecd
442  function dcclocktochar0(clk) result(result)
443  !
444  !=== CPU 時間を適当に整形して文字型変数に変換
445  !
446  ! CPU 時間に関して適当に整形を行い, 文字型変数に変換して返します.
447  !
448  ! 第一引数 *clk* に対して DCClockCreate
449  ! による初期化が行われていない場合, 空文字が返ります.
450  !
451  use dc_string, only: cprintf
452  use dc_date, only: evalsec
453  implicit none
454  type(clock), intent(in):: clk
455  character(STRING):: result
456  character(20):: clk_name
457  continue
458  clk_name = clk % name
459  if (clk % initialized) then
460  result = cprintf(' %c%c %c', c1 = clk_name, &
461  & c2=trim(result_value_form(clk % elapsed_time)), &
462  & c3=trim(fit_unit_value(clk % elapsed_time)))
463  else
464  result = ''
465  end if
466  end function dcclocktochar0
467  subroutine dcclockputline0(clk, unit, indent, err)
468  !
469  !=== 構造型 CLOCK 変数の情報を表示
470  !
471  ! 構造型 CLOCK 変数に関する情報を表示します. *unit* には出力先の装置番号を
472  ! 与えてください. *unit* を与えない場合, 標準出力へ表示されます.
473  !
474  ! 第一引数 *clk* に対して DCClockCreate による初期化が行われていない場合,
475  ! エラーを発生させます. *err* を与える場合には *err* に .true. が返り,
476  ! プログラムは続行されます.
477  !
478  use dc_types, only: stdout
479  use dc_message, only: messagenotify
480  use dc_string, only: printf, tochar, cprintf
481  use dc_date, only: evalsec, evalday, tochar
483  use dc_types, only: dp
484  implicit none
485  type(clock), intent(in):: clk
486  integer, intent(in), optional:: unit
487  character(*), intent(in), optional:: indent
488  ! 表示されるメッセージの字下げ.
489  !
490  ! Indent of displayed messages.
491  logical, intent(out), optional:: err
492  integer:: out_unit
493  character(STRING):: cause_c
494  integer:: stat
495  integer:: indent_len
496  character(STRING):: indent_str
497  character(*), parameter:: subname = 'DCClockPutLine'
498  continue
499  call beginsub(subname)
500  stat = dc_noerr
501  cause_c = 'CLOCK'
502  if (.not. clk % initialized) then
503  call messagenotify('W', subname, 'Call Create before PutLine in dc_clock.')
504  call dbgmessage('Ignored because input argument was not initialized.')
505  stat = dc_enotinit
506  goto 999
507  end if
508  if (present(unit)) then
509  out_unit = unit
510  else
511  out_unit = stdout
512  end if
513  indent_len = 0
514  indent_str = ''
515  if (present(indent)) then
516  if (len(indent) /= 0) then
517  indent_len = len(indent)
518  indent_str(1:indent_len) = indent
519  end if
520  end if
521  call printf(out_unit, &
522  & indent_str(1:indent_len) // &
523  & '#<CLOCK:: @name=%c @clocking=%y @elapsed_time=%f sec. %c @start_date=%c>', &
524  & c1=trim(clk % name), l=(/clk % start_time > 0.0_dp/), &
525  & d=(/clk % elapsed_time/), &
526  & c2=trim(fit_unit_value(clk % elapsed_time)), &
527  & c3=trim(tochar(clk % start_date)))
528  call dbgmessage('name=%c, output to device number %d', &
529  & c1=trim(clk % name), i=(/out_unit/))
530 999 continue
531  call storeerror(stat, subname, err, cause_c)
532  call endsub(subname)
533  end subroutine dcclockputline0
534  subroutine dcclockresult0(clks, unit, total_auto, clk_total, total_name, err)
535  !
536  !=== CPU 時間の総計を表示
537  !
538  ! CPU 時間の総計を表示します. *clks* へ, CLOCK 変数の配列を
539  ! 与えてください. プログラムの最後で呼び出されることを
540  ! 想定しています. *unit* には出力先の装置番号を
541  ! 与えてください. *unit* を与えない場合, 標準出力へ表示されます.
542  !
543  ! 引数 *total_auto* に .true. を与えると, *clks* を全て足し合わせた
544  ! 合計値を自動的に表示します. 下記の引数 *clk_total* が与えられている
545  ! 場合は *clk_total* が優先されます.
546  !
547  ! 引数 *clk_total* に CLOCK 変数を与えると, この変数を合計値と
548  ! して表示します.
549  !
550  ! 引数 *total_name* に文字型変数を与えると, 総計メッセージの
551  ! 冒頭にこの文字列を出力します.
552  !
553  ! 第一引数 *clk* に対して DCClockCreate による初期化が行われていない場合,
554  ! エラーを発生させます. *err* を与える場合には *err* に .true. が返り,
555  ! プログラムは続行されます.
556  !
557  use dc_types, only: stdout, string, dp
558  use dc_message, only: messagenotify
559  use dc_string, only: printf, tochar, cprintf
560  use dc_date, only: evalsec
562  implicit none
563  type(clock), intent(in):: clks(:)
564  integer, intent(in), optional:: unit
565  logical, intent(in), optional:: total_auto
566  type(clock), intent(in), optional:: clk_total
567  logical, intent(out), optional:: err
568  character(*), intent(in), optional:: total_name
569  integer:: out_unit, i, clks_size, ra
570  character(20):: clk_name
571  character(STRING):: cause_c
572  character(STRING):: total_name_work
573  type(clock):: clk_auto_total
574  logical:: total_print_complete
575  real(DP):: elapsed_time_val_cor
576  integer:: stat
577  character(*), parameter:: total_time_mes = ' TOTAL TIME = '
578  integer:: myrank_mpi, nprocs_mpi
579  character(*), parameter:: subname = 'DCClockResult'
580  continue
581  call beginsub(subname)
582  stat = dc_noerr
583  cause_c = 'CLOCK'
584  clks_size = size(clks)
585  do i = 1, clks_size
586  if (.not. clks(i) % initialized) then
587  call messagenotify('W', subname, 'Call Create before Result in dc_clock.')
588  call dbgmessage('Ignored because input argument was not initialized.')
589  stat = dc_enotinit
590  goto 999
591  end if
592  end do
593  if (present(unit)) then
594  out_unit = unit
595  else
596  out_unit = stdout
597  end if
598  if (present(total_name)) then
599  total_name_work = ' (' // trim(total_name) // ')'
600  else
601  total_name_work = ''
602  end if
603  myrank_mpi = -1
604  nprocs_mpi = 1
605  do ra = 0, nprocs_mpi - 1
606  call printf(out_unit, '')
607  if ( myrank_mpi < 0 ) then
608  call printf(out_unit, &
609  & ' ############## CPU TIME SUMMARY%c################', &
610  & c1=trim(total_name_work) // ' ')
611  else
612  call printf(out_unit, &
613  & ' ####### CPU TIME SUMMARY%c#### [rank=%06d] ####', &
614  & c1=trim(total_name_work) // ' ', &
615  & i = (/myrank_mpi/) )
616  end if
617  do i = 1, clks_size
618  clk_name = clks(i) % name
619  elapsed_time_val_cor = clks(i) % elapsed_time
620  if (elapsed_time_val_cor < 0.0_dp) elapsed_time_val_cor = 0.0_dp
621  call printf(out_unit, &
622  & ' %c%c %c', c1=clk_name, &
623  & c2=trim(result_value_form(elapsed_time_val_cor)), &
624  & c3=trim(fit_unit_value(clks(i) % elapsed_time)))
625  end do
626  total_print_complete = .false.
627  if (present(clk_total)) then
628  if (clk_total % initialized) then
629  call printf(out_unit, &
630  & ' ------------------------------------------------')
631  elapsed_time_val_cor = clk_total % elapsed_time
632  if (elapsed_time_val_cor < 0.0_dp) elapsed_time_val_cor = 0.0_dp
633  call printf(out_unit, &
634  & ' %c%c %c', c1=total_time_mes, &
635  & c2=trim(result_value_form(elapsed_time_val_cor)), &
636  & c3=trim(fit_unit_value(clk_total % elapsed_time)))
637  total_print_complete = .true.
638  end if
639  end if
640  if (present(total_auto) .and. .not. total_print_complete) then
641  if (total_auto) then
642  clk_auto_total = clks(1)
643  if (clks_size > 1) then
644  do i = 2, clks_size
645  clk_auto_total = clk_auto_total + clks(i)
646  end do
647  end if
648  call printf(out_unit, &
649  & ' ------------------------------------------------')
650  elapsed_time_val_cor = clk_auto_total % elapsed_time
651  if (elapsed_time_val_cor < 0.0_dp) elapsed_time_val_cor = 0.0_dp
652  call printf(out_unit, &
653  & ' %c%c %c', c1=total_time_mes, &
654  & c2=trim(result_value_form(elapsed_time_val_cor)), &
655  & c3=trim(fit_unit_value(clk_auto_total % elapsed_time)))
656  end if
657  end if
658  call dbgmessage('total results, output to device number %d', &
659  & i=(/out_unit/))
660  end do
661 999 continue
662  call storeerror(stat, subname, err, cause_c)
663  call endsub(subname)
664  end subroutine dcclockresult0
665  function result_value_form(value) result(result)
666  !
667  ! 引数 value として与えられた倍精度実数型のデータを,
668  ! 以下のフォーマットに整形して文字型として返します.
669  !
670  ! 0.183400E+02
671  !
672  use dc_types, only: dp, token
673  implicit none
674  character(TOKEN):: result
675  real(DP), intent(in):: value
676  continue
677  write(result, "(e15.6)") value
678  end function result_value_form
679  function fit_unit_value(sec, diff) result(result)
680  !
681  ! 引数 sec に与えられた数値を秒と扱い,
682  ! 以下のフォーマットに整形して文字型として返します.
683  !
684  ! (23.18 days)
685  !
686  ! 単位は days, hrs., minutes から適当に
687  ! 選ばれます. (値が 1 以上の値となるように選ばれます).
688  ! 1 分以内の場合は空文字を返します.
689  !
690  use dc_types, only: dp, token
691  use dc_date_types, only: dc_difftime
692  use dc_date, only: dcdifftimecreate, evalday, evalhour, evalmin, evalsec
693  use dc_types, only: dp
694  implicit none
695  character(TOKEN):: result
696  real(DP), intent(in):: sec
697  type(dc_difftime), intent(in), optional:: diff
698  type(dc_difftime):: diffw
699  character(TOKEN):: unit
700  real(DP):: value
701  character(TOKEN):: cval
702  continue
703  if ( present(diff) ) then
704  diffw = diff
705  else
706  call dcdifftimecreate( diffw, sec = sec )
707  end if
708  if (evalday(diffw) > 1.0_dp) then
709  unit = ' days'
710  value = evalday(diffw)
711  elseif (evalhour(diffw) > 1.0_dp) then
712  unit = ' hrs.'
713  value = evalhour(diffw)
714  elseif (evalmin(diffw) > 1.0_dp) then
715  unit = ' minutes'
716  value = evalmin(diffw)
717  else
718  result = ''
719  return
720  end if
721  cval = printf_g5_2(value)
722  result = '(' // trim(adjustl(cval)) // trim(unit) // ')'
723  end function fit_unit_value
724  function printf_g5_2(value) result(result)
725  !
726  ! 引数 value に与えられた数値データを
727  ! 以下のフォーマットに整形して文字型として返します.
728  !
729  ! 23.18
730  ! 0.23
731  !
732  use dc_types, only: dp, token, string
733  use dc_string, only: cprintf
734  implicit none
735  character(TOKEN):: result
736  real(DP), intent(in):: value
737  character(TOKEN):: int_part, dem_part
738  integer:: dem_int
739  continue
740  write(int_part, "(i20)") int(value)
741  dem_int = nint((value - int(value)) * 100)
742  if (dem_int < 0) dem_int = - dem_int
743  if (dem_int == 100) then
744  dem_int = 0
745  write(int_part, "(i20)") int(value) + 1
746  end if
747  dem_part = cprintf('%02d', i=(/dem_int/))
748  result = trim(adjustl(int_part)) // '.' // trim(dem_part)
749  end function printf_g5_2
750  function dcclockadd(clk1, clk2) result(clk_total)
751  !
752  !=== CLOCK 変数を足し合わせる
753  !
754  ! CLOCK 変数 <b>clk1</b> と <b>clk2</b> を足し合わせます.
755  ! 与えられた 2 つの CLOCK 変数の CPU 時間を合計し,
756  ! CLOCK 変数として返します. 計測内容の名称は <b>clk1</b> と <b>clk2</b>
757  ! の名称を '+' で組み合わせたものとなります.
758  !
759  use dc_string, only: cprintf
760  use dc_date, only: operator(+), operator(<)
761  implicit none
762  type(clock), intent(in):: clk1
763  type(clock), intent(in):: clk2
764  type(clock):: clk_total
765  continue
766  if (.not. clk1 % initialized .or. .not. clk2 % initialized) then
767  clk_total % initialized = .false.
768  return
769  end if
770  clk_total % name = cprintf('%c+%c', &
771  & c1=trim(clk1 % name), c2=trim(clk2 % name))
772  clk_total % start_time = - 1.0
773  clk_total % initialized = .true.
774  clk_total % elapsed_time = 0.0
775  if (clk1 % start_date < clk2 % start_date) then
776  clk_total % start_date = clk1 % start_date
777  else
778  clk_total % start_date = clk2 % start_date
779  end if
780  clk_total % elapsed_time = &
781  & clk1 % elapsed_time + clk2 % elapsed_time
782  end function dcclockadd
783  function dcclocksubtract(clk1, clk2) result(clk_total)
784  !
785  !=== CLOCK 変数を足し合わせる
786  !
787  ! CLOCK 変数 <b>clk1</b> から <b>clk2</b> を引きます.
788  ! 1 つ目の CLOCK 変数の CPU 時間と
789  ! 2 つ目の CLOCK 変数の CPU 時間との差を
790  ! CLOCK 変数として返します. 計測内容の名称は <b>clk1</b> と <b>clk2</b>
791  ! の名称を '-' で組み合わせたものとなります.
792  !
793  use dc_string, only: cprintf
794  use dc_date, only: operator(-), operator(<)
795  implicit none
796  type(clock), intent(in):: clk1
797  type(clock), intent(in):: clk2
798  type(clock):: clk_total
799  continue
800  if (.not. clk1 % initialized .or. .not. clk2 % initialized) then
801  clk_total % initialized = .false.
802  return
803  end if
804  clk_total % name = cprintf('%c-%c', &
805  & c1=trim(clk1 % name), c2=trim(clk2 % name))
806  clk_total % start_time = - 1.0
807  clk_total % initialized = .true.
808  clk_total % elapsed_time = 0.0
809  if (clk1 % start_date < clk2 % start_date) then
810  clk_total % start_date = clk1 % start_date
811  else
812  clk_total % start_date = clk2 % start_date
813  end if
814  clk_total % elapsed_time = &
815  & clk1 % elapsed_time - clk2 % elapsed_time
816  end function dcclocksubtract
817  subroutine dcclocksetname0(clk, name, err)
818  !
819  !=== 測定内容の名称を変更する.
820  !
821  ! CLOCK 変数 *clk* の計測内容の名称を変更します.
822  ! この名称は Create の *name* 引数で指定されたものです.
823  !
824  ! 第一引数 *clk* に対して DCClockCreate による初期化が行われていない場合,
825  ! エラーを発生させます. *err* を与える場合には *err* に .true. が返り,
826  ! プログラムは続行されます.
827  !
828  use dc_message, only: messagenotify
829  use dc_string, only: tochar, cprintf
831  implicit none
832  type(clock), intent(inout):: clk
833  character(*), intent(in):: name
834  logical, intent(out), optional:: err
835  character(STRING):: cause_c
836  integer:: stat
837  character(*), parameter:: subname = 'DCClockSetName'
838  continue
839  call beginsub(subname)
840  stat = dc_noerr
841  cause_c = 'CLOCK'
842  if (.not. clk % initialized) then
843  call messagenotify('W', subname, 'Call Create before Set_Name in dc_clock.')
844  call dbgmessage('Ignored because input argument was not initialized.')
845  stat = dc_enotinit
846  goto 999
847  end if
848  clk % name = name
849  call dbgmessage('set new name "%c"', c1=trim(clk % name))
850 999 continue
851  call storeerror(stat, subname, err, cause_c)
852  call endsub(subname)
853  end subroutine dcclocksetname0
854  subroutine dcclockpredict0(clk, progress, unit, err)
855  !
856  !=== プログラムが終了するまでの予測 CPU 時間, および日時を表示
857  !
858  ! CLOCK 変数 *clk* と *progress* から, プログラムが
859  ! 終了するまでの予測 CPU 時間, および日時を以下のように表示します.
860  !
861  ! ########## PREDICTION OF CALCULATION ###########
862  ! Start Date 2007-03-08T16:49:25+09:00
863  ! Current Date 2007-03-08T16:49:27+09:00
864  ! Progress 66.67% [**************** ]
865  ! Remaining CPU TIME 0.100000E+01
866  ! Completion Date 2007-03-08T16:49:28+09:00
867  !
868  ! 第2引数である *progress* には 0 〜 1 までの値を与えてください.
869  ! プログラムの開始時を 0, 終了時を 1 とします. (例えば,
870  ! プログラムが半分進んだ時には 0.5 を与えます).
871  !
872  ! ここで行う「予測」とは, これまでの経過時間および
873  ! 終了したプログラムの分量から単純なアルゴリズムで割り出している
874  ! ものなので, 正確な予測値を返すわけではありません.
875  ! あくまで目安として利用してください.
876  !
877  ! 引数 *unit* には出力先の装置番号を
878  ! 与えてください. *unit* を与えない場合, 標準出力へ表示されます.
879  !
880  ! 第一引数 *clk* に対して DCClockCreate による初期化が行われていない場合,
881  ! エラーを発生させます. *err* を与える場合には *err* に .true. が返り,
882  ! プログラムは続行されます.
883  !
884  use dc_types, only: stdout, dp
885  use dc_message, only: messagenotify
886  use dc_string, only: tochar, cprintf, printf
889  use dc_date, only: operator(+), dcdatetimecreate, tochar, evalsec, &
890  & dcdifftimecreate
891  implicit none
892  type(clock), intent(in):: clk
893  real, intent(in):: progress
894  integer, intent(in), optional:: unit
895  logical, intent(out), optional:: err
896  character(STRING):: cause_c
897  integer:: stat, out_unit
898  type(dc_difftime):: remain_diff
899  type(dc_datetime):: comp_date, cur_date
900  character(7):: prog_percent
901  character(25):: prog_bar
902  integer:: prog_bar_ptr
903  real:: prog_valid
904  character(*), parameter:: subname = 'DCClockPredict'
905  continue
906  call beginsub(subname)
907  stat = dc_noerr
908  cause_c = 'CLOCK'
909  if (.not. clk % initialized) then
910  call messagenotify('W', subname, 'Call Create before Predict in dc_clock.')
911  call dbgmessage('Ignored because input argument was not initialized.')
912  stat = dc_enotinit
913  goto 999
914  end if
915  if (progress <= 0.0) then
916  call messagenotify('W', subname, 'Specify 0.0 -- 1.0 value to "progress"')
917  return
918  elseif (progress > 1.0) then
919  call messagenotify('W', subname, 'Over 1.0 value to "progress" was modified to 1.0')
920  prog_valid = 1.0
921  else
922  prog_valid = progress
923  end if
924  if (present(unit)) then
925  out_unit = unit
926  else
927  out_unit = stdout
928  end if
929  call dcdifftimecreate( remain_diff, &
930  & sec = real(nint(EvalSec(clk) / prog_valid * (1.0 - prog_valid)), DP) )
931  call dcdatetimecreate(cur_date)
932  comp_date = cur_date + remain_diff
933  prog_percent = ''
934  prog_percent = adjustr(trim(printf_g5_2(real(prog_valid * 100, dp))) // '%')
935  prog_bar = ''
936  prog_bar_ptr = int(prog_valid * 25)
937  if (prog_bar_ptr > 0) prog_bar(1:prog_bar_ptr) = '*************************'
938  call printf(out_unit, '')
939  call printf(out_unit, &
940  & ' ########## PREDICTION OF CALCULATION ###########')
941  call printf(out_unit, &
942  & ' Start Date %c', c1=trim(tochar(clk % start_date)))
943  call printf(out_unit, &
944  & ' Current Date %c', c1=trim(tochar(cur_date)))
945  call printf(out_unit, &
946  & ' Progress %c [%c]', c1=prog_percent, c2=prog_bar)
947  call printf(out_unit, &
948  & ' Remaining CPU TIME %c %c', &
949  & c1=trim(result_value_form(evalsec(remain_diff))), &
950  & c2=trim(fit_unit_value(0.0_dp, remain_diff)))
951  call printf(out_unit, &
952  & ' Completion Date %c', c1=trim(tochar(comp_date)))
953 999 continue
954  call storeerror(stat, subname, err, cause_c)
955  call endsub(subname)
956  end subroutine dcclockpredict0
957 end module dc_clock
character(token) function printf_g5_2(value)
Definition: dc_clock.f90:725
type(clock) function dcclockadd(clk1, clk2)
Definition: dc_clock.f90:751
subroutine dcclockgetd(clk, sec, err)
Definition: dc_clock.f90:385
subroutine dcclockpredict0(clk, progress, unit, err)
Definition: dc_clock.f90:855
integer, parameter, public dc_enotinit
Definition: dc_error.f90:557
integer, parameter, public token
単語やキーワードを保持する文字型変数の種別型パラメタ
Definition: dc_types.f90:109
subroutine dcclockresult0(clks, unit, total_auto, clk_total, total_name, err)
Definition: dc_clock.f90:535
subroutine dcclockcreate0(clk, name)
Definition: dc_clock.f90:216
character(token) function fit_unit_value(sec, diff)
Definition: dc_clock.f90:680
type(clock) function dcclocksubtract(clk1, clk2)
Definition: dc_clock.f90:784
subroutine, public storeerror(number, where, err, cause_c, cause_i)
Definition: dc_error.f90:830
integer, parameter, public dc_noerr
Definition: dc_error.f90:509
real(dp) function dcclockevalsecd(clk)
Definition: dc_clock.f90:425
subroutine dcclockgetr(clk, sec, err)
Definition: dc_clock.f90:346
character(*), parameter version
Definition: dc_clock.f90:211
integer, parameter, public dp
倍精度実数型変数
Definition: dc_types.f90:83
subroutine, public dbgmessage(fmt, i, r, d, L, n, c1, c2, c3, ca)
Definition: dc_trace.f90:509
subroutine, public beginsub(name, fmt, i, r, d, L, n, c1, c2, c3, ca, version)
Definition: dc_trace.f90:351
subroutine dcclocksetname0(clk, name, err)
Definition: dc_clock.f90:818
character(string) function dcclocktochar0(clk)
Definition: dc_clock.f90:443
integer, parameter, public stdout
標準出力の装置番号
Definition: dc_types.f90:98
文字型変数の操作.
Definition: dc_string.f90:24
種別型パラメタを提供します。
Definition: dc_types.f90:49
subroutine dcclockstop0(clk, err)
Definition: dc_clock.f90:300
subroutine dcclockputline0(clk, unit, indent, err)
Definition: dc_clock.f90:468
character(token) function result_value_form(value)
Definition: dc_clock.f90:666
subroutine dcclockclose0(clk)
Definition: dc_clock.f90:245
subroutine dcclockstart0(clk, err)
Definition: dc_clock.f90:262
subroutine, public endsub(name, fmt, i, r, d, L, n, c1, c2, c3, ca)
Definition: dc_trace.f90:446
integer, parameter, public string
文字列を保持する 文字型変数の種別型パラメタ
Definition: dc_types.f90:118