mirror of
https://github.com/cp2k/cp2k.git
synced 2026-07-28 14:15:19 -04:00
add a master-slave mode for doing farming.
This improves load balance in the case where jobs of unequal lenght are being processed. Allow for dependencies between jobs in a farming run. svn-origin-rev: 6390
This commit is contained in:
parent
6cf31a5ed3
commit
c1cfd7176f
19 changed files with 1139 additions and 155 deletions
415
src/cp2k_runs.F
415
src/cp2k_runs.F
|
|
@ -36,10 +36,15 @@ MODULE cp2k_runs
|
|||
f_env_add_defaults,&
|
||||
f_env_rm_defaults,&
|
||||
f_env_type
|
||||
USE farming_methods, ONLY: farming_parse_input
|
||||
USE farming_methods, ONLY: farming_parse_input, &
|
||||
get_next_job, &
|
||||
do_nothing, &
|
||||
do_wait, &
|
||||
do_deadlock
|
||||
USE farming_types, ONLY: deallocate_farming_env,&
|
||||
farming_env_type,&
|
||||
init_farming_env
|
||||
init_farming_env,&
|
||||
job_pending,job_running,job_finished
|
||||
USE fist_debug, ONLY: fist_debug_control => debug_control
|
||||
USE force_env_methods, ONLY: force_env_calc_energy_force
|
||||
USE force_env_types, ONLY: force_env_get,&
|
||||
|
|
@ -71,21 +76,20 @@ MODULE cp2k_runs
|
|||
dp
|
||||
USE library_tests, ONLY: lib_test
|
||||
USE machine, ONLY: m_chdir,&
|
||||
m_flush,&
|
||||
m_getcwd,&
|
||||
m_walltime
|
||||
USE mc_run, ONLY: do_mon_car
|
||||
USE md_run, ONLY: qs_mol_dyn
|
||||
USE message_passing, ONLY: mp_comm_free,&
|
||||
mp_comm_split,&
|
||||
mp_environ,&
|
||||
mp_sum,&
|
||||
mp_sync
|
||||
USE message_passing, ONLY: &
|
||||
mp_any_source, mp_bcast, mp_comm_dup, mp_comm_free, mp_comm_split, &
|
||||
mp_environ, mp_recv, mp_send, mp_sum, mp_sync
|
||||
USE neb_methods, ONLY: neb
|
||||
USE pint_methods, ONLY: do_pint_run
|
||||
USE qs_debug, ONLY: qs_debug_energy_and_forces
|
||||
USE qs_linres_module, ONLY: linres_calculation
|
||||
USE qs_tddfpt_module, ONLY: tddfpt_calculation
|
||||
USE reference_manager, ONLY: print_all_references, &
|
||||
USE reference_manager, ONLY: print_all_references,&
|
||||
print_format_html
|
||||
USE timings, ONLY: timeset,&
|
||||
timestop
|
||||
|
|
@ -427,15 +431,22 @@ CPSourceFileRef,&
|
|||
|
||||
CHARACTER(len=*), PARAMETER :: routineN = 'farming_run', &
|
||||
routineP = moduleN//':'//routineN
|
||||
INTEGER, PARAMETER :: slave_status_done = -3, &
|
||||
slave_status_wait = -4
|
||||
|
||||
CHARACTER(len=5) :: label
|
||||
CHARACTER(LEN=default_path_length) :: output_file
|
||||
CHARACTER(LEN=default_string_length) :: str
|
||||
INTEGER :: handle, i, i_job_to_restart, ierr, ijob, ijob_end, ijob_start, &
|
||||
iunit, n_jobs_to_run, new_group, new_output_unit, new_rank, new_size, &
|
||||
ngroups, output_unit, stat
|
||||
INTEGER, DIMENSION(:), POINTER :: group_distribution
|
||||
LOGICAL :: failure, found, run_OK
|
||||
INTEGER :: dest, handle, i, i_job_to_restart, ierr, ijob, ijob_end, &
|
||||
ijob_start, ijob_current, iunit, n_jobs_to_run, new_group, new_output_unit, new_rank, &
|
||||
new_size, ngroups, num_slaves, output_unit, primus_slave, slave_group, &
|
||||
slave_rank, source, stat, tag, todo
|
||||
INTEGER, DIMENSION(:), POINTER :: group_distribution, &
|
||||
master_slave_partition, &
|
||||
slave_distribution, &
|
||||
slave_status
|
||||
LOGICAL :: failure, found, master, &
|
||||
run_OK, slave
|
||||
REAL(KIND=dp) :: t1, t2
|
||||
REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: waittime
|
||||
TYPE(cp_logger_type), POINTER :: logger
|
||||
|
|
@ -445,6 +456,8 @@ CPSourceFileRef,&
|
|||
TYPE(section_type), POINTER :: g_section
|
||||
TYPE(section_vals_type), POINTER :: g_data
|
||||
|
||||
! the primus of all slaves, talks to the master on topics concerning all slaves
|
||||
|
||||
failure=.FALSE.
|
||||
CALL timeset(routineN,'I','',handle)
|
||||
NULLIFY(my_parser,g_section,g_data,default_units)
|
||||
|
|
@ -462,25 +475,94 @@ CPSourceFileRef,&
|
|||
CALL m_getcwd(farming_env%cwd)
|
||||
CALL farming_parse_input(farming_env,root_section,para_env,error)
|
||||
|
||||
! split the current communicator
|
||||
ALLOCATE(group_distribution(0:para_env%num_pe-1),STAT=stat)
|
||||
CPPostcondition(stat==0,cp_failure_level,routineP,error,failure)
|
||||
IF (farming_env%group_size_wish_set) THEN
|
||||
CALL mp_comm_split(para_env%group,new_group,ngroups,group_distribution,&
|
||||
subgroup_min_size=farming_env%group_size_wish)
|
||||
ELSE IF (farming_env%ngroup_wish_set) THEN
|
||||
CALL mp_comm_split(para_env%group,new_group,ngroups,group_distribution,&
|
||||
n_subgroups=farming_env%ngroup_wish,&
|
||||
group_partition=farming_env%group_partition)
|
||||
ELSE
|
||||
CPPostcondition(.FALSE.,cp_failure_level,routineP,error,failure)
|
||||
ENDIF
|
||||
CALL mp_environ(new_size,new_rank,new_group)
|
||||
! the full mpi group is first split in a slave group and a master group, the latter being at most 1 process
|
||||
slave=.TRUE.
|
||||
master=.FALSE.
|
||||
IF (farming_env%master_slave) THEN
|
||||
IF (output_unit>0) WRITE(output_unit,FMT="(T2,A)") "FARMING| using a master-slave setup"
|
||||
|
||||
ALLOCATE(master_slave_partition(0:1))
|
||||
master_slave_partition=(/1,para_env%num_pe-1/)
|
||||
ALLOCATE(group_distribution(0:para_env%num_pe-1),STAT=stat)
|
||||
CPPostcondition(stat==0,cp_failure_level,routineP,error,failure)
|
||||
|
||||
CALL mp_comm_split(para_env%group,slave_group,ngroups,group_distribution,&
|
||||
n_subgroups=2, group_partition=master_slave_partition)
|
||||
DEALLOCATE(master_slave_partition)
|
||||
DEALLOCATE(group_distribution)
|
||||
CALL mp_environ(num_slaves,slave_rank,slave_group)
|
||||
|
||||
IF (para_env%mepos==0) THEN
|
||||
slave =.FALSE.
|
||||
master=.TRUE.
|
||||
! on the master node, num_slaves corresponds to the size of the master group
|
||||
! due to the mp_environ call.
|
||||
CPPostcondition(num_slaves==1,cp_failure_level,routineP,error,failure)
|
||||
num_slaves=para_env%num_pe-1
|
||||
slave_rank=-1
|
||||
ENDIF
|
||||
CPPostcondition(num_slaves==para_env%num_pe-1,cp_failure_level,routineP,error,failure)
|
||||
ELSE
|
||||
! all processes are slaves
|
||||
IF (output_unit>0) WRITE(output_unit,FMT="(T2,A)") "FARMING| using a slave-only setup"
|
||||
CALL mp_comm_dup(para_env%group,slave_group)
|
||||
CALL mp_environ(num_slaves,slave_rank,slave_group)
|
||||
ENDIF
|
||||
IF (output_unit>0) WRITE(output_unit,FMT="(T2,A,I0)") "FARMING| number of slaves ",num_slaves
|
||||
|
||||
! keep track of which para_env rank is which slave/master
|
||||
ALLOCATE(slave_distribution(0:para_env%num_pe-1),STAT=stat)
|
||||
CPPostcondition(stat==0,cp_failure_level,routineP,error,failure)
|
||||
slave_distribution=0
|
||||
slave_distribution(para_env%mepos)=slave_rank
|
||||
CALL mp_sum(slave_distribution,para_env%group)
|
||||
! we do have a primus inter pares
|
||||
primus_slave=0
|
||||
DO i=1,para_env%num_pe-1
|
||||
IF (slave_distribution(i)==0) primus_slave=i
|
||||
ENDDO
|
||||
|
||||
! split the current communicator for the slaves
|
||||
! in a new_group, new_size and new_rank according to the number of groups required according to the input
|
||||
ALLOCATE(group_distribution(0:num_slaves-1),STAT=stat)
|
||||
CPPostcondition(stat==0,cp_failure_level,routineP,error,failure)
|
||||
group_distribution=-1
|
||||
IF (slave) THEN
|
||||
IF (farming_env%group_size_wish_set) THEN
|
||||
CALL mp_comm_split(slave_group,new_group,ngroups,group_distribution,&
|
||||
subgroup_min_size=farming_env%group_size_wish)
|
||||
ELSE IF (farming_env%ngroup_wish_set) THEN
|
||||
CALL mp_comm_split(slave_group,new_group,ngroups,group_distribution,&
|
||||
n_subgroups=farming_env%ngroup_wish,&
|
||||
group_partition=farming_env%group_partition)
|
||||
ELSE
|
||||
CPPostcondition(.FALSE.,cp_failure_level,routineP,error,failure)
|
||||
ENDIF
|
||||
CALL mp_environ(new_size,new_rank,new_group)
|
||||
ENDIF
|
||||
|
||||
|
||||
! transfer the info about the slave group distribution to the master
|
||||
IF (farming_env%master_slave) THEN
|
||||
IF (para_env%mepos==primus_slave) THEN
|
||||
tag=1
|
||||
CALL mp_send(group_distribution,0,tag,para_env%group)
|
||||
tag=2
|
||||
CALL mp_send(ngroups,0,tag,para_env%group)
|
||||
ENDIF
|
||||
IF (para_env%mepos==0) THEN
|
||||
tag=1
|
||||
CALL mp_recv(group_distribution,primus_slave,tag,para_env%group)
|
||||
tag=2
|
||||
CALL mp_recv(ngroups,primus_slave,tag,para_env%group)
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
! write info on group distribution
|
||||
IF (output_unit>0) THEN
|
||||
WRITE(output_unit,FMT="(T2,A,T71,I10)") "FARMING| Number of created MPI groups:",ngroups
|
||||
WRITE(output_unit,FMT="(T2,A)",ADVANCE="NO") "FARMING| Task to group correspondence:"
|
||||
DO i=0,para_env%num_pe-1
|
||||
WRITE(output_unit,FMT="(T2,A,T71,I10)") "FARMING| Number of created MPI (slave) groups:",ngroups
|
||||
WRITE(output_unit,FMT="(T2,A)",ADVANCE="NO") "FARMING| MPI (slave) process to group correspondence:"
|
||||
DO i=0,num_slaves-1
|
||||
IF (MODULO(i,4)==0) WRITE(output_unit,*)
|
||||
WRITE(output_unit,FMT='(A3,I4,A3,I4,A1)',ADVANCE="NO")&
|
||||
" (",i," : ",group_distribution(i),")"
|
||||
|
|
@ -489,10 +571,9 @@ CPSourceFileRef,&
|
|||
ENDIF
|
||||
|
||||
! protect about too many jobs being run in single go. Not more jobs are allowed than the number in the input file
|
||||
|
||||
! and determine the restart point
|
||||
! and determine the future restart point
|
||||
IF (farming_env%cycle) THEN
|
||||
n_jobs_to_run=MIN(farming_env%njobs,farming_env%max_steps*ngroups)
|
||||
n_jobs_to_run=farming_env%max_steps*ngroups
|
||||
i_job_to_restart=MODULO(farming_env%restart_n+n_jobs_to_run-1,farming_env%njobs)+1
|
||||
ELSE
|
||||
n_jobs_to_run=MIN(farming_env%njobs,farming_env%max_steps*ngroups)
|
||||
|
|
@ -500,7 +581,7 @@ CPSourceFileRef,&
|
|||
i_job_to_restart=n_jobs_to_run+farming_env%restart_n
|
||||
ENDIF
|
||||
|
||||
! and write it now, that's the point where the next job starts, even if this one is running
|
||||
! and write the restart now, that's the point where the next job starts, even if this one is running
|
||||
IF (para_env%ionode) THEN
|
||||
iunit=get_unit_number()
|
||||
OPEN(UNIT=iunit,FILE="RESTARTFARM")
|
||||
|
|
@ -508,112 +589,171 @@ CPSourceFileRef,&
|
|||
CLOSE(UNIT=iunit)
|
||||
ENDIF
|
||||
|
||||
! this is the job range to be executed. Will be treated cycle
|
||||
! this is the job range to be executed.
|
||||
ijob_start=farming_env%restart_n
|
||||
ijob_end=ijob_start+n_jobs_to_run-1
|
||||
|
||||
IF (output_unit>0) THEN
|
||||
IF (ijob_end-ijob_start<0) THEN
|
||||
WRITE(output_unit,FMT="(T2,A)") "FARMING| --- WARNING --- NO JOBS NEED EXECUTION ? "
|
||||
WRITE(output_unit,FMT="(T2,A)") "FARMING| is the cycle keyword required ?"
|
||||
WRITE(output_unit,FMT="(T2,A)") "FARMING| or is a stray RESTARTFARM present ?"
|
||||
ELSE
|
||||
WRITE(output_unit,FMT="(T2,A)") "FARMING| List of jobs : "
|
||||
DO ijob=ijob_start,ijob_end
|
||||
i=MODULO(ijob-1,farming_env%njobs)+1
|
||||
WRITE(output_unit,FMT=*) "Job: ",i," Dir: ",TRIM(farming_env%Job_cwd(i))," Input: ", &
|
||||
TRIM(farming_env%Job_input(i))," MPI group:", MODULO(i-1,ngroups)
|
||||
ENDDO
|
||||
ENDIF
|
||||
IF (output_unit>0 .AND. ijob_end-ijob_start<0) THEN
|
||||
WRITE(output_unit,FMT="(T2,A)") "FARMING| --- WARNING --- NO JOBS NEED EXECUTION ? "
|
||||
WRITE(output_unit,FMT="(T2,A)") "FARMING| is the cycle keyword required ?"
|
||||
WRITE(output_unit,FMT="(T2,A)") "FARMING| or is a stray RESTARTFARM present ?"
|
||||
WRITE(output_unit,FMT="(T2,A)") "FARMING| or is the group_size requested smaller than the number of CPUs?"
|
||||
ENDIF
|
||||
|
||||
! actual executions of the jobs in two different modes
|
||||
IF (farming_env%master_slave) THEN
|
||||
IF (slave) THEN
|
||||
! keep on doing work until master has decided otherwise
|
||||
todo=do_wait
|
||||
DO
|
||||
IF (new_rank==0) THEN
|
||||
! the head slave tells the master he's done or ready to start
|
||||
! the message tells what has been done lately
|
||||
tag=1
|
||||
dest=0
|
||||
CALL mp_send(todo,dest,tag,para_env%group)
|
||||
|
||||
DO ijob=ijob_start,ijob_end
|
||||
i=MODULO(ijob-1,farming_env%njobs)+1
|
||||
! this farms out the jobs
|
||||
IF (MODULO(ijob-1,ngroups)==group_distribution(para_env%mepos)) THEN
|
||||
! change to the new working directory
|
||||
CALL m_chdir(TRIM(farming_env%Job_cwd(i)),ierr)
|
||||
! gets the new todo item
|
||||
tag=2
|
||||
source=0
|
||||
CALL mp_recv(todo,source,tag,para_env%group)
|
||||
|
||||
! generate a fresh call to cp2k_run
|
||||
IF (ierr==0) THEN
|
||||
IF (new_rank == 0) THEN
|
||||
! and informs his peer slaves
|
||||
CALL mp_bcast(todo,0,new_group)
|
||||
ELSE
|
||||
CALL mp_bcast(todo,0,new_group)
|
||||
ENDIF
|
||||
|
||||
! if the todo is do_nothing we are flagged to quit. Otherwise it is the job number
|
||||
SELECT CASE(todo)
|
||||
CASE(do_wait,do_deadlock)
|
||||
! go for a next round, but we first wait a bit
|
||||
t1=m_walltime()
|
||||
DO
|
||||
t2=m_walltime()
|
||||
IF (t2-t1>farming_env%wait_time) EXIT
|
||||
ENDDO
|
||||
CASE(do_nothing)
|
||||
EXIT
|
||||
CASE(1:)
|
||||
CALL execute_job(todo)
|
||||
END SELECT
|
||||
ENDDO
|
||||
ELSE ! master
|
||||
ALLOCATE(slave_status(0:ngroups-1),STAT=stat)
|
||||
CPPostcondition(stat==0,cp_failure_level,routineP,error,failure)
|
||||
slave_status=slave_status_wait
|
||||
ijob_current=ijob_start-1
|
||||
|
||||
! generate the output file
|
||||
WRITE(output_file,'(A12,I5.5)') "FARMING_OUT_",i
|
||||
CALL parser_create(my_parser,file_name=TRIM(farming_env%Job_input(i)),error=error)
|
||||
label="&GLOBAL"
|
||||
CALL parser_search_string(my_parser,label,ignore_case=.TRUE.,found=found,error=error)
|
||||
IF (found) THEN
|
||||
CALL create_global_section(g_section,error=error)
|
||||
CALL section_vals_create(g_data,g_section,error=error)
|
||||
CALL cp_unit_set_create(default_units, "OUTPUT",error=error)
|
||||
CALL section_vals_parse(g_data,my_parser,default_units,&
|
||||
error=error)
|
||||
CALL cp_unit_set_release(default_units,error=error)
|
||||
CALL section_vals_val_get(g_data,"PROJECT",&
|
||||
c_val=str, error=error)
|
||||
IF (str.NE."") output_file=TRIM(str)//".out"
|
||||
CALL section_vals_val_get(g_data,"OUTPUT_FILE_NAME",&
|
||||
c_val=str,error=error)
|
||||
IF (str.NE."") output_file=str
|
||||
CALL section_vals_release(g_data,error=error)
|
||||
CALL section_release(g_section,error=error)
|
||||
END IF
|
||||
CALL parser_release(my_parser,error=error)
|
||||
CALL open_file(file_name=TRIM(output_file),&
|
||||
file_action="WRITE",&
|
||||
file_status="UNKNOWN",&
|
||||
file_position="APPEND",&
|
||||
unit_number=new_output_unit)
|
||||
ELSE
|
||||
! this should never be used by cp2k_run, but e.g. still happens, incorrectly,
|
||||
! on eror, writes now to fort.999 so that error messages can be recovered and fixed
|
||||
new_output_unit=999
|
||||
ENDIF
|
||||
DO
|
||||
IF (ALL(slave_status==slave_status_done)) EXIT
|
||||
|
||||
IF (output_unit > 0) WRITE(output_unit,FMT="(T2,A,I5.5,A)") " Running Job ",i, &
|
||||
" output to "//TRIM(farming_env%Job_cwd(i))//"/"//TRIM(output_file)
|
||||
run_OK=cp2k_run(TRIM(farming_env%Job_input(i)),new_output_unit,new_group)
|
||||
! who's the next slave waiting for work
|
||||
tag=1
|
||||
source=mp_any_source
|
||||
CALL mp_recv(todo,source,tag,para_env%group) ! updates source
|
||||
IF (todo>0) THEN
|
||||
farming_env%Job(todo)%status=job_finished
|
||||
IF (output_unit>0) THEN
|
||||
WRITE(output_unit,FMT=*) "Job finished: ",todo
|
||||
CALL m_flush(output_unit)
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
IF (new_rank == 0) CALL close_file(unit_number=new_output_unit)
|
||||
! get the next job in line, this could be do_nothing, if we're finished
|
||||
CALL get_next_job(farming_env,ijob_start,ijob_end,ijob_current,todo)
|
||||
dest=source
|
||||
tag =2
|
||||
CALL mp_send(todo,dest,tag,para_env%group)
|
||||
|
||||
ELSE ! problem if just one node does not change...
|
||||
IF (output_unit > 0 ) WRITE(output_unit,FMT="(T2,A,A)") &
|
||||
" ... Failed to change dir to "//TRIM(farming_env%Job_cwd(i))
|
||||
ENDIF
|
||||
IF (todo>0) THEN
|
||||
farming_env%Job(todo)%status=job_running
|
||||
IF (output_unit>0) THEN
|
||||
WRITE(output_unit,FMT=*) "Job: ",todo," Dir: ",TRIM(farming_env%Job(todo)%cwd), &
|
||||
" assigned to group ",group_distribution(slave_distribution(dest))
|
||||
CALL m_flush(output_unit)
|
||||
ENDIF
|
||||
ELSE
|
||||
IF (todo==do_nothing) THEN
|
||||
slave_status(group_distribution(slave_distribution(dest)))=slave_status_done
|
||||
IF (output_unit>0) THEN
|
||||
WRITE(output_unit,FMT=*) "group done: ",group_distribution(slave_distribution(dest))
|
||||
CALL m_flush(output_unit)
|
||||
ENDIF
|
||||
ENDIF
|
||||
IF (todo==do_deadlock) THEN
|
||||
IF (output_unit>0) THEN
|
||||
WRITE(output_unit,FMT=*) ""
|
||||
WRITE(output_unit,FMT=*) "FARMING JOB DEADLOCKED ... CIRCULAR DEPENDENCIES"
|
||||
WRITE(output_unit,FMT=*) ""
|
||||
CALL m_flush(output_unit)
|
||||
ENDIF
|
||||
CPPostcondition(todo.NE.do_deadlock,cp_failure_level,routineP,error,failure)
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
! change to the original working directory
|
||||
CALL m_chdir(TRIM(farming_env%cwd),ierr)
|
||||
IF (ierr/=0) THEN
|
||||
IF (output_unit > 0) WRITE(output_unit,FMT="(T2,A,A)") &
|
||||
" ... Failed to change back home to "//TRIM(farming_env%cwd)
|
||||
ENDIF
|
||||
ENDDO
|
||||
|
||||
DEALLOCATE(slave_status,STAT=stat)
|
||||
CPPostcondition(stat==0,cp_failure_level,routineP,error,failure)
|
||||
|
||||
ENDIF
|
||||
ENDDO
|
||||
ELSE
|
||||
! this is the non-master-slave mode way of executing the jobs
|
||||
! the i-th job in the input is always executed by the MODULO(i-1,ngroups)-th group
|
||||
! (needed for cyclic runs, we don't want two groups working on the same job)
|
||||
IF (output_unit>0) THEN
|
||||
IF (ijob_end-ijob_start>=0) THEN
|
||||
WRITE(output_unit,FMT="(T2,A)") "FARMING| List of jobs : "
|
||||
DO ijob=ijob_start,ijob_end
|
||||
i=MODULO(ijob-1,farming_env%njobs)+1
|
||||
WRITE(output_unit,FMT=*) "Job: ",i," Dir: ",TRIM(farming_env%Job(i)%cwd)," Input: ", &
|
||||
TRIM(farming_env%Job(i)%input)," MPI group:", MODULO(i-1,ngroups)
|
||||
ENDDO
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
DO ijob=ijob_start,ijob_end
|
||||
i=MODULO(ijob-1,farming_env%njobs)+1
|
||||
! this farms out the jobs
|
||||
IF (MODULO(i-1,ngroups)==group_distribution(slave_rank)) THEN
|
||||
IF (output_unit > 0) WRITE(output_unit,FMT="(T2,A,I5.5,A)",ADVANCE="NO") " Running Job ",i, &
|
||||
" in "//TRIM(farming_env%Job(i)%cwd)//"."
|
||||
CALL execute_job(i)
|
||||
IF (output_unit > 0) WRITE(output_unit,FMT="(A)") " Done, output in "//TRIM(output_file)
|
||||
ENDIF
|
||||
ENDDO
|
||||
ENDIF
|
||||
|
||||
! keep information about how long each process has to wait
|
||||
! i.e. the load imbalance
|
||||
t1=m_walltime()
|
||||
CALL mp_sync(para_env%group)
|
||||
t2=m_walltime()
|
||||
ALLOCATE(waittime(0:ngroups-1))
|
||||
ALLOCATE(waittime(0:para_env%num_pe-1))
|
||||
waittime=0.0_dp
|
||||
IF (new_rank==0) waittime(group_distribution(para_env%mepos))=t2-t1
|
||||
waittime(para_env%mepos)=t2-t1
|
||||
CALL mp_sum(waittime,para_env%group)
|
||||
IF (output_unit>0) THEN
|
||||
WRITE(output_unit,'(T2,A)') "Group idle times [s] at the end of the run"
|
||||
DO i=0,ngroups-1
|
||||
WRITE(output_unit,'(T2,A)') "Process idle times [s] at the end of the run"
|
||||
DO i=0,para_env%num_pe-1
|
||||
WRITE(output_unit,FMT='(A2,I4,A3,F8.3,A1)',ADVANCE="NO")&
|
||||
" (",i," : ",waittime(i),")"
|
||||
IF (MOD(i+1,4)==0) WRITE(output_unit,'(A)') ""
|
||||
ENDDO
|
||||
CALL m_flush(output_unit)
|
||||
ENDIF
|
||||
DEALLOCATE(waittime)
|
||||
|
||||
! give back the communicators of the split groups
|
||||
CALL mp_comm_free(new_group)
|
||||
IF (slave) CALL mp_comm_free(new_group)
|
||||
CALL mp_comm_free(slave_group)
|
||||
|
||||
! and message passing deallocate structures
|
||||
DEALLOCATE(group_distribution,STAT=stat)
|
||||
CPPostcondition(stat==0,cp_failure_level,routineP,error,failure)
|
||||
DEALLOCATE(slave_distribution,STAT=stat)
|
||||
CPPostcondition(stat==0,cp_failure_level,routineP,error,failure)
|
||||
|
||||
! clean the farming env
|
||||
CALL deallocate_farming_env(farming_env)
|
||||
|
||||
|
|
@ -622,6 +762,59 @@ CPSourceFileRef,&
|
|||
|
||||
CALL timestop(0.0_dp,handle)
|
||||
|
||||
CONTAINS
|
||||
SUBROUTINE execute_job(i)
|
||||
INTEGER :: i
|
||||
|
||||
! change to the new working directory
|
||||
CALL m_chdir(TRIM(farming_env%Job(i)%cwd),ierr)
|
||||
CPPostcondition(ierr==0,cp_failure_level,routineP,error,failure)
|
||||
|
||||
! generate a fresh call to cp2k_run
|
||||
IF (new_rank == 0) THEN
|
||||
|
||||
! generate the output file
|
||||
WRITE(output_file,'(A12,I5.5)') "FARMING_OUT_",i
|
||||
CALL parser_create(my_parser,file_name=TRIM(farming_env%Job(i)%input),error=error)
|
||||
label="&GLOBAL"
|
||||
CALL parser_search_string(my_parser,label,ignore_case=.TRUE.,found=found,error=error)
|
||||
IF (found) THEN
|
||||
CALL create_global_section(g_section,error=error)
|
||||
CALL section_vals_create(g_data,g_section,error=error)
|
||||
CALL cp_unit_set_create(default_units, "OUTPUT",error=error)
|
||||
CALL section_vals_parse(g_data,my_parser,default_units,&
|
||||
error=error)
|
||||
CALL cp_unit_set_release(default_units,error=error)
|
||||
CALL section_vals_val_get(g_data,"PROJECT",&
|
||||
c_val=str, error=error)
|
||||
IF (str.NE."") output_file=TRIM(str)//".out"
|
||||
CALL section_vals_val_get(g_data,"OUTPUT_FILE_NAME",&
|
||||
c_val=str,error=error)
|
||||
IF (str.NE."") output_file=str
|
||||
CALL section_vals_release(g_data,error=error)
|
||||
CALL section_release(g_section,error=error)
|
||||
END IF
|
||||
CALL parser_release(my_parser,error=error)
|
||||
CALL open_file(file_name=TRIM(output_file),&
|
||||
file_action="WRITE",&
|
||||
file_status="UNKNOWN",&
|
||||
file_position="APPEND",&
|
||||
unit_number=new_output_unit)
|
||||
ELSE
|
||||
! this should never be used by cp2k_run, but e.g. still happens, incorrectly,
|
||||
! on eror, writes now to fort.999 so that error messages can be recovered and fixed
|
||||
new_output_unit=999
|
||||
ENDIF
|
||||
|
||||
run_OK=cp2k_run(TRIM(farming_env%Job(i)%input),new_output_unit,new_group)
|
||||
|
||||
IF (new_rank == 0) CALL close_file(unit_number=new_output_unit)
|
||||
|
||||
! change to the original working directory
|
||||
CALL m_chdir(TRIM(farming_env%cwd),ierr)
|
||||
CPPostcondition(ierr==0,cp_failure_level,routineP,error,failure)
|
||||
|
||||
END SUBROUTINE execute_job
|
||||
END SUBROUTINE farming_run
|
||||
|
||||
!!****f* cp2k_runs/write_cp2k_html_manual *
|
||||
|
|
@ -744,7 +937,7 @@ WRITE(unit_nr,*) ' <!-- END CODE --></TD><TD> '
|
|||
WRITE(unit_nr,*) "<HTML><BODY><HEAD><TITLE>The cp2k literature list</TITLE>"
|
||||
WRITE(unit_nr,*) "<H1>CP2K references</H1>"
|
||||
CALL print_all_references(sorted=.FALSE.,cited_only=.FALSE., &
|
||||
format=print_format_html,unit=unit_nr)
|
||||
FORMAT=print_format_html,unit=unit_nr)
|
||||
WRITE(unit_nr,*) '<BR><hr>Back to the <A HREF="http://cp2k.berlios.de/">CP2K homepage</A>'
|
||||
WRITE(unit_nr,*) "</BODY></HTML>"
|
||||
CALL close_file(unit_nr)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ MODULE farming_methods
|
|||
USE cp_output_handling, ONLY: cp_print_key_finished_output,&
|
||||
cp_print_key_unit_nr
|
||||
USE cp_para_types, ONLY: cp_para_env_type
|
||||
USE farming_types, ONLY: farming_env_type
|
||||
USE farming_types, ONLY: farming_env_type, &
|
||||
init_job_type, job_pending, job_running, job_finished
|
||||
USE input_section_types, ONLY: section_vals_get,&
|
||||
section_vals_get_subs_vals,&
|
||||
section_vals_type,&
|
||||
|
|
@ -18,12 +19,80 @@ MODULE farming_methods
|
|||
|
||||
IMPLICIT NONE
|
||||
PRIVATE
|
||||
PUBLIC :: farming_parse_input
|
||||
PUBLIC :: farming_parse_input, get_next_job
|
||||
|
||||
! must be negative in order to avoid confusion with job numbers
|
||||
INTEGER, PARAMETER, PUBLIC :: do_nothing = -1, &
|
||||
do_wait = -2, &
|
||||
do_deadlock = -3
|
||||
|
||||
CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'farming_methods'
|
||||
|
||||
CONTAINS
|
||||
|
||||
SUBROUTINE get_next_job(farming_env,start,end,current,todo)
|
||||
TYPE(farming_env_type), POINTER :: farming_env
|
||||
INTEGER, INTENT(IN) :: start, end
|
||||
INTEGER, INTENT(INOUT) :: current
|
||||
INTEGER, INTENT(OUT) :: todo
|
||||
|
||||
INTEGER :: itry,idep,ndep,icheck
|
||||
LOGICAL :: dep_ok
|
||||
|
||||
IF (farming_env%cycle) THEN
|
||||
IF (current<start) THEN
|
||||
current=start
|
||||
ELSE
|
||||
current=current+1
|
||||
ENDIF
|
||||
IF (current>end) THEN
|
||||
todo=do_nothing
|
||||
ELSE
|
||||
todo=MODULO(current-1,farming_env%njobs)+1
|
||||
ENDIF
|
||||
ELSE
|
||||
! find a pending job
|
||||
itry=start
|
||||
todo=do_nothing
|
||||
DO itry=start,end
|
||||
IF (farming_env%job(itry)%status==job_pending) THEN
|
||||
|
||||
! see if all dependencies are OK
|
||||
ndep=SIZE(farming_env%job(itry)%dependencies)
|
||||
dep_ok=.TRUE.
|
||||
dep: DO idep=1,ndep
|
||||
DO icheck=start,end
|
||||
IF (farming_env%job(icheck)%status.NE.job_finished) THEN
|
||||
IF (farming_env%job(icheck)%id==farming_env%job(itry)%dependencies(idep)) THEN
|
||||
dep_ok=.FALSE.
|
||||
EXIT dep
|
||||
ENDIF
|
||||
ENDIF
|
||||
ENDDO
|
||||
ENDDO dep
|
||||
|
||||
! if there are pending jobs, the slave can not be told to stop
|
||||
! at least wait if there are unresolved dependencies
|
||||
IF (dep_OK) THEn
|
||||
todo=itry
|
||||
EXIT
|
||||
ELSE
|
||||
todo=do_wait
|
||||
ENDIF
|
||||
ENDIF
|
||||
ENDDO
|
||||
! If we have to wait, but there are no running jobs we are deadlocked
|
||||
! which we signal
|
||||
IF (todo==do_wait) THEN
|
||||
dep_OK=.FALSE.
|
||||
DO itry=start,end
|
||||
IF (farming_env%job(icheck)%status.EQ.job_running) dep_OK=.TRUE.
|
||||
ENDDO
|
||||
IF (.NOT. dep_OK) todo=do_deadlock
|
||||
ENDIF
|
||||
ENDIF
|
||||
END SUBROUTINE get_next_job
|
||||
|
||||
SUBROUTINE farming_parse_input(farming_env,root_section,para_env,error)
|
||||
TYPE(farming_env_type), POINTER :: farming_env
|
||||
TYPE(section_vals_type), POINTER :: root_section
|
||||
|
|
@ -35,11 +104,13 @@ CONTAINS
|
|||
|
||||
CHARACTER(LEN=3) :: text
|
||||
INTEGER :: i, iunit, n_rep_val, &
|
||||
output_unit, stat
|
||||
output_unit, stat, num_slaves
|
||||
INTEGER, DIMENSION(:), POINTER :: i_vals
|
||||
LOGICAL :: failure, found
|
||||
TYPE(cp_logger_type), POINTER :: logger
|
||||
TYPE(section_vals_type), POINTER :: farming_section, jobs_section
|
||||
INTEGER, POINTER, DIMENSION(:) :: dependencies
|
||||
LOGICAL :: has_dep
|
||||
|
||||
failure=.FALSE.
|
||||
|
||||
|
|
@ -80,34 +151,81 @@ CONTAINS
|
|||
END IF
|
||||
END IF
|
||||
|
||||
CALL section_vals_val_get(farming_section,"restart",&
|
||||
CALL section_vals_val_get(farming_section,"RESTART",&
|
||||
l_val=farming_env%restart,error=error)
|
||||
CALL section_vals_val_get(farming_section,"max_steps",&
|
||||
CALL section_vals_val_get(farming_section,"MAX_JOBS_PER_GROUP",&
|
||||
i_val=farming_env%max_steps,error=error)
|
||||
CALL section_vals_val_get(farming_section,"cycle",&
|
||||
CALL section_vals_val_get(farming_section,"CYCLE",&
|
||||
l_val=farming_env%cycle,error=error)
|
||||
CALL section_vals_val_get(farming_section,"WAIT_TIME",&
|
||||
r_val=farming_env%wait_time,error=error)
|
||||
|
||||
CALL section_vals_val_get(farming_section,"MASTER_SLAVE",&
|
||||
l_val=farming_env%master_slave,error=error)
|
||||
|
||||
|
||||
jobs_section => section_vals_get_subs_vals(farming_section,"JOB",error=error)
|
||||
CALL section_vals_get(jobs_section,n_repetition=farming_env % njobs,error=error)
|
||||
|
||||
ALLOCATE(farming_env%Job_cwd(farming_env % njobs),STAT=stat)
|
||||
CPPostcondition(stat==0,cp_failure_level,routineP,error,failure)
|
||||
ALLOCATE(farming_env%Job_input(farming_env % njobs),STAT=stat)
|
||||
ALLOCATE(farming_env%Job(farming_env % njobs),STAT=stat)
|
||||
CPPostcondition(stat==0,cp_failure_level,routineP,error,failure)
|
||||
CALL init_job_type(farming_env%job)
|
||||
|
||||
IF (.NOT. failure) THEN
|
||||
has_dep=.FALSE.
|
||||
DO i=1,farming_env%njobs
|
||||
CALL section_vals_val_get(jobs_section,i_rep_section=i,&
|
||||
keyword_name="directory",c_val=farming_env%Job_cwd(i),error=error)
|
||||
keyword_name="DIRECTORY",c_val=farming_env%Job(i)%cwd,error=error)
|
||||
CALL section_vals_val_get(jobs_section,i_rep_section=i,&
|
||||
keyword_name="input_file_name",c_val=farming_env%Job_input(i),error=error)
|
||||
keyword_name="INPUT_FILE_NAME",c_val=farming_env%Job(i)%input,error=error)
|
||||
|
||||
! if job id is not specified the job id is the index
|
||||
CALL section_vals_val_get(jobs_section,i_rep_section=i,&
|
||||
keyword_name="JOB_ID",n_rep_val=n_rep_val,error=error)
|
||||
IF (n_rep_val==0) THEN
|
||||
farming_env%Job(i)%id=i
|
||||
ELSE
|
||||
CALL section_vals_val_get(jobs_section,i_rep_section=i,&
|
||||
keyword_name="JOB_ID",i_val=farming_env%Job(i)%id,error=error)
|
||||
ENDIF
|
||||
|
||||
! get dependencies
|
||||
CALL section_vals_val_get(jobs_section,i_rep_section=i,&
|
||||
keyword_name="DEPENDENCIES",n_rep_val=n_rep_val,error=error)
|
||||
IF (n_rep_val==0) THEN
|
||||
ALLOCATE(farming_env%Job(i)%dependencies(0))
|
||||
ELSE
|
||||
CALL section_vals_val_get(jobs_section,i_rep_section=i,&
|
||||
keyword_name="DEPENDENCIES",i_vals=dependencies,error=error)
|
||||
ALLOCATE(farming_env%Job(i)%dependencies(SIZE(dependencies,1)))
|
||||
farming_env%Job(i)%dependencies=dependencies
|
||||
IF (SIZE(dependencies,1).NE.0) has_dep=.TRUE.
|
||||
ENDIF
|
||||
END DO
|
||||
END IF
|
||||
|
||||
IF (has_dep) THEN
|
||||
CPPostcondition(farming_env%master_slave,cp_failure_level,routineP,error,failure)
|
||||
CPPostcondition(.NOT.farming_env%cycle,cp_failure_level,routineP,error,failure)
|
||||
ENDIF
|
||||
|
||||
IF (.NOT. failure) THEN
|
||||
|
||||
logger => cp_error_get_logger(error)
|
||||
output_unit=cp_print_key_unit_nr(logger,root_section,"GLOBAL%PROGRAM_RUN_INFO",&
|
||||
extension=".log",error=error)
|
||||
|
||||
! master slave not supported
|
||||
IF (para_env%num_pe==1) THEN
|
||||
farming_env%master_slave=.FALSE.
|
||||
WRITE(output_unit,FMT="(T2,A)") "FARMING| Master-slave setup not support for serial runs"
|
||||
ENDIF
|
||||
IF (farming_env%master_slave) THEN
|
||||
num_slaves=para_env%num_pe-1
|
||||
ELSE
|
||||
num_slaves=para_env%num_pe
|
||||
ENDIF
|
||||
|
||||
IF (output_unit > 0) THEN
|
||||
WRITE(output_unit,FMT="(T2,A,T71,I10)") "FARMING| Number of jobs found",farming_env%njobs
|
||||
IF (farming_env%ngroup_wish_set) THEN
|
||||
|
|
@ -119,10 +237,10 @@ CONTAINS
|
|||
WRITE(output_unit,FMT='(I4)',ADVANCE="NO") farming_env%group_partition(i)
|
||||
END DO
|
||||
WRITE(output_unit,*)
|
||||
IF (SUM(farming_env%group_partition).NE.para_env%num_pe) THEN
|
||||
IF (SUM(farming_env%group_partition).NE.num_slaves) THEN
|
||||
WRITE(output_unit,FMT="(T2,A,T61,I10,T71,I10)") &
|
||||
"FARMING| WARNING : partition CPUs not equal actual number ", &
|
||||
para_env%num_pe, SUM(farming_env%group_partition)
|
||||
"FARMING| WARNING : group partition CPUs not equal to the available number (ignoring master) ", &
|
||||
num_slaves, SUM(farming_env%group_partition)
|
||||
WRITE(output_unit,FMT="(T2,A)") "FARMING| partition data ignored" ! any better idea ??
|
||||
DEALLOCATE(farming_env%group_partition)
|
||||
ENDIF
|
||||
|
|
|
|||
|
|
@ -4,13 +4,23 @@
|
|||
!-----------------------------------------------------------------------------!
|
||||
|
||||
MODULE farming_types
|
||||
USE kinds, ONLY: default_path_length
|
||||
USE kinds, ONLY: default_path_length,dp
|
||||
#include "cp_common_uses.h"
|
||||
|
||||
IMPLICIT NONE
|
||||
PRIVATE
|
||||
|
||||
PUBLIC :: farming_env_type, deallocate_farming_env, init_farming_env
|
||||
PUBLIC :: farming_env_type, deallocate_farming_env, init_farming_env, init_job_type, job_type
|
||||
|
||||
INTEGER, PUBLIC, PARAMETER :: job_pending=1,job_running=2,job_finished=3
|
||||
|
||||
TYPE job_type
|
||||
CHARACTER(LEN=default_path_length) :: cwd ! the directory to go to
|
||||
CHARACTER(LEN=default_path_length) :: input ! the input file to use
|
||||
INTEGER :: ID ! the ID of this job
|
||||
INTEGER, POINTER, DIMENSION(:) :: dependencies ! the dependencies of this job
|
||||
INTEGER :: status ! pending,running,finished
|
||||
END TYPE job_type
|
||||
|
||||
TYPE farming_env_type
|
||||
INTEGER :: group_size_wish
|
||||
|
|
@ -19,15 +29,15 @@ MODULE farming_types
|
|||
LOGICAL :: ngroup_wish_set
|
||||
LOGICAL :: restart
|
||||
LOGICAL :: CYCLE
|
||||
LOGICAL :: master_slave
|
||||
INTEGER, DIMENSION(:), POINTER :: group_partition ! user preference for partitioning the cpus
|
||||
CHARACTER(LEN=default_path_length) :: cwd ! directory we started from
|
||||
INTEGER :: Njobs ! how many jobs to run
|
||||
INTEGER :: restart_n ! where to start
|
||||
INTEGER :: max_steps ! max number of steps,
|
||||
! results in max_steps*Ngroup jobs being run
|
||||
CHARACTER(LEN=default_path_length), DIMENSION(:), POINTER :: Job_cwd ! list of directories to go to
|
||||
CHARACTER(LEN=default_path_length), DIMENSION(:), POINTER :: Job_input ! name of the input file to use
|
||||
INTEGER, DIMENSION(:), POINTER :: Job_group ! number of the target group
|
||||
TYPE(job_type), DIMENSION(:), POINTER :: job ! a list of jobs
|
||||
REAL(KIND=dp) :: wait_time
|
||||
END TYPE farming_env_type
|
||||
|
||||
CONTAINS
|
||||
|
|
@ -64,17 +74,66 @@ SUBROUTINE init_farming_env(farming_env)
|
|||
farming_env%restart = .FALSE.
|
||||
farming_env%restart_n = 1
|
||||
farming_env%cycle = .FALSE.
|
||||
farming_env%master_slave = .FALSE.
|
||||
NULLIFY(farming_env%group_partition)
|
||||
farming_env%cwd = "."
|
||||
farming_env%Njobs = 0
|
||||
! so that maxsteps*ngroup is not overflowing
|
||||
farming_env%max_steps = HUGE(0)/32768
|
||||
NULLIFY(farming_env%Job_cwd)
|
||||
NULLIFY(farming_env%Job_input)
|
||||
NULLIFY(farming_env%Job_group)
|
||||
NULLIFY(farming_env%Job)
|
||||
ENDIF
|
||||
END SUBROUTINE
|
||||
|
||||
!!****f* farming_types/init_job_type *
|
||||
!!
|
||||
!! NAME
|
||||
!! init_job_type
|
||||
!!
|
||||
!! FUNCTION
|
||||
!! provide a default initialization
|
||||
!!
|
||||
!! NOTES
|
||||
!!
|
||||
!! INPUTS
|
||||
!!
|
||||
!! MODIFICATION HISTORY
|
||||
!! 09.2007 created [Joost VandeVondele ]
|
||||
!!
|
||||
!!*** **********************************************************************
|
||||
ELEMENTAL SUBROUTINE init_job_type(job)
|
||||
TYPE(job_type), INTENT(OUT) :: job
|
||||
|
||||
job%cwd=""
|
||||
job%input=""
|
||||
job%ID=-1
|
||||
job%status=job_pending
|
||||
NULLIFY(job%dependencies)
|
||||
|
||||
END SUBROUTINE init_job_type
|
||||
|
||||
!!****f* farming_types/deallocate_job_type *
|
||||
!!
|
||||
!! NAME
|
||||
!! deallocate_job_type
|
||||
!!
|
||||
!! FUNCTION
|
||||
!! deallocates all memory associated with this job
|
||||
!!
|
||||
!! NOTES
|
||||
!!
|
||||
!! INPUTS
|
||||
!!
|
||||
!! MODIFICATION HISTORY
|
||||
!! 09.2007 created [Joost VandeVondele ]
|
||||
!!
|
||||
!!*** **********************************************************************
|
||||
SUBROUTINE deallocate_job_type(job)
|
||||
TYPE(job_type) :: job
|
||||
|
||||
IF (ASSOCIATED(job%dependencies)) DEALLOCATE(job%dependencies)
|
||||
|
||||
END SUBROUTINE deallocate_job_type
|
||||
|
||||
!!****f* farming_types/deallocate_farming_env *
|
||||
!!
|
||||
!! NAME
|
||||
|
|
@ -97,17 +156,21 @@ END SUBROUTINE
|
|||
!! 03.2004 created [Joost VandeVondele]
|
||||
!!
|
||||
!!*** **********************************************************************
|
||||
|
||||
SUBROUTINE deallocate_farming_env(farming_env)
|
||||
TYPE(farming_env_type), POINTER :: farming_env
|
||||
|
||||
IF (ASSOCIATED(farming_env)) THEN
|
||||
IF (ASSOCIATED(farming_env%Job_cwd)) DEALLOCATE(farming_env%Job_cwd)
|
||||
IF (ASSOCIATED(farming_env%Job_input)) DEALLOCATE(farming_env%Job_input)
|
||||
IF (ASSOCIATED(farming_env%Job_group)) DEALLOCATE(farming_env%Job_group)
|
||||
IF (ASSOCIATED(farming_env%group_partition)) DEALLOCATE(farming_env%group_partition)
|
||||
DEALLOCATE(farming_env) ! and the type itself
|
||||
ENDIF
|
||||
INTEGER :: I
|
||||
|
||||
IF (ASSOCIATED(farming_env)) THEN
|
||||
IF (ASSOCIATED(farming_env%job)) THEN
|
||||
DO I=1,SIZE(farming_env%job,1)
|
||||
CALL deallocate_job_type(farming_env%job(I))
|
||||
ENDDO
|
||||
DEALLOCATE(farming_env%job)
|
||||
ENDIF
|
||||
IF (ASSOCIATED(farming_env%group_partition)) DEALLOCATE(farming_env%group_partition)
|
||||
DEALLOCATE(farming_env) ! and the type itself
|
||||
ENDIF
|
||||
END SUBROUTINE deallocate_farming_env
|
||||
END MODULE farming_types
|
||||
!!*****
|
||||
|
|
|
|||
|
|
@ -1269,18 +1269,27 @@ SUBROUTINE create_farming_section(section,error)
|
|||
repeats=.FALSE., required=.TRUE., error=error)
|
||||
NULLIFY(keyword)
|
||||
|
||||
CALL keyword_create(keyword, name="GROUP_SIZE",&
|
||||
description="Gives the wanted size of a working group.",&
|
||||
usage="group_size 2", default_i_val=8, error=error)
|
||||
CALL keyword_create(keyword, name="MASTER_SLAVE",&
|
||||
description="If a master-slave setup should be employed, in which one process is used to distribute the tasks. "//&
|
||||
"This is most useful to load-balance if not all jobs have the same length, "//&
|
||||
"and a lot of CPUs/groups are availabe.",&
|
||||
usage="MASTER_SLAVE",default_l_val=.FALSE.,lone_keyword_l_val=.TRUE.,error=error)
|
||||
CALL section_add_keyword(section,keyword,error=error)
|
||||
CALL keyword_release(keyword,error=error)
|
||||
|
||||
CALL keyword_create(keyword, name="NGROUPS",variants=(/"NGROUP"/),&
|
||||
description="Gives the wanted number of groups.",&
|
||||
description="Gives the preferred number of working groups.",&
|
||||
usage="ngroups 4", type_of_var=integer_t, error=error)
|
||||
CALL section_add_keyword(section,keyword,error=error)
|
||||
CALL keyword_release(keyword,error=error)
|
||||
|
||||
CALL keyword_create(keyword, name="GROUP_SIZE",&
|
||||
description="Gives the preferred size of a working group, "//&
|
||||
"groups will always be equal or larger than this size.",&
|
||||
usage="group_size 2", default_i_val=8, error=error)
|
||||
CALL section_add_keyword(section,keyword,error=error)
|
||||
CALL keyword_release(keyword,error=error)
|
||||
|
||||
CALL keyword_create(keyword, name="GROUP_PARTITION",&
|
||||
description="gives the exact number of processors for each group.",&
|
||||
usage="group_partition 2 2 4 2 4 ", type_of_var=integer_t, n_var=-1, error=error)
|
||||
|
|
@ -1288,44 +1297,75 @@ SUBROUTINE create_farming_section(section,error)
|
|||
CALL keyword_release(keyword,error=error)
|
||||
|
||||
CALL keyword_create(keyword, name="RESTART",&
|
||||
description="if you are restarting a farming job (and should pick up where the previous left off)",&
|
||||
description="restart a farming job (and should pick up where the previous left off)",&
|
||||
usage="RESTART",default_l_val=.FALSE.,lone_keyword_l_val=.TRUE.,&
|
||||
error=error)
|
||||
CALL section_add_keyword(section,keyword,error=error)
|
||||
CALL keyword_release(keyword,error=error)
|
||||
|
||||
CALL keyword_create(keyword, name="MAX_STEP",variants=(/"max_steps"/),&
|
||||
description="maximum number of steps done by a processor",&
|
||||
CALL keyword_create(keyword, name="MAX_JOBS_PER_GROUP",&
|
||||
variants=(/"MAX_JOBS"/),&
|
||||
description="maximum number of jobs executed per group",&
|
||||
usage="max_step 4", default_i_val=HUGE(0)/32768, error=error)
|
||||
CALL section_add_keyword(section,keyword,error=error)
|
||||
CALL keyword_release(keyword,error=error)
|
||||
|
||||
CALL keyword_create(keyword, name="CYCLE",&
|
||||
description="If farming should cycle between the inputs" ,&
|
||||
description="If farming should process all jobs in a cyclic way, stopping only if MAX_JOBS_PER_GROUP is exceeded." ,&
|
||||
usage="CYCLE",default_l_val=.FALSE.,lone_keyword_l_val=.TRUE.,&
|
||||
error=error)
|
||||
CALL section_add_keyword(section,keyword,error=error)
|
||||
CALL keyword_release(keyword,error=error)
|
||||
|
||||
CALL keyword_create(keyword, name="WAIT_TIME",&
|
||||
description="Time to wait [s] for a new task if no task is currently available, make this zero if no clock is available",&
|
||||
usage="WAIT_TIME 0.1",default_r_val=0.5_dp, error=error)
|
||||
CALL section_add_keyword(section,keyword,error=error)
|
||||
CALL keyword_release(keyword,error=error)
|
||||
|
||||
NULLIFY(sub_section)
|
||||
CALL section_create(sub_section,name="job",&
|
||||
CALL section_create(sub_section,name="JOB",&
|
||||
description="description of the jobs to be executed",&
|
||||
repeats=.TRUE., required=.TRUE., error=error)
|
||||
|
||||
CALL keyword_create(keyword,name="directory",&
|
||||
CALL keyword_create(keyword,name="DIRECTORY",&
|
||||
description="the directory in which the job should be executed",&
|
||||
usage="directory /my/path",&
|
||||
usage="DIRECTORY /my/path",&
|
||||
required=.TRUE.,default_lc_val=".",error=error)
|
||||
CALL section_add_keyword(sub_section,keyword,error=error)
|
||||
CALL keyword_release(keyword,error=error)
|
||||
|
||||
CALL keyword_create(keyword,name="input_file_name",&
|
||||
CALL keyword_create(keyword,name="INPUT_FILE_NAME",&
|
||||
description="the filename of the input file",&
|
||||
usage="input_file my_input.inp",&
|
||||
required=.TRUE.,default_lc_val="input.inp",error=error)
|
||||
CALL section_add_keyword(sub_section,keyword,error=error)
|
||||
CALL keyword_release(keyword,error=error)
|
||||
|
||||
CALL keyword_create(keyword,name="JOB_ID",&
|
||||
description="An ID used to indentify a job in DEPENDENCIES. "//&
|
||||
"JOB_IDs do not need to be unique, dependencies will be on all jobs with a given ID. "//&
|
||||
"If no JOB_ID is given, the index of the &JOB section in the input file will be used. ",&
|
||||
usage="JOB_ID 13", type_of_var=integer_t, error=error)
|
||||
CALL section_add_keyword(sub_section,keyword,error=error)
|
||||
CALL keyword_release(keyword,error=error)
|
||||
|
||||
CALL keyword_create(keyword,name="DEPENDENCIES",&
|
||||
description="specifies a list of JOB_IDs on which the current job depends. "//&
|
||||
"The current job will not be executed before all the dependencies have finished. "//&
|
||||
"The keyword requires a MASTER_SLAVE farming run. "//&
|
||||
"Beyond the default case, some special cases might arise: "//&
|
||||
"1) circular dependencies will lead to a deadlock. "//&
|
||||
"2) This keyword is not compatible with CYCLE. "//&
|
||||
"3) MAX_JOBS_PER_GROUP is ignored (though only a total of MAX_JOBS_PER_GROUP*NGROUPS jobs will be executed) "//&
|
||||
"4) dependencies on jobs that will not be executed (due to RESTART or MAX_JOBS_PER_GROUP) are ignored. "//&
|
||||
"Additionally, note that, on some file systems, "//&
|
||||
" output (restart) files might not be immediately available on all compute nodes,"//&
|
||||
"potentially resulting in unexpected failures.", &
|
||||
usage="DEPENDENCIES 13 1 7",type_of_var=integer_t, n_var=-1, error=error)
|
||||
CALL section_add_keyword(sub_section,keyword,error=error)
|
||||
CALL keyword_release(keyword,error=error)
|
||||
|
||||
CALL section_add_subsection(section, sub_section, error=error)
|
||||
CALL section_release(sub_section,error=error)
|
||||
|
||||
|
|
|
|||
|
|
@ -54,12 +54,19 @@ MODULE message_passing
|
|||
|
||||
#ifdef __parallel
|
||||
LOGICAL, PARAMETER :: cp2k_is_parallel=.TRUE.
|
||||
INTEGER, PARAMETER, PUBLIC :: mp_any_tag=MPI_ANY_TAG
|
||||
INTEGER, PARAMETER, PUBLIC :: mp_any_source=MPI_ANY_SOURCE
|
||||
#else
|
||||
LOGICAL, PARAMETER :: cp2k_is_parallel=.FALSE.
|
||||
INTEGER, PARAMETER, PUBLIC :: mp_any_tag=-1
|
||||
INTEGER, PARAMETER, PUBLIC :: mp_any_source=-2
|
||||
#endif
|
||||
|
||||
|
||||
CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'message_passing'
|
||||
|
||||
! parameters that might be needed
|
||||
|
||||
! init and error
|
||||
PUBLIC :: mp_world_init, mp_world_finalize
|
||||
PUBLIC :: mp_stop, mp_abort
|
||||
|
|
@ -84,6 +91,7 @@ MODULE message_passing
|
|||
PUBLIC :: mp_sum_scatter, mp_shift, mp_isendrecv, mp_wait, mp_waitall
|
||||
PUBLIC :: mp_gatherv
|
||||
PUBLIC :: mp_sum_i8
|
||||
PUBLIC :: mp_send, mp_recv
|
||||
|
||||
! currently not used
|
||||
! PUBLIC :: mp_group
|
||||
|
|
@ -161,6 +169,14 @@ MODULE message_passing
|
|||
mp_alltoall_i11v, mp_alltoall_r11v
|
||||
END INTERFACE
|
||||
|
||||
INTERFACE mp_send
|
||||
MODULE PROCEDURE mp_send_i,mp_send_iv
|
||||
END INTERFACE
|
||||
|
||||
INTERFACE mp_recv
|
||||
MODULE PROCEDURE mp_recv_i,mp_recv_iv
|
||||
END INTERFACE
|
||||
|
||||
INTERFACE mp_sendrecv
|
||||
MODULE PROCEDURE mp_sendrecv_rm3, mp_sendrecv_rm2, mp_sendrecv_rv
|
||||
END INTERFACE
|
||||
|
|
@ -185,7 +201,7 @@ MODULE message_passing
|
|||
REAL (KIND=dp) :: time
|
||||
END TYPE mp_perf_type
|
||||
|
||||
INTEGER, PARAMETER :: MAX_PERF = 12
|
||||
INTEGER, PARAMETER :: MAX_PERF = 14
|
||||
|
||||
TYPE mp_perf_env_type
|
||||
!private
|
||||
|
|
@ -207,7 +223,8 @@ MODULE message_passing
|
|||
(/"MP_Group ", "MP_Bcast ", "MP_Allreduce ", &
|
||||
"MP_Gather ", "MP_Sync ", "MP_Alltoall ", &
|
||||
"MP_SendRecv ", "MP_ISendRecv ", "MP_Wait ", &
|
||||
"MP_comm_split ", "MP_ISend ", "MP_IRecv "/)
|
||||
"MP_comm_split ", "MP_ISend ", "MP_IRecv ", &
|
||||
"MP_Send ", "MP_Recv "/)
|
||||
REAL (KIND=dp) :: t_start, t_end
|
||||
|
||||
! we make some assumptions on the length of INTEGERS, REALS and LOGICALS
|
||||
|
|
@ -1456,6 +1473,123 @@ END SUBROUTINE mp_alltoall_i
|
|||
|
||||
!******************************************************************************
|
||||
|
||||
! ..mp_send
|
||||
SUBROUTINE mp_send_iv(msg,dest,tag,gid)
|
||||
INTEGER :: msg( : ), dest, gid,tag
|
||||
|
||||
INTEGER :: ierr, msglen
|
||||
INTEGER :: handle
|
||||
CHARACTER(len=*), PARAMETER :: routineN = 'mp_send_iv', &
|
||||
routineP = moduleN//':'//routineN
|
||||
#if defined(__mp_timeset__)
|
||||
CALL timeset(routineN,handle)
|
||||
#endif
|
||||
|
||||
ierr = 0
|
||||
msglen = SIZE(msg)
|
||||
#if defined(__parallel)
|
||||
t_start = m_walltime ( )
|
||||
CALL mpi_send(msg,msglen,MPI_INTEGER,dest,tag,gid,ierr)
|
||||
IF ( ierr /= 0 ) CALL mp_stop( ierr, "mpi_send @ mp_send_iv" )
|
||||
t_end = m_walltime ( )
|
||||
CALL add_perf(perf_id=13,count=1,time=t_end-t_start,msg_size=msglen*intlen)
|
||||
#endif
|
||||
#if defined(__mp_timeset__)
|
||||
CALL timestop(handle)
|
||||
#endif
|
||||
END SUBROUTINE mp_send_iv
|
||||
|
||||
SUBROUTINE mp_send_i(msg,dest,tag,gid)
|
||||
INTEGER :: msg, dest, gid,tag
|
||||
|
||||
INTEGER :: ierr, msglen
|
||||
INTEGER :: handle
|
||||
CHARACTER(len=*), PARAMETER :: routineN = 'mp_send_iv', &
|
||||
routineP = moduleN//':'//routineN
|
||||
#if defined(__mp_timeset__)
|
||||
CALL timeset(routineN,handle)
|
||||
#endif
|
||||
|
||||
ierr = 0
|
||||
msglen = 1
|
||||
#if defined(__parallel)
|
||||
t_start = m_walltime ( )
|
||||
CALL mpi_send(msg,msglen,MPI_INTEGER,dest,tag,gid,ierr)
|
||||
IF ( ierr /= 0 ) CALL mp_stop( ierr, "mpi_send @ mp_send_iv" )
|
||||
t_end = m_walltime ( )
|
||||
CALL add_perf(perf_id=13,count=1,time=t_end-t_start,msg_size=msglen*intlen)
|
||||
#endif
|
||||
#if defined(__mp_timeset__)
|
||||
CALL timestop(handle)
|
||||
#endif
|
||||
END SUBROUTINE mp_send_i
|
||||
|
||||
|
||||
! ..mp_recv
|
||||
SUBROUTINE mp_recv_iv(msg,source,tag,gid)
|
||||
INTEGER, INTENT(INOUT) :: msg( : ), source, tag
|
||||
INTEGER, INTENT(IN) :: gid
|
||||
|
||||
INTEGER :: ierr, msglen
|
||||
INTEGER :: handle
|
||||
INTEGER, DIMENSION(:), ALLOCATABLE :: status
|
||||
CHARACTER(len=*), PARAMETER :: routineN = 'mp_recv_iv', &
|
||||
routineP = moduleN//':'//routineN
|
||||
#if defined(__mp_timeset__)
|
||||
CALL timeset(routineN,handle)
|
||||
#endif
|
||||
|
||||
ierr = 0
|
||||
msglen = SIZE(msg)
|
||||
#if defined(__parallel)
|
||||
ALLOCATE(status(MPI_STATUS_SIZE))
|
||||
t_start = m_walltime ( )
|
||||
CALL mpi_recv(msg,msglen,MPI_INTEGER,source,tag,gid,status,ierr)
|
||||
IF ( ierr /= 0 ) CALL mp_stop( ierr, "mpi_recv @ mp_recv_iv" )
|
||||
t_end = m_walltime ( )
|
||||
CALL add_perf(perf_id=14,count=1,time=t_end-t_start,msg_size=msglen*intlen)
|
||||
source = status(MPI_SOURCE)
|
||||
tag = status(MPI_TAG)
|
||||
DEALLOCATE(status)
|
||||
#endif
|
||||
#if defined(__mp_timeset__)
|
||||
CALL timestop(handle)
|
||||
#endif
|
||||
END SUBROUTINE mp_recv_iv
|
||||
|
||||
SUBROUTINE mp_recv_i(msg,source,tag,gid)
|
||||
INTEGER, INTENT(INOUT) :: msg, source, tag
|
||||
INTEGER, INTENT(IN) :: gid
|
||||
|
||||
INTEGER :: ierr, msglen
|
||||
INTEGER :: handle
|
||||
INTEGER, DIMENSION(:), ALLOCATABLE :: status
|
||||
CHARACTER(len=*), PARAMETER :: routineN = 'mp_recv_iv', &
|
||||
routineP = moduleN//':'//routineN
|
||||
#if defined(__mp_timeset__)
|
||||
CALL timeset(routineN,handle)
|
||||
#endif
|
||||
|
||||
ierr = 0
|
||||
msglen = 1
|
||||
#if defined(__parallel)
|
||||
ALLOCATE(status(MPI_STATUS_SIZE))
|
||||
t_start = m_walltime ( )
|
||||
CALL mpi_recv(msg,msglen,MPI_INTEGER,source,tag,gid,status,ierr)
|
||||
IF ( ierr /= 0 ) CALL mp_stop( ierr, "mpi_recv @ mp_recv_iv" )
|
||||
t_end = m_walltime ( )
|
||||
CALL add_perf(perf_id=14,count=1,time=t_end-t_start,msg_size=msglen*intlen)
|
||||
source = status(MPI_SOURCE)
|
||||
tag = status(MPI_TAG)
|
||||
DEALLOCATE(status)
|
||||
#endif
|
||||
#if defined(__mp_timeset__)
|
||||
CALL timestop(handle)
|
||||
#endif
|
||||
END SUBROUTINE mp_recv_i
|
||||
|
||||
|
||||
|
||||
!..mp_bcast
|
||||
SUBROUTINE mp_bcast_i1(msg,source,gid)
|
||||
INTEGER :: msg, source, gid
|
||||
|
|
|
|||
13
tests/FARMING/regtest-1/TEST_FILES
Normal file
13
tests/FARMING/regtest-1/TEST_FILES
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# runs are executed in the same order as in this file
|
||||
# the second field tells which test should be run in order to compare with the last available output
|
||||
# e.g. 0 means do not compare anything, running is enough
|
||||
# 1 compares the last total energy in the file
|
||||
# for details see cp2k/tools/do_regtest
|
||||
farming-1.inp 0
|
||||
farming-2.inp 0
|
||||
farming-3.inp 0
|
||||
farming-4.inp 0
|
||||
farming-5.inp 0
|
||||
farming-6.inp 0
|
||||
farming-7.inp 0
|
||||
farming-8.inp 0
|
||||
0
tests/FARMING/regtest-1/TEST_FILES_RESET
Normal file
0
tests/FARMING/regtest-1/TEST_FILES_RESET
Normal file
45
tests/FARMING/regtest-1/farming-1.inp
Normal file
45
tests/FARMING/regtest-1/farming-1.inp
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
&GLOBAL
|
||||
PROGRAM FARMING
|
||||
RUN_TYPE NONE
|
||||
&END GLOBAL
|
||||
|
||||
&FARMING
|
||||
NGROUP 1
|
||||
&JOB
|
||||
DIRECTORY dir-1
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-2
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-3
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-4
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-5
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-6
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-7
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-8
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-9
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&END FARMING
|
||||
|
||||
45
tests/FARMING/regtest-1/farming-2.inp
Normal file
45
tests/FARMING/regtest-1/farming-2.inp
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
&GLOBAL
|
||||
PROGRAM FARMING
|
||||
RUN_TYPE NONE
|
||||
&END GLOBAL
|
||||
|
||||
&FARMING
|
||||
NGROUP 3
|
||||
&JOB
|
||||
DIRECTORY dir-1
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-2
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-3
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-4
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-5
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-6
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-7
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-8
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-9
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&END FARMING
|
||||
|
||||
45
tests/FARMING/regtest-1/farming-3.inp
Normal file
45
tests/FARMING/regtest-1/farming-3.inp
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
&GLOBAL
|
||||
PROGRAM FARMING
|
||||
RUN_TYPE NONE
|
||||
&END GLOBAL
|
||||
|
||||
&FARMING
|
||||
NGROUP 2
|
||||
&JOB
|
||||
DIRECTORY dir-1
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-2
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-3
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-4
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-5
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-6
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-7
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-8
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-9
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&END FARMING
|
||||
|
||||
45
tests/FARMING/regtest-1/farming-4.inp
Normal file
45
tests/FARMING/regtest-1/farming-4.inp
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
&GLOBAL
|
||||
PROGRAM FARMING
|
||||
RUN_TYPE NONE
|
||||
&END GLOBAL
|
||||
|
||||
&FARMING
|
||||
GROUP_SIZE 4
|
||||
&JOB
|
||||
DIRECTORY dir-1
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-2
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-3
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-4
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-5
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-6
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-7
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-8
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-9
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&END FARMING
|
||||
|
||||
47
tests/FARMING/regtest-1/farming-5.inp
Normal file
47
tests/FARMING/regtest-1/farming-5.inp
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
&GLOBAL
|
||||
PROGRAM FARMING
|
||||
RUN_TYPE NONE
|
||||
&END GLOBAL
|
||||
|
||||
&FARMING
|
||||
NGROUP 2
|
||||
CYCLE
|
||||
MAX_JOBS_PER_GROUP 10
|
||||
&JOB
|
||||
DIRECTORY dir-1
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-2
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-3
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-4
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-5
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-6
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-7
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-8
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-9
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&END FARMING
|
||||
|
||||
48
tests/FARMING/regtest-1/farming-6.inp
Normal file
48
tests/FARMING/regtest-1/farming-6.inp
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
&GLOBAL
|
||||
PROGRAM FARMING
|
||||
RUN_TYPE NONE
|
||||
&END GLOBAL
|
||||
|
||||
&FARMING
|
||||
NGROUP 2
|
||||
! CYCLE
|
||||
RESTART
|
||||
! MAX_JOBS_PER_GROUP 10
|
||||
&JOB
|
||||
DIRECTORY dir-1
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-2
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-3
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-4
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-5
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-6
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-7
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-8
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-9
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&END FARMING
|
||||
|
||||
46
tests/FARMING/regtest-1/farming-7.inp
Normal file
46
tests/FARMING/regtest-1/farming-7.inp
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
&GLOBAL
|
||||
PROGRAM FARMING
|
||||
RUN_TYPE NONE
|
||||
&END GLOBAL
|
||||
|
||||
&FARMING
|
||||
NGROUPS 2
|
||||
MASTER_SLAVE
|
||||
&JOB
|
||||
DIRECTORY dir-1
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-2
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-3
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-4
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-5
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-6
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-7
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-8
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-9
|
||||
INPUT_FILE_NAME water.inp
|
||||
&END JOB
|
||||
&END FARMING
|
||||
|
||||
62
tests/FARMING/regtest-1/farming-8.inp
Normal file
62
tests/FARMING/regtest-1/farming-8.inp
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
&GLOBAL
|
||||
PROGRAM FARMING
|
||||
RUN_TYPE NONE
|
||||
&END GLOBAL
|
||||
|
||||
&FARMING
|
||||
NGROUPS 5
|
||||
MASTER_SLAVE
|
||||
&JOB
|
||||
DIRECTORY dir-1
|
||||
INPUT_FILE_NAME water.inp
|
||||
JOB_ID 1
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-2
|
||||
INPUT_FILE_NAME water.inp
|
||||
JOB_ID 1
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-3
|
||||
INPUT_FILE_NAME water.inp
|
||||
JOB_ID 2
|
||||
DEPENDENCIES 1
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-4
|
||||
INPUT_FILE_NAME water.inp
|
||||
JOB_ID 3
|
||||
DEPENDENCIES 1 2
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-5
|
||||
INPUT_FILE_NAME water.inp
|
||||
JOB_ID 4
|
||||
DEPENDENCIES 5
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-6
|
||||
INPUT_FILE_NAME water.inp
|
||||
JOB_ID 5
|
||||
DEPENDENCIES 3
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-7
|
||||
INPUT_FILE_NAME water.inp
|
||||
JOB_ID 5
|
||||
DEPENDENCIES 3
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-8
|
||||
INPUT_FILE_NAME water.inp
|
||||
JOB_ID 5
|
||||
DEPENDENCIES 3
|
||||
&END JOB
|
||||
&JOB
|
||||
DIRECTORY dir-9
|
||||
INPUT_FILE_NAME water.inp
|
||||
JOB_ID 5
|
||||
DEPENDENCIES 3
|
||||
&END JOB
|
||||
&END FARMING
|
||||
|
||||
18
tests/FARMING/regtest-1/tidy
Executable file
18
tests/FARMING/regtest-1/tidy
Executable file
|
|
@ -0,0 +1,18 @@
|
|||
#!/bin/tcsh
|
||||
# Script to clean files after execution of a test
|
||||
echo "This script will clean the directory" $PWD "from scratch files.."
|
||||
echo
|
||||
foreach file (`cvs update -A -P|grep '? '|awk '{print $2}'`)
|
||||
if ( ${file:e} == 'inp' ) then
|
||||
echo "This files could be a new input file you don't want to be deleted.. Do you really want it deleted?"
|
||||
if ( $1 == "-int" ) then
|
||||
echo "You requested to run the cleaning script interactively! Forget about complains!"
|
||||
rm -f $file
|
||||
else
|
||||
rm -i $file
|
||||
endif
|
||||
else
|
||||
rm -f $file
|
||||
endif
|
||||
end
|
||||
rm -f *.bak
|
||||
18
tests/FARMING/water.pot
Normal file
18
tests/FARMING/water.pot
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
BONDS
|
||||
HT HT 0.000 1.5139
|
||||
OT HT 450.000 0.9572
|
||||
|
||||
ANGLES
|
||||
HT OT HT 55.000 104.5200
|
||||
|
||||
DIHEDRALS
|
||||
|
||||
IMPROPER
|
||||
|
||||
NONBONDED
|
||||
HT 0.000000 -0.046000 0.224500
|
||||
OT 0.000000 -0.152100 1.768200
|
||||
|
||||
HBOND CUTHB 0.5
|
||||
|
||||
END
|
||||
3
tests/FARMING/water_1.pdb
Normal file
3
tests/FARMING/water_1.pdb
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
ATOM 1 OT TIP3 1 -0.757 -5.616 -7.101 1.00 0.00 WAT O
|
||||
ATOM 2 HT TIP3 1 -1.206 -5.714 -6.262 1.00 0.00 WAT H
|
||||
ATOM 3 HT TIP3 1 0.024 -5.102 -6.896 1.00 0.00 WAT H
|
||||
|
|
@ -56,3 +56,4 @@ FE/regtest-2
|
|||
QS/regtest-ot-refine-2
|
||||
QS/regtest-nonortho
|
||||
QS/regtest-ot-refine-3
|
||||
FARMING/regtest-1
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue