2017-02-01 2 views
3

Ich habe eine Stata-Datei pyexample3.do, die ihr Argument als Regressor verwendet, um eine Regression auszuführen. Die F-Statistik aus der Regression wird in einer Textdatei gespeichert. Der Code lautet wie folgt:Ausführen paralleler Stata-Dateien in Python mit Multiprozess und Subprozess

clear all 
set more off   
local y `1'   
display `"first parameter: `y'"' 

sysuse auto 
regress price `y' 
local f=e(F) 
display "`f'" 
file open myhandle using test_result.txt, write append 
file write myhandle "`f'" _n 
file close myhandle 
exit, STATA clear 

Nun Ich versuche, die Stata-do-Datei parallel in Python und schreiben alle F-Statistik in einer Textdatei laufen. Meine CPU hat 4 Kerne.

import multiprocessing 
    import subprocess 

    def work(staname): 
     dofile = "pyexample3.do" 
     cmd = ["StataMP-64.exe","/e", "do", dofile,staname] 
     return subprocess.call(cmd, shell=False) 

    if __name__ == '__main__': 

     my_list =[ "mpg","rep78","headroom","trunk","weight","length","turn","displacement","gear_ratio" ] 

     my_list.sort() 

     print my_list 

     # Get the number of processors available 
     num_processes = multiprocessing.cpu_count() 

     threads = [] 

     len_stas = len(my_list) 

     print "+++ Number of stations to process: %s" % (len_stas) 

     # run until all the threads are done, and there is no data left 

     for list_item in my_list: 

      # if we aren't using all the processors AND there is still data left to 
      # compute, then spawn another thread 

      if(len(threads) < num_processes): 

       p = multiprocessing.Process(target=work,args=[list_item]) 

       p.start() 

       print p, p.is_alive() 

       threads.append(p) 

      else: 
       for thread in threads: 

       if not thread.is_alive(): 

        threads.remove(thread) 

Obwohl die tun, Datei 9 mal laufen soll, wie es 9 Strings in my_list sind, war es nur 4-mal ausgeführt werden. Also, wo ging es schief?

Antwort

1

In Ihrem for list_item in my_list Schleife, nachdem die ersten vier Prozesse initiiert erhalten, geht es dann in else:

for thread in threads: 
    if not thread.is_alive(): 
     threads.remove(thread) 

Wie Sie da thread.is_alive() diese Schleife sofort ohne jede der Hingerichteten blockieren nicht sehen können, erhalten 4 Prozesse beenden ihre Aufgabe. Daher werden nur die ersten 4 Prozesse ausgeführt.

Sie einfach eine while Schleife verwenden könnte ständig Prozesszustand mit einem kleinen Abstand zu überprüfen:

keep_checking = True 

while keep_checking: 
    for thread in threads: 
     if not thread.is_alive(): 
      threads.remove(thread) 
      keep_checking = False 

    time.sleep(0.5) # wait 0.5s 
+0

die Jetzt-Dateien zu tun ist 7-mal laufen, aber immer noch 2 mal fehlen. Die Nummer ändert sich auch, wenn 0.5s geändert wird. Wird es durch das gleichzeitige Schreiben in die Textdatei verursacht? – user20726

+0

könnte es sein. Da das Schreiben in dieselbe Datei nicht threadsicher ist, dh wenn Sie gleichzeitig aus verschiedenen Prozessen in eine Datei schreiben, kann es zu unerwarteten Ergebnissen kommen. Daher sollten Sie 'RLock' verwenden, um sicherzustellen, dass es nur einen Prozess gibt gleichzeitig an der Datei arbeiten. – Shane