
subprocess
Executes a shell command as a concurrent subprocess to NCL.
Available in version 6.5.0 and later.
Prototype
function subprocess ( command [1] : string ) return_val [1] : integer
Arguments
commandA singly dimensioned string containing a shell command to execute.
Return value
Returns a numeric ID associated with the subprocess. This ID may be used with the subprocess_wait function to determine whether the subprocess has finished or to wait for it to finish.
Description
This procedure passes the string command to the shell environment for concurrent execution in a new subprocess. Control is returned immediately to NCL and the calling script continues its execution. Any output from the command to stdout/stderr will be intermingled with output from the calling script unless the shell command employs I/O redirection (see Examples below).
Using the subprocess command, an NCL script can perform several tasks in parallel. Typical use-cases might be the parallel execution of multiple independent NCL scripts, or executing multiple instances of a plotting script to generate plot-frames intended for an animation.
The default shell used to execute command is /bin/sh (Bourne Shell). A different shell may be specified in command; to use a different shell, such as the C-Shell, commands are enclosed by single quotes (') to prevent the Bourne Shell from interpreting the commands. If the C-Shell command itself contains single quotes, they must be escaped with a '\'. See Example 5 for the system command.
See Also
getenv, subprocess_wait system systemfunc
Examples
Example 1
Creating an animation. This example consist of two scripts. One is a simple "worker" script that takes a timestep as a parameter on the command-line and generates a contour plot of a variable for that time. It gets invoked by an outer "driver" script that coordinates running multiple instances of the worker script and then uses Imagemagick to generate an animation from the individual frames. The driver employs a simple gating mechanism to run some number of plot instances concurrently to keep the machine busy, but not so many as to overwhelm the system. Informal experiments with this techniquehave suggested that the number of concurrent plots could be on the order of the number of processor cores the machine has.
Driver:
begin MAX_CONCURRENT = 8 numTimeSteps = -1 ; ; determine how many time steps from the file... ; f = addfile("sst8292.nc", "r") dimNames = getvardims(f) dimSizes = getfiledimsizes(f) do i=0, dimsizes(dimNames)-1 if (dimNames(i).eq."time") then numTimeSteps = dimSizes(i) break end if end do print("Number of timesteps: " + numTimeSteps) delete(f) ; no longer needed ; ; begin generating plot frames... ; numPlotsCompleted = 0 numJobsActive = 0 do i=0,numTimeSteps-1 ; don't allow more than MAX_CONCURRENT processes at a time.... do while (numJobsActive.ge.MAX_CONCURRENT) ; check if any tasks have completed; block until something completes... pid = subprocess_wait(0, True) if (pid.gt.0) then numPlotsCompleted = numPlotsCompleted + 1 numJobsActive = numJobsActive - 1 break end if end do print("working on frame: " + i) command = "ncl contourSST.ncl " + str_get_sq() + "timestep=" + i + str_get_sq() + " >/dev/null" pid = subprocess(command) numJobsActive = numJobsActive + 1 end do ; ; need to wait for all pending jobs to complete... ; do while (numPlotsCompleted.lt.numTimeSteps-1) pid = subprocess_wait(0, True) if (pid.gt.0) then numPlotsCompleted = numPlotsCompleted + 1 end if end do ; ; use Imagemagick to create the animation from the *png frames... ; system("convert -delay 100 -loop 0 sst*.png sst.gif") end
Plotting script:
/; ;; Generates a contour plot of SST at a specific timestamp. ;; The variable "timestamp" is expected to be passed in on the command line ;/ begin print(timestep) f = addfile("sst8292.nc","r") sst = f->SST(timestep,:,:) plotfile = "sst" + sprinti("%03d", timestep) wks = gsn_open_wks("png", plotfile) res = True res@gsnMaximize = True res@cnFillOn = True res@cnFillPalette = "rainbow" res@tmYROn = False res@lbOrientation = "Vertical" res@pmLabelBarOrthogonalPosF = -0.02 yyyymm = cd_calendar(f->time(timestep), 0) res@tiMainString = sprinti("%02d", floattoint(yyyymm(0,1))) + "/" + sprinti("%4d", floattoint(yyyymm(0,0))) plot = gsn_csm_contour_map_ce(wks,sst,res) end