Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 16/03/2016, à 19:01

alius

Lancer X jobs en parallèle à la chaîne [SOLVED]

Salut tout le monde,

je suis actuellement entrain de faire de l'extraction de caractéristique musicales sur une grande quantité de fichier .wav ce qui est un traitement lourd. Je veux le faire de manière automatique, le tout en lançant plusieurs job (un par fichier wav) en parrallèle. Je fais ça avec nohup, cependant je me retrouve rapidement à cours de mémoire et le swap n'est pas l'idéal. Alors il m'est venu l'idée de scripter le lancement de mes jobs de manière à n'avoir que 3 jobs simultanément.
Le problème c'est que ça ne marche pas. Tout mes jobs se lancent à la suite ce qui fait tout swapper et freeze la machine pendant un long moment...


J'ai donc deux fichiers .sh :

le premier scheduler.sh s'occupe du parcours de tous les fichiers .wav a traiter et fait nohup de l'autre .sh (qui s'occupe de lancer le job) si je n'ai pas atteint la limite de 3 jobs. Lorsque ma limite est atteinte, je check en boucle le contenu de 3 fichier contenant le PID des jobs qui ont été lancé. En fait la première chose que fait un job lorsqu'il se lance c'est écrire son PID dans un fichier. Lorsqu'un job se termine je peux alors lancer un nouveau job. Et ainsi de suite...

le deuxième fichier launcher.sh s'occupe du lancement du job.  En premier lieu il écrit son pid dans un fichier et lance mon programme de traitement.



voici une version simulée de mon script qui au lieu de lancer mon prog, fait simplement un sleep...

scheduler.sh :

FILES_DIR=$1       # le repertoire de mes fichiers wav
let JOB_LIMIT=2    # la limite de job fixée a 3 (0, 1 et 2)
let CTR=0          # un conteur pour les jobs

# une boucle qui parcour mes .wav avec un find
for $WAV_FILE in $(find -L $FILES_DIR -type f -name *.wav)
do
    # je check le nombre de job
    while [ $CTR -gt $JOB_LIMIT ]    # si le nombre de job est > que 2, true
    do
        # une boucle pour traiter chaque fichier .pid de chaque job
        for K in `seq 0 2`
        do
            PID= cat ./.myscript$K.pid                                      # lis le fichier qui contient le pid
            if [ "$(ps -p $PID | tr -s ' ' | cut -d' ' -f1)" != "$PID" ]    # on check l'état du process avec la commande ps,
                                                                            # si le processus est fini est fini, true
            then
                let CTR=CTR-1    # on décremente le counter de job
            fi
        done

    done

    # on appel le launcher.sh avec nohup
    nohup bash launcher.sh $CTR
    # CTR++
    let CTR=CTR+1
done

launcher.sh:

# écrit son pid dans le fichier .pid fournit en argument
echo $$ > ./.myscript$1.pid

# fait un petit somm
sleep 1

en fait j'ai l'impression que le sleep n'est pas bloquant et que donc le processus lancé par le nohup bash launcher.sh $CTR se termine avant le sleep

edit: Est-ce que quelqu'un sait si un sleep peut devenir non bloquant quand utilisér avec un nohup ?

Dernière modification par alius (Le 17/03/2016, à 21:29)


Alius

Hors ligne

#2 Le 16/03/2016, à 19:14

Sciensous

Re : Lancer X jobs en parallèle à la chaîne [SOLVED]

le problème est que

while [ $CTR -gt $JOB_LIMIT ]  

ne se vérifie pas car CTR=0 et JOB_LIMIT>0 au départ , non ?


antiX 19 et 21 et Ubuntu 20.04 et 22.04
( sous LXDE et gnome-shell )

Hors ligne

#3 Le 16/03/2016, à 19:51

alius

Re : Lancer X jobs en parallèle à la chaîne [SOLVED]

Salut,

JOB_LIMIT est fixé à 2 et ne bouge pas, seulement CTR bouge.

j'ai fais une bourde de recopie sur le forum, le nohup n'est pas dans le while, j'ai rectifié sur le premier post.
les 3 premiere fois on ne rentre pas dans le while, on lance simplement 3 jobs

Dernière modification par alius (Le 16/03/2016, à 19:54)


Alius

Hors ligne

#4 Le 17/03/2016, à 12:04

alius

Re : Lancer X jobs en parallèle à la chaîne [SOLVED]

Problem Solved !

Le problème viens des sorties de la commande ps... explications :

ps -p ${PID} -h | tr -s ' ' | cut -d ' ' -f1

renvois des choses différentes (je ne suis pas encore bien sur du pourquoi) toujours est il qu'il faut y faire attention.

je met les codes de mes scripts au cas où ça puisse servir à quelqu'un:

scheduler.sh :

#!/usr/bin/env bash

# jobs scheduler
#
# schedulnig the call of the job launcher to a fixed number of jobs


# a function for display text
function info() {
    task="$1"
    shift
    FG="\033[1;32m"
    BG="\033[40m"
    NC="\033[0m"
    echo -e "[${FG}${BG}${task}${NC}] $*"
}


# set job limit, job counter
# and a .pid file identifier
let job_limit=2
let ctr=0
let id=0

# remove old .pid files and old nohup output
rm .myscript*.pid
rm nohup.log

# looping on sequence of something (files to process)
sequence=$(seq 0 25)
for file in ${sequence}; do
    prt_wait="true" # a var to know when print to wait

    # a loop to wait a job to return
    while [ ${ctr} -gt ${job_limit} ]; do # when counter > limit, true

        # condition to print wait only once
        if [ ${prt_wait} = "true" ]; then
            info "wait" "A job is waiting to end before a new to launch"
            prt_wait="false"
        fi

        # loop on each pid file and check the pid status
        for k in $(seq 0 ${job_limit}); do
            pid=$(cat ./.myscript${k}.pid)  # read pid

            # check pid status
            status=$(ps -p ${pid} -h | tr -s ' ' | cut -d ' ' -f1)
            # check status again when we have a text format issue
            if [ -z "${status}" ]; then
                status=$(ps -p ${pid} -h | tr -s ' ' | cut -d ' ' -f2)
            fi

            # when status does not match with pid, means process has return
            if [ "${status}" != "${pid}" ]; then
                info "ready" "Job #${pid} has just terminated"
                let ctr=ctr-1   # job counter ++
                id=${k}         # set id to the available pid file
                break           # break pid file checking
            fi
        done
    done

    # here we can launch new job,
    # we make it using nohup in background
    # stdout and stderr are redirected to nohup.log
    nohup bash ./launcher.sh ${id} &>nohup.log &
    info "launch" "Scheduler has launch a new job $!"
    let ctr=ctr+1   # job counter ++
    let id=id+1     # pid file id ++
    sleep 0.2       # short sleep to give time to process
done

et launcher.sh :

#!/usr/bin/env bash

# job launcher
#
# write its pid in a file and launch a job

id=$1   # set id from argument passed by scheduler
pid_file=./.myscript${id}.pid   # build pid file name with id
shift

# write process's pid in the file
echo $$ > ${pid_file}

# simulate a job
sleep 3

Alius

Hors ligne