Как (тривиально) распараллелить с оболочкой Linux, запустив одну задачу на ядро ​​Linux? - PullRequest
6 голосов
/ 24 января 2012

Современные процессоры обычно состоят из нескольких физических ядер.Они могут даже быть многопоточными, так что ядро ​​Linux видит довольно большое количество ядер и, соответственно, несколько раз запускает планировщик Linux (по одному на каждое ядро).При выполнении нескольких задач в системе Linux планировщик обычно обеспечивает хорошее распределение общей рабочей нагрузки по всем ядрам Linux (возможно, это одно и то же физическое ядро).

Теперь, скажем, у меня есть большое количество файлов дляпроцесс с тем же исполняемым файлом.Я обычно делаю это с помощью команды «find»:

find <path> <option> <exec>

Однако, это запускает только одну задачу в любое время и ждет ее завершения, прежде чем начинать следующую задачу.Таким образом, для этого используется только одно ядро.Это оставляет большинство ядер бездействующими (если эта команда find является единственной задачей, выполняющейся в системе).Было бы намного лучше запустить N задач одновременно.Где N - количество ядер, видимых ядром Linux.

Есть ли команда, которая это сделает?

Ответы [ 3 ]

7 голосов
/ 24 января 2012

Используйте find с опцией -print0.Отправьте трубку к xargs с опцией -0.xargs также принимает опцию -P для указания количества процессов.-P следует использовать в сочетании с -n или -L.

Для получения дополнительной информации прочитайте man xargs.

Пример команды: find . -print0 | xargs -0 -P4 -n4 grep searchstring

2 голосов
/ 25 января 2012

Если у вас установлен GNU Parallel http://www.gnu.org/software/parallel/, вы можете сделать это:

find | parallel do stuff {} --option_a\; do more stuff {}

Вы можете установить GNU Parallel просто:

wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel
cp parallel sem

Посмотрите вступительные видео для GNU Parallel, чтобы узнать больше: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

0 голосов
/ 25 января 2012

Gnu параллельно или xargs -P, вероятно, лучший способ справиться с этим, но вы также можете написать своего рода многозадачный фреймворк в bash.Это немного грязно и ненадежно, однако, из-за отсутствия определенных возможностей.

#!/bin/sh

MAXJOBS=3
CJ=0
SJ=""

gj() {
    echo ${1//[][-]/}
}

endj() {
    trap "" sigchld
    ej=$(gj $(jobs | grep Done))
    jobs %$ej
    wait %$ej
    CJ=$(( $CJ - 1 ))
    if [ -n "$SJ" ]; then
        kill $SJ
        SJ=""
    fi
}
startj() {
    j=$*
    while [ $CJ -ge $MAXJOBS ]; do
        sleep 1000 &
        SJ=$!
        echo too many jobs running: $CJ 
        echo waiting for sleeper job [$SJ]
        trap endj sigchld
        wait $SJ 2>/dev/null
    done
    CJ=$(( $CJ + 1 ))
    echo $CJ jobs running.  starting: $j
    eval "$j &"
}

set -m

# test
startj sleep 2
startj sleep 10
startj sleep 1
startj sleep 1
startj sleep 1
startj sleep 1
startj sleep 1
startj sleep 1
startj sleep 2
startj sleep 10

wait
...