30 logical:: syncing=.false.
31 logical:: dispatcher=.false.
32 real(8):: sync_time=-1.0, sync_next=-1.0
35 procedure:: initialize
36 procedure:: init_levels
38 procedure:: init_queue
42 procedure:: append_task_list
43 procedure:: print => print1
44 procedure:: init_levelstats
45 procedure:: init_task_list_pointers
47 real(8),
save:: dead_mans_hand=60d0, first_finished=0d0
56 SUBROUTINE init (self, name)
58 character(len=*),
optional:: name
59 class(
link_t),
pointer:: link
61 real(8),
save:: job_seconds=1d30
62 real(8),
save:: sync_time=0.0
63 logical,
save:: detailed_timer=.false.
64 integer,
save:: verbose=0
65 namelist /task_list_params/ verbose, job_seconds, dead_mans_hand, sync_time, &
70 call trace%begin(
'task_list_t%init')
71 call self%list_t%init (name)
75 read(io%input, task_list_params, iostat=iostat)
76 write (io%output, task_list_params)
77 if (sync_time > 0.0) &
78 self%sync_next = sync_time
79 self%sync_time = sync_time
80 io%job_seconds = job_seconds
81 timer%dead_mans_hand = dead_mans_hand
82 self%verbose = verbose
83 self%detailed_timer = detailed_timer
84 call load_balance%init
91 SUBROUTINE initialize (self)
94 call trace%begin (
'task_list_t%initialize')
96 call self%init_all_nbors
97 call self%reset_status
98 call self%count_status
100 END SUBROUTINE initialize
106 SUBROUTINE init_levels (self)
108 type(
link_t),
pointer:: link
109 logical:: first_time=.true.
110 integer:: levelmin, levelmax
112 call trace%begin (
'task_list_t%init_levels')
119 do while (
associated(link))
120 associate(patch => link%task)
123 call patch%init_level
127 levelmin = patch%level
128 levelmax = patch%level
130 levelmin = min(levelmin,patch%level)
131 levelmax = max(levelmax,patch%level)
141 refine%levelmin = levelmin
142 refine%levelmax = max(levelmax,refine%levelmax)
147 refine%levelmin = levelmin
148 refine%levelmax = levelmax
150 write (io%output,*) &
151 'task_list_t%init_levels: levelmin,max =', refine%levelmin, refine%levelmax
155 if (refine%levelmax > refine%levelmin) &
156 download%check_filled = .true.
157 call self%init_levelstats
158 shared%levelmax = levelmax
160 END SUBROUTINE init_levels
166 SUBROUTINE startup (self)
169 class(link_t),
pointer:: link, rem
170 class(task_t),
pointer:: task
173 integer,
save:: itimer=0
174 logical:: was_refined
176 call trace%begin (
'task_list_t%startup', itimer=itimer)
177 if (.not.self%dispatcher)
call mpi%abort (
"no dispatcher is used to execute the task list. Execution is unpredictable, therefore aborting.")
194 call self%init_levels
195 call self%task_mesg_t%init
203 call self%task_mesg_t%init_virtual ()
204 if (io%restart >= 0)
then 205 call self%resend_bdry ()
217 print
'(a,f8.3,a)',
' Memory per process:', io%gb,
' GB' 218 call mpi%barrier (
'self%execute')
221 self%n_tasks = self%na
222 call trace%end (itimer)
223 END SUBROUTINE startup
228 SUBROUTINE init_queue (self)
230 class(link_t),
pointer:: link
232 call trace%begin (
'task_list_t%init_queue')
234 do while (
associated(link))
235 call link%task%clear(bits%ready)
236 if (link%task%is_set(bits%virtual))
then 237 link%task%wc_last = wallclock()
239 call self%check_ready (link)
241 if (self%sync_time > 0.0) &
242 link%task%sync_time = link%task%time + self%sync_time
245 if (self%verbose > 0) &
246 call self%print_queue_times (
'init_queue')
248 END SUBROUTINE init_queue
254 SUBROUTINE execute (self)
259 integer,
save:: itimer=0
261 call trace%begin (
'task_list_t%execute', itimer=itimer)
269 do while (self%na > 0 .and. .not.io%do_stop)
270 call self%update (self%head, .false.)
273 call mpi_mesg%diagnostics(1)
274 write (io_unit%log,*)
'thread',omp%thread,
' arrived' 277 call toc (
'wall time', timer%n_update, time=sec)
278 call mpi%barrier (
'end')
282 call trace%end (itimer)
283 END SUBROUTINE execute
288 SUBROUTINE update (self, head, test, was_refined, was_derefined)
290 class(link_t),
pointer:: head
292 logical,
optional:: was_refined, was_derefined
294 class(task_t),
pointer:: task
295 real(8):: wc, levelstart
296 logical:: refined, derefined
297 integer,
save:: itimer=0
299 call trace%begin(
'task_list_t%update', itimer=itimer)
303 levelstart = wallclock()
306 if (task%id==io%id_track)
then 307 task%track = .not.task%track
313 if (task%is_set (bits%frozen))
then 314 call task%clear (bits%ready)
315 call trace%end (itimer)
332 call refine%check_current(self, head, refined, derefined)
334 if (
present(was_refined))
then 335 was_refined = refined
337 if (
present(was_derefined))
then 338 was_derefined = derefined
344 call trace%end (itimer)
350 if (mpi_mesg%delay_ms==0.0)
then 353 task%rotated = .false.
355 call task%test_update
359 call validate%check (head, task%mem(:,:,:,task%idx%d,task%it,1),
'before update')
369 if (self%verbose > 0)
then 370 associate(unit => merge(io_unit%log, io_unit%mpi, self%verbose > 1))
371 write (unit,
'(f12.6,2x,a,i6,1p,g14.6)') &
372 wallclock(),
'update:', task%id, task%time+task%dtime
380 if (mpi_mesg%delay_ms==0.0)
then 382 mpi_mesg%delay_ms = 1d3*(wallclock()-wc)*0.1
385 mpi_mesg%n_update = mpi_mesg%n_update+1
386 if (self%verbose>1) &
387 write (io_unit%log,
'(a,i4,2x,a,i7,2x,a,2x,a,i7,2x,a,1p,2g14.6,2x,a,2i5,l3)') &
388 'thread', omp_mythread,
'task', task%id, trim(task%type), &
389 'step', task%istep,
'dt, time:', task%dtime, task%time, &
390 'n, nq', self%n, self%nq,
associated(head%nbor)
398 if (.not.task%rotated)
then 402 class is (experiment_t)
403 call validate%check (head, task%mem(:,:,:,task%idx%d,task%it,1),
' after update')
404 call task%info (self%nq, self%na)
406 if (io%log_sent > 0)
then 408 call mpi_mesg%log_files ()
409 write (io_unit%sent,
'(f16.6,i4,2x,a,i6,f16.6,l5)') &
410 wallclock(), omp%thread,
'upd', task%id, task%time, task%is_set(bits%boundary)
421 if (task%is_set(bits%boundary))
then 422 head%task%nq = self%nq
423 if (load_balance%check_load (head))
then 424 call self%count_status
426 if (task%id == io%id_debug) &
427 write(io_unit%mpi,*) &
428 'DBG task_list_t%update: calling send_to_vnbors', task%id
429 call task%log (
'send')
430 call self%send_to_vnbors (head)
436 if (task%is_set (bits%init_nbors))
then 437 call self%init_nbors (head)
438 call self%check_ready (head)
439 if (self%verbose > 1)
then 441 else if (self%verbose > 0)
then 442 write (io_unit%log,*)
'task_list_t%update: init_nbors for task', task%id
452 if (task%has_finished())
then 457 if (first_finished == 0.0)
then 459 first_finished = wallclock()
460 else if (wallclock() > first_finished+dead_mans_hand)
then 461 call dead_mans_hand_list (self)
464 call load_balance%active (.false.)
468 if (task%is_clear (bits%frozen))
then 469 call task%set (bits%frozen)
470 call self%count_status (
'has_finished')
471 if (self%verbose > 0)
then 472 write (io_unit%log,*) task%id,
'has finished, na =', self%na
477 if (task%time > io%end_time .and. task%is_clear(bits%frozen))
then 478 print *, mpi%rank, omp%thread,
'ERROR: task should be frozen', &
479 task%time, io%end_time, task%is_set(bits%frozen), task%has_finished()
480 call task%set (bits%frozen)
488 if (self%syncing)
then 489 write (io_unit%mpi,*) task%id,omp%thread, &
490 ' is waiting on a sync at t =', self%sync_next
492 call mpi%barrier (
'sync')
494 write (io_unit%mpi,*) task%id,omp%thread, &
495 ' finished wating on a sync at t =', self%sync_next
496 self%sync_next = self%sync_next + self%sync_time
497 self%syncing = .false.
499 task%sync_time = self%sync_next
503 if (.not.was_derefined)
then 505 timer%levelcost(task%level) = &
506 timer%levelcost(task%level) + (wallclock() - levelstart)
508 call trace%end (itimer)
509 END SUBROUTINE update
514 SUBROUTINE dead_mans_hand_list (self)
516 class(link_t),
pointer:: link
518 write (stderr,*)
'Updates stopped after expired dead_mans_hand time!' 519 write (stderr,*)
'Active tasks remaining:', self%na
521 do while (
associated(link))
522 write (stderr,*)
'task id, time =', link%task%id, link%task%time
525 write (stderr,*)
'tasks in garbage:' 527 do while (
associated(link))
528 write (stderr,*)
'task id, time =', &
529 link%task%id, link%task%time, link%task%n_needed
532 END SUBROUTINE dead_mans_hand_list
537 FUNCTION average (self, idx, time)
540 real(8):: average, time
542 class(link_t) ,
pointer:: link
543 class(task_t) ,
pointer:: task
544 real(8),
dimension(:,:,:),
allocatable:: buffer
545 integer:: n, m(3), jt(2), l(3), u(3)
550 call trace%begin (
'task_list_t%average')
552 time = link%task%time
553 do while (
associated(link))
554 time = min(time, link%task%time)
563 do while (
associated(link))
570 call task%time_interval (time, jt, pt)
571 if (.not.
allocated(buffer)) &
572 allocate (buffer(m(1),m(2),m(3)))
573 buffer = task%mem(l(1):u(1),l(2):u(2),l(3):u(3),idx,jt(1),1)*pt(1) &
574 + task%mem(l(1):u(1),l(2):u(2),l(3):u(3),idx,jt(2),1)*pt(2)
575 average = average + sum(buffer)
581 average = average/n/product(shape(buffer))
588 SUBROUTINE append_task_list (self, task_list)
591 class(list_t),
pointer:: list
593 call trace%begin (
'task_list_t%append_task_list')
595 call self%append_list (list)
597 END SUBROUTINE append_task_list
602 SUBROUTINE print1 (self, label)
604 character(len=*),
optional:: label
605 class(link_t) ,
pointer:: link, nbor
607 call trace%begin (
'task_list_t%print_tasklist')
608 if (io%master.and.
present(label))
write (io_unit%output,*) label
610 do while (
associated(link))
611 call link%print_nbors (
'')
614 call self%print_queue
616 END SUBROUTINE print1
621 FUNCTION task2experiment (task)
RESULT (exper)
622 class(task_t),
pointer:: task
623 class(experiment_t),
pointer:: exper
626 class is (experiment_t)
629 END FUNCTION task2experiment
636 SUBROUTINE init_levelstats (self)
638 class(link_t),
pointer:: link
640 call trace%begin (
'task_list_t%init_levelstats')
642 if (.not.
allocated(timer%levelcost))
then 643 allocate (timer%levelpop (refine%levelmin:refine%levelmax))
644 timer%levelmin = refine%levelmin
645 timer%levelmax = refine%levelmax
648 do while (
associated(link))
650 timer%levelpop(link%task%level) = &
651 timer%levelpop(link%task%level) + 1
655 allocate (timer%levelcost(refine%levelmin:refine%levelmax))
656 timer%levelcost = 0d0
660 END SUBROUTINE init_levelstats
665 SUBROUTINE init_task_list_pointers (self, task_list)
668 class(list_t),
pointer:: list
669 class(link_t),
pointer:: link
673 call trace%begin (
'task_list_t%init_task_list_pointers')
676 do while (
associated(link))
677 associate(task=>link%task)
679 class is (experiment_t)
680 call task%init_task_list (list)
Each thread uses a private timer data type, with arrays for start time and total time for each regist...
download_link: takes care of downloads to linktask same: called for patches on the same level differ:...
Support tic/toc timing, as in MATLAB, and accurate wallclock() function. The timing is generally much...
Generic validation module. The general idea is to be able to compare two runs at critical points in t...
Module with list handling for generic class task_t objects.
Template module for patches, which adds pointers to memory and mesh, and number of dimensions and var...
This module handles checking max change between neighboring points. Each instance of it needs an inde...
This module is a placeholder for shared information, solving the problem of making a piece of informa...
Message handling for task lists. Some of the methods are only used by dispatcher0_t, so should perhaps be moved over to that file.
Task list data type, with methods for startup and updates. Message handling is inherited from the tas...
Module with list handling for generic class task_t objects.
Keep track of neighbor ranks and their loads, by sending and receiving short messages, storing the info in a linked list.
Template module for tasks.