Отсутствие итераций в цикле под SLURM - PullRequest
0 голосов
/ 29 января 2019

У меня есть простой код, который перебирает файл и делает простое исчисление.Приведенный ниже код является выдержкой из самого крупного: не просите никакой утилиты в этом коде, это всего лишь минимальный пример проблемы.

#!/bin/bash

#SBATCH --job-name=test
#SBATCH --output=test_%j.out
#SBATCH --error=test_%j.err
#SBATCH --workdir=.
#SBATCH --time=0:5:0
#SBATCH --partition=main
#SBATCH --qos=lowprio
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=4
#SBATCH --requeue

for SM in MB BL
do
    while read -r id
    do
        srun --job-name "Test-${id}" --nodes 1 --ntasks 1 --cpus-per-task 1 ls "$id" 1>&2
        echo "${id}"
    done < <(grep "$SM" internal.txt | awk '{print $1 "_" $2 "_" $3 ".txt"}') > "test_${SM}.dat"
done

Рациональное использование этого кода:файл с именем internal.txt У меня есть список данных, которые мне нужно разделить на две группы, с именами MB и BL .Я использую grep для поиска каждой из групп, я использую awk для составления базового имени файла, и он подается в цикл while как id.В этом цикле я использую srun для запуска команды (ls в этом примере), и в результате я просто вывожу $id.

Файл internal.txt содержит:

file 1 BL
file 1 MB
file 2 BL
file 2 MB
file 3 MB

Итак, ожидаемый результат - два файла, test_BL.dat:

file_1_BL.txt
file_2_BL.txt

и test_MB.dat:

file_1_MB.txt
file_2_MB.txt
file_3_MB.txt

Но реальность такова, что я получаю эти два файла... с первой записанной строкой, test_BL.dat:

file_1_BL.txt

и test_MB.dat:

file_1_MB.txt

Я уже знаю, что srun вовлечен в проблему,потому что если я избавлюсь от srun и оставлю только ls, он будет работать, как и ожидалось:

#!/bin/bash

#SBATCH --job-name=test
#SBATCH --output=test_%j.out
#SBATCH --error=test_%j.err
#SBATCH --workdir=.
#SBATCH --time=0:5:0
#SBATCH --partition=main
#SBATCH --qos=lowprio
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=4
#SBATCH --requeue

for SM in MB BL
do
    while read -r id
    do
        ls "$id" 1>&2
        echo "${id}"
    done < <(grep "$SM" internal.txt | awk '{print $1 "_" $2 "_" $3 ".txt"}') > "test_${SM}.dat"
done

Этот последний код работает хорошо, но теперь мне не хватает srun.Любые идеи о том, что здесь происходит?

Примечание: перечисленные файлы существуют.

1 Ответ

0 голосов
/ 30 января 2019

Благодаря @Inian, проблема решена!

Хитрость заключается в том, что srun по умолчанию считывает свой стандартный ввод для передачи его различным подпроцессам, которые он запускает.Он не ждет, пока подпроцессы начнут чтение с ввода, он просто читает свой ввод и сохраняет его в буфере до тех пор, пока кто-то не прочитает или процессы не завершатся (а затем данные не будут отброшены).

Чтобы решитьпроблема под рукой, нам нужно только закрыть стандартный ввод srun.Самый простой способ сделать это - использовать параметр --input, установив для него значение none:

srun --input none --job-name "Test-${id}" --nodes 1 --ntasks 1 --cpus-per-task 1 ls "$id" 1>&2

Закрытие стандартного ввода с помощью инструментов bash (т.е. добавление <&-) илиперенаправление /dev/null на стандартный вход (< /dev/null) также работает (проверено).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...