Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

make: Run several tasks in parallel and wait for completion

One target in my makefile is a very CPU and time consuming task. But I can split the workload and run the task several times in parallel to speed up the entire process.

My problem is that make doesn't wait for all processes to complete.

Consider this simple script, named myTask.sh:

#!/bin/bash

echo "Sleeping $1 seconds"
sleep $1
echo "$1 are over!"

Now, let's call this from a bash script, and use wait to wait for all tasks to complete:

#!/bin/bash

echo "START"
./myTask.sh 5 &
./myTask.sh 15 &
./myTask.sh 10 &

wait  # Wait for all tasks to complete

echo "DONE"

The output is as expected:

START
Sleeping 15 seconds
Sleeping 5 seconds
Sleeping 10 seconds
5 are over!
10 are over!
15 are over!
DONE

But when trying the same in a Makefile:

test:
    echo "START"
    ./myTask.sh 5 &
    ./myTask.sh 15 &
    ./myTask.sh 10 &
    wait
    echo "DONE"

it doesn't work:

START
Sleeping 5 seconds
Sleeping 15 seconds
Sleeping 10 seconds
DONE
sweber@pc:~/testwait $5 are over!
10 are over!
15 are over!

Of course, I could create multiple targets which can be "built" in parallel by make, or let make just run the bash script which runs the tasks. But is there a way to do it more like what I already tried?

like image 222
sweber Avatar asked Jan 03 '17 21:01

sweber


People also ask

What does it mean to do tasks in parallel?

Parallel tasks are split into subtasks that are assigned to multiple workers and then completed simultaneously. A worker system can carry out both parallel and concurrent tasks by working on multiple tasks at the same time while also breaking down each task into sub-tasks that are executed simultaneously.

How many process can run in parallel?

Parallelism refers to the ability to execute two or more concurrent processes simultaneously. You must have more than one processing core to execute two processes in parallel. Erlang is built for concurrency and will run concurrent solutions (even with a single CPU).

Does make run in parallel?

Normally, the make command runs commands sequentially for only one target at a time, waiting for the command to finish before running the next. However, the make command can also run in a parallel run mode, where it can run many concurrent jobs to build independent targets.

How do you run a command in parallel?

To start GNU Make in parallel mode it's enough to specify either the -j or --jobs option on the command-line. The argument to the option is the maximum number of processes that GNU Make will run in parallel. For example, typing make --jobs=4 will allow GNU Make to run up to four subprocesses in parallel.


2 Answers

Each individual logical line in a recipe is invoked in its own shell. So your makefile is basically running this:

test:
        /bin/sh -c 'echo "START"'
        /bin/sh -c './myTask.sh 5 &'
        /bin/sh -c './myTask.sh 15 &'
        /bin/sh -c './myTask.sh 10 &'
        /bin/sh -c 'wait'
        /bin/sh -c 'echo "DONE"'

You should make it all run in a single shell using semicolons and backslash/newlines to combine the physical lines into one logical line:

test:
        echo "START"; \
        ./myTask.sh 5 & \
        ./myTask.sh 15 & \
        ./myTask.sh 10 & \
        wait; \
        echo "DONE"
like image 143
MadScientist Avatar answered Oct 25 '22 15:10

MadScientist


Why not use the mechanisms already built in make? Something like this:

task%:
        sh task.sh $*

test: task5 task15 task10
        echo "DONE"

You will be able to adjust the level of parallelism on the make command line, instead of having it hard-coded into your makefile (e.g use 'make -j 2 test' if you have 2 cores available and 'make -j 32 test' if you have 32 cores)

like image 25
Come Raczy Avatar answered Oct 25 '22 17:10

Come Raczy