Search code examples
pythonsubprocessexternal-process

Running multiple external programs


So, I set up a short script which executes an external program (written in Fortran 77). I want to run multiple instances of the program and since I have 8 cores on my computer the simplest solution I found was:

import subprocess


import os


i = n

while(i<n):
  dire = "dir/Run"+str(i)+"/"
  os.chdir(dire)
  p1 = subprocess.Popen(['./mej'])
  dire = "dir/Run"+str(i+1)+"/"
  os.chdir(dire)
  p2 = subprocess.Popen(['./mej'])
  dire = "dir/Run"+str(i+2)+"/"
  os.chdir(dire)
  p3 = subprocess.Popen(['./mej'])
  dire = "dir/Run"+str(i+3)+"/"
  os.chdir(dire)
  p4 = subprocess.Popen(['./mej'])  
  dire = "dir/Run"+str(i+4)+"/"
  os.chdir(dire)
  p5 = subprocess.Popen(['./mej'])
  dire = "dir/Run"+str(i+5)+"/"
  os.chdir(dire)
  p6 = subprocess.Popen(['./mej'])
  dire = "dir/Run"+str(i+6)+"/"
  os.chdir(dire)
  p7 = subprocess.Popen(['./mej'])
  dire = "dir/Run"+str(i+7)+"/"
  os.chdir(dire)
  p8 = subprocess.Popen(['./mej'])
  dire = "/Run"+str(i+8)+"/"
  os.chdir(dire)
  p3 = subprocess.Popen(['./mej'])
  exit_codes = [p.wait() for p in p1, p2, p3, p4, p5, p6, p7, p8]
  i = i + 8



print "Job's done!"

Now this worked mostly fine at first, however I just changed to a variable time step and in doing so the time each integration runs for varies significantly. Now the problem is that the script will wait for the slowest one to finish before starting up a new set of integrations. How can I write it so that I will always have 8 instances running?


Solution

  • You could use a thread pool, to keep all CPUs busy:

    #!/usr/bin/env python
    import os
    import subprocess
    from multiprocessing.pool import ThreadPool
    
    def run(i):
        working_dir = "dir/Run/" + str(i + 1)
        return i, subprocess.call(os.path.join(working_dir, 'mej'), cwd=working_dir)
    
    results = ThreadPool().map(run, range(n))
    

    As soon as one mej process finishes, the next one is started. No more than os.cpu_count() concurrent worker processes are running at a time.