# Dispatches a fixed number of tasks to computational nodes. 
# Every task receives a large argument. 
# Measures the time required for returning the 
# First
# Run it by typing
#  mpirun -n 4 python3 03-dispatch.py
# If you run it with 
#  python3 03-dispatch.py
# only the local processor will be used. 
#
# Under Windows you should use Microsoft MPI. mpiexec and python should be in 
# the system path. 
#
#   mpiexec /np <number of processes> python 03-dispatch.py

from pyopus.parallel.cooperative import cOS
from pyopus.parallel.mpi import MPI
from funclib import echoer
from time import time, sleep

if __name__=='__main__':
	# Set up MPI
	vm=MPI(debug=0)
	vm.setWorkerDebug(0)
	cOS.setVM(vm)
	
	# Large data
	data=[0]*1000000
	
	# This generator produces 100 jobs which are tuples of the form
	#   (function, args)
	jobGen=((echoer, [data]) for _ in range(10))
	
	# Dispatch jobs and collect results, send and receive actual object
	t1=time()
	results=cOS.dispatch(jobList=jobGen, remote=True)
	t2=time()
	
	# Results are put in the list in the ame order as the jobs are generated by jobGen
	print("Without object persistence, results received in", t2-t1, "seconds")
	
	# Do over again, but this time with persistence
	vm.markPersistentObject(data)
	jobGen=((echoer, [data]) for _ in range(10))
	t1=time()
	results=cOS.dispatch(jobList=jobGen, remote=True)
	t2=time()
	
	## Results are put in the list in the ame order as the jobs are generated by jobGen
	print("With object persistence, results received in", t2-t1, "seconds")
	
	while True:
		retval=vm.receiveMessage(timeout=1.0)
		if type(retval) is tuple and len(retval)==0:
			break
	
	# Finish, need to do this if MPI is used
	cOS.finalize()
