paexec(1) | paexec(1) |
paexec - parallel executor, distribute tasks over network or CPUs
paexec [options]
paexec -C [options] command [args...]
Suppose you have a long list of tasks that need to be done, for example, you want to convert thousands of .wav audio files to .ogg format. Also suppose that multiple CPUs are available, e.g. multi-CPU system or a cluster consisting of individual computers connected to the network or internet. paexec can efficiently do this work, that is, paexec efficiently distributes different tasks to different processors (or computers), receives the results of processing from them and sends these results to stdout.
There are several notions that should be defined: task, command, transport, node.
Tasks are read by paexec from stdin and are represented as one line of text, i.e. one input line - one task.
node identifier - remote computer or CPU identifier, for example CPU ordinal number or computer's DNS name like node12.cluster.company.com.
Command - user's program that reads one-line task from stdin and sends multiline result to stdout ending with an end of task (EOT) marker. EOT marker means "Task is done. I am ready for the next one". After sending EOT to stdout, stdout MUST be flushed. Remember that EOT marker MUST NOT appears in general result. Otherwise, paexec may hang due to deadlock. The default EOT is an empty line. Command may use environment variable PAEXEC_EOT for the end-of-task marker.
Transport - special program that helps to run command on node. It takes the node identifier as its first argument and command with its arguments as the rest. Good examples for transport are ssh and rsh. Both transport and command may be specified with their arguments, e.g, '/usr/bin/ssh -x' is allowed as a transport program.
How paexec works. Commands are run on each node with a help of transport program. Then, tasks are read from stdin one-by-one and sent to free node (exactly one task per node at a time). At the same time result lines are read from command's stdout and are output to paexec's stdout. When EOT marker is obtained from the node, it is marked as free and becomes ready for the next task. These steps repeat until the end of stdin is reached and all nodes finish their job.
More formally (to better understand how paexec works):
run_command_on_each_node mark_all_nodes_as_free while not(end_of_stdin) or not(all_nodes_are_free) while there_is_free_node/i and not(end_of_stdin) task = read_task_from_stdin send_task_to_node(task, i) mark_node_as_busy(i) end while result_line_from_node_is_available/i result = read_result_line_from_node(i) send_line_to_stdout(result) if is_EOT(result) mark_node_as_free(i) end end end close_command_on_each_node
Note that commands are run once per node, it is not restarted for every task.
Also note that output contains result lines (obtained from different nodes) in the mixed order. That is, the first line of the output may contain a result line obtain from the first node, the second line of output - from the second node, but the third output line may contain result line from the first node again. It is also not guaranteed that the first line of output will be from the first node or from the first task. All result lines are output as soon as they are read by paexec, i.e as soon as they are ready. paexec works this way for the efficiency reasons. You can play with -l, -r and -p options to see what happens. For reordering output line you can use paexec_reorder utility.
Instead of autonomous tasks, graph of the tasks is read from stdin. In this mode every task can either FAIL or SUCCEED. As always an empty line output by command means end of task. The line before it shows an EXIT STATUS of the task. The word "failure" means failure, "success" - success and "fatal" means that the current task is reassigned to another node (and restarted, of course) (see option -z). See examples/1_div_x/cmd for the sample. An input line (paexec's stdin) should contain either single task without spaces inside or two tasks separated by single space character, e.g. task1<SPC>task2. task1<SPC>task2 line means that task1 must be done before task2 and it is mandatory, that is if task1 fail all dependent tasks (including task2) are also failed recursively. Tasks having dependencies are started only after all dependencies are succeeded. When a task succeeds paexec outputs "success" word just before end_of_task marker (see -e or -E), otherwise "failure" word is output followed by a list of tasks failed because of it.
Samples: tasks (examples/make_package/tasks file) textproc/dictem devel/autoconf wip/libmaa devel/gmake wip/libmaa wip/libmaa wip/dict-server wip/libmaa wip/dict-client devel/m4 wip/dict-server devel/byacc wip/dict-server devel/byacc wip/dict-client devel/flex wip/dict-server devel/flex wip/dict-client devel/glib2 devel/libjudy command (examples/make_package/cmd__flex) #!/usr/bin/awk -f { print $0 if ($0 == "devel/flex") print "failure" else print "success" print "" # end of task marker fflush() } output of "paexec -s -l -c cmd__flex -n +10 \ < tasks" 3 devel/autoconf 3 success 4 devel/gmake 4 success 7 devel/m4 7 success 8 devel/byacc 8 success 9 devel/flex 9 failure 9 devel/flex wip/dict-server wip/dict-client 10 devel/glib2 10 success 11 devel/libjudy 11 success 1 textproc/dictem 1 success 2 wip/libmaa 2 success
weight: gtk2 30 weight: glib2 20 gtk2 firefox weight: firefox 200 glib2 gtk2 weight: qt4 200 weight: kcachegrind 2 qt4 kcachegrind qt4 djview4 tiff djview4 png djview4 weight: twm 1 weight: gqview 4
paexec -t '/usr/bin/ssh -x' -n 'host1 host2 host3' \ -le -g -c calculate-me < tasks.txt | paexec_reorder -Mf -Sl
ls -1 *.wav | paexec -x -n +4 -c 'oggenc -Q'
ls -1 *.wav | paexec -xCil -n+4 flac -f --silent
{ uname -s; uname -r; uname -m; } | paexec -x -lp -n+2 -c banner | paexec_reorder -l
find . -name '*.dat' -print0 | paexec -0 -n+10 -C -J// scp // remoteserver:/remote/path
ls -1 *.txt | paexec -n+10 -J%% -c 'awk "BEGIN {print toupper(\"%%\")}"'
For more examples see paexec.pdf and examples/ subdirectory in the distribution.
select(2) system call and non-blocking read(2) are used to read result lines from nodes.
At the moment blocking write(2) is used to send task to the node. This may slow down an entire processing if tasks are too big. So, it is recommended to use shorter tasks, for example, filename or URI (several tens of bytes in size) instead of multi-megabyte content. Though this may be fixed in the future.
Original paexec tarball contains a number of sample of use in presentation/paexec.pdf file. After installation you can find this file under share/doc/paexec/paexec.pdf or nearby.
Please send any comments, questions, bug reports etc. to me by e-mail or (even better) register them at sourceforge project home. Feature requests are also welcomed.
<http://sourceforge.net/projects/paexec>
2019-11-24 |