Beispiel #1
0
def launch(scan,alg,model,opt):
    #print 'launching scan'        
    #Set up MPI
    if opt.mode=='MPI':
        from mpi4py import MPI
        comm = MPI.COMM_WORLD 
        rank = comm.Get_rank()
    
        #let mother process write some initial info
        if rank==0:
            #print headers
            io.print_init(opt)
            #Set up directories            
            master_init(opt)            
        
        #Wait for mother before starting
        comm.barrier()
    
        scan(rank,alg,model,opt)
        
        if rank==0:
            io.print_finish(opt)
            if opt.merge_files:
                infiles=[os.path.join(opt.path,opt.run_name,'%s_%i.dat'%(opt.run_name,i)) for i in range(opt.chains)]
                outfile=os.path.join(opt.path,opt.run_name,'%s.dat'%(opt.run_name))
                io.merge_files(infiles,outfile,delete_files=True)
    
    #Otherwise use multiprocessing    
    if opt.mode=='multiprocessing':
        import multiprocessing as mp
        #impoer dill for proper pickling
        #import dill
        #print headers and initialize run_log
        io.print_init(opt)
        #master initialize: Sets up folders, and performs model.master_init if it exists
        master_init(opt,model)
        
        #queue for passing updates to master
        #Create Pipes for communication 
        master_ends,worker_ends=[[],[]]
        for rank in range(opt.chains-1):
            master,worker=mp.Pipe(duplex=True)
            master_ends+=[master]
            worker_ends+=[worker]
        
        processes=[]
        for rank in range(opt.chains):
            if rank==0:
                connection=master_ends
            else:
                connection=worker_ends[rank-1]    
            
            proc=mp.Process(target=scan, args=(rank,alg,model,opt,connection))
            proc.start()
    
            processes.append(proc)
    
        for proc in processes:
            proc.join()
            
        
        #Check if output from different files should be merged
        if opt.merge_files:
            infiles=[os.path.join(opt.path,opt.run_name,'%s_%i.dat'%(opt.run_name,i)) for i in range(opt.chains)]
            outfile=os.path.join(opt.path,opt.run_name,'%s.dat'%(opt.run_name))
            io.merge_files(infiles,outfile,delete_files=True)
            
    
    return
Beispiel #2
0
def scan(rank,alg,model,opt,connection=None):
    #Initialize random seed
    sp.random.seed(int(time.time())+rank)   
    #change directory
    orgdir=os.getcwd()
    os.chdir(os.path.join('tmp','tmp_%i'%rank))
    comm=prl.communicate(rank,opt,connection) 
    #Initialize Markov chain kernel and markov chain   
    kernel=alg.kernel(rank,opt)
    #Initialize global state
    state=alg.state(rank,opt,model)

    if rank==0:
        comm.send_state(state)         
    else:
        state=comm.worker_check(state,blocked=True)
   
    #Initialize chain (local state)
    chain=alg.chain(rank,opt,model,state)
    #Set up writer and printer
    writer=io.writer(rank,opt)
    printer=io.printer(rank,opt)
    
    if rank==0:
        updates=[]#initialize list of chain updates  
    
    #check if model has sequantial target distribution
    if 'parts' in dir(model):
        partial_lnP=True
    else:
        partial_lnP=False
    
    #Sample initial point
    init=True
    #print 'initializing'
    while init:
        params,modelid=kernel.initialize(state,chain)#Sample from initial distribution
        X_i=model(modelid,params)#Construct model from parameters
        chain.size+=1
        
        #Check if likelihood should be calculated sequentially
        if partial_lnP:                                  
            for part in X_i.parts:
                #Calculate a target component and update
                X_i.calculate(part)
 
                #check wether proposal already fails
                if opt.sequential:
                    if X_i.accept:
                        X_i.accept=X_i.lnP>=opt.lnP_min
                    if not X_i.accept:
                        break
            
            if not opt.sequential and X_i.accept:
                X_i.accept=X_i.lnP>=opt.lnP_min
                        
        else:
            #print "Calculating X_i"
            X_i.calculate()
            #print "X_i.accept:%i X_i.lnP: %f"%(X_i.accept,X_i.lnP)
            if X_i.accept:
                X_i.accept=X_i.lnP>=opt.lnP_min
                #print 'X_i accepted'
            
        #If accept update
        if X_i.accept:
            #print 'Stop initialization'
            init=False
            #chain.size+=1
            chain.accepted+=1
            #Assign initial weight, differs for different algorithms
            kernel.weight(X_i)
            if X_i.lnP>chain.lnP_max:
                chain.lnP_max=X_i.lnP
                chain.params_bf=X_i.params
        else:
            printer.print_model(X_i)
                        
            
        #finalize model if method exists
        if 'finalize' in dir(X_i):
            X_i.finalize()
                    
    #Loop while global and local state permits it
    while state.continue_sampling and chain.continue_sampling:   
        #sample proposal
        params,modelid=kernel.propose(X_i,state,chain)
        X_f=model(modelid,params)        
        
        chain.size+=1
        
        #generate random number for checking, dummyfor non-mcmc 
        u=sp.rand()        
        #Check if likelihood should be calculated sequentially
        if partial_lnP:                                  
            for part in X_f.parts:
                #Calculate a target component and update the total target
                X_f.calculate(part)                
                
                #check wether proposal already fails
                if opt.sequential:
                    if X_f.accept:
                        X_f.accept=kernel.accept(X_i,X_f,state,u)
                    if not X_f.accept:
                        break
                    
            if not opt.sequential and X_f.accept:
                X_f.accept=kernel.accept(X_i,X_f,state,u)
                        
        else:
            X_f.calculate()
            if X_f.accept:
                X_f.accept=kernel.accept(X_i,X_f,state,u)            
          
        #accept/reject point
        #If accept update
        if X_f.accept:
            chain.accepted+=1
            chain.batch_sum+=X_i.weight*sp.array(X_i.params.values())
            chain.batch_weight+=X_i.weight
            if X_i.lnP>chain.lnP_max:
                chain.lnP_max=X_i.lnP
                chain.params_bf=X_i.params
                    
            writer.add(X_i)
            printer.print_model(X_i)

            X_i=X_f
            #Assign initial weight, differs for different algorithms
            kernel.weight(X_i)
        else:
            printer.print_model(X_f)
            kernel.reweight(X_i)

        #finalize model if method exists
        if 'finalize' in dir(X_f):
            X_f.finalize()            
        
        #update chain
        chain.update()
        #Send state if send=True
        if chain.send:
            #No need to send to itself, just update state directly
            if rank==0:
                updates+=[chain]
            #Send updated chain state to master
            else:
                comm.send_chain(chain)
            
            #Reinitialize send status
            chain.send=False
        
        if rank==0:
            #Master: check for and get updated chain_state of workers
            while True:
                updates+=comm.master_check()
                #Master: update global state
                if len(updates)>0:
                    state.update(updates)
                    updates=[]#new empty updates list
                
                    #Send updated state to workerss
                    comm.send_state(state)
                    
                    #only print state if all chains have reached batch size, ignore master (which is slower)
                    if all(state.chain_sizes[1:][state.chain_status[1:]==1]>=state.N_prog):
                        state.N_prog+=state.batch_size    
                        printer.print_state(state)
                    
                #If master is finished before worker then wait
                if chain.continue_sampling==False and state.continue_sampling==True:
                    pass
                else:
                    break
                
        else:
            #Worker: check for status update from master
            try:
                state=comm.worker_check(state) 
            except:
                state.continue_sampling=False
        
        #Write last point and print results
        if chain.continue_sampling==False or state.continue_sampling==False:
            writer.add(X_i)
            printer.print_model(X_i)
            if rank==0:
                io.print_finish(opt)
        
    #close file
    #print 'closing writer'
    writer.close()
    os.chdir(orgdir)