Я пытаюсь использовать GNU параллельно для проведения серии экспериментов с использованием MATLAB на нашем суперкомпьютере, который использует SLURM. У меня есть текстовый файл, содержащий комбинации из 4 параметров, которые считываются и передаются в функцию MATLAB. Этот текстовый файл называется gnu_parameters.txt
и имеет 4 столбца, разделенных одним пробелом.
fs_method data_name use_vars 1
fs_method1 data_name use_vars 1
fs_method3 data_name use_vars 1
где параметры в столбцах 1–3 следует считывать как строку, а параметр 4 — число.
Я хочу запускать каждую комбинацию параметров параллельно, чтобы ускорить процесс. Мой сценарий SLURM приведен ниже, но когда я говорю GNU-parallel, куда поместить каждый параметр, используя обозначение {1} {2} {3} {4}
, я получаю сообщение об ошибке, что MATLAB не распознает переменную fs_method
. Просмотр журнала говорит мне, что ошибка означает, что MATLAB не читает как строку. Чтобы это исправить, я попробовал добавить одинарные кавычки в сценарий SLURM следующим образом:
#!/bin/bash -l
#SBATCH --time=4-00:00:00
#SBATCH --ntasks=1
#SBATCH --mem=1200g
#SBATCH --tmp=500g
#SBATCH --cpus-per-task=115
#SBATCH --mail-type=FAIL,END
#SBATCH --mail-user=myemail
#SBATCH -p groupPartition
cd $WRK_DIR
module load matlab
module load parallel
export JOBS_PER_NODE=$(( $SLURM_CPUS_ON_NODE / $SLURM_CPUS_PER_TASK ))
echo $JOBS_PER_NODE
cat gnu_parameters.txt | parallel --jobs $JOBS_PER_NODE --joblog tasklog.log --progress --colsep ' ' 'matlab -nodisplay -r "run_holdout_parallel('{1}', '{2}', '{3}', {4});exit" '
Ниже приведены выдержки из файла журнала, файла ошибок и выходного файла.
Бревно
Seq Host Starttime JobRuntime Send Receive Exitval Signal Command
1 : 1719498346.300 14.911 0 298 0 0 matlab -nodisplay -r "run_holdout_parallel(fs_method, data_name, use_vars, 1);exit"
2 : 1719498361.751 14.387 0 298 0 0 matlab -nodisplay -r "run_holdout_parallel(fs_method1, data_name, use_vars, 1);exit"
3 : 1719498376.666 14.385 0 298 0 0 matlab -nodisplay -r "run_holdout_parallel(fs_method3, data_name, use_vars, 1);exit"
Файл ошибок
local:1/0/100%/0.0s sh: /dev/tty: No such device or address
local:1/0/100%/0.0s sh: /dev/tty: No such device or address
local:1/0/100%/0.0s {Unrecognized function or variable 'fs_method'.
}
local:0/1/100%/15.0s
Выходной файл
< M A T L A B (R) >
Copyright 1984-2023 The MathWorks, Inc.
R2023b Update 7 (23.2.0.2515942) 64-bit (glnxa64)
January 30, 2024
To get started, type doc.
For product information, visit www.mathworks.com.
< M A T L A B (R) >
Copyright 1984-2023 The MathWorks, Inc.
R2023b Update 7 (23.2.0.2515942) 64-bit (glnxa64)
January 30, 2024
To get started, type doc.
For product information, visit www.mathworks.com.
Но это возвращает ту же ошибку. Как я могу передать эти параметры в виде строк в MATLAB? Есть ли лучший способ провести эти эксперименты параллельно, чем тот метод, который я использую?
@CrisLuengo Да, я отредактировал свой вопрос, включив их.
Ага, понятно. Возможно, вам придется избежать кавычек. run_holdout_parallel(\'{1}\',
@CrisLuengo Хорошая мысль. Я попробовал это и получил синтаксическую ошибку /var/spool/slurmd/job19168324/slurm_script: line 16: syntax error near unexpected token `)'`
. Я думаю, что проблема в синтаксисе этих кавычек. Я не эксперт в bash :/
Да, кавычки в bash я всегда делаю методом проб и ошибок, я их правда не понимаю. Я думаю, что часть {1}
должна быть за пределами одинарных кавычек. Но вам нужны одинарные кавычки для передачи в MATLAB. Так может быть что-то вроде run_holdout_parallel(\''{1}'\',
?
В настоящее время в журнале вы видите, что выполняется команда matlab -nodisplay -r "run_holdout_parallel(fs_method, data_name, use_vars, 1);exit"
. Вам нужно настроить bash-скрипт так, чтобы это стало matlab -nodisplay -r "run_holdout_parallel('fs_method', 'data_name', 'use_vars', 1);exit"
. Иногда кавычки необходимо экранировать дважды (\\\'
), если они проходят два этапа интерпретации bash. Не спрашивай...
Очевидно, вы не можете избежать одинарных кавычек. Вот обходной путь: stackoverflow.com/a/1250279/7328782 -- Так что, я думаю, будет run_holdout_parallel('"'"{1}"'"',
.
@CrisLuengo казалось, что это сработало, но в файле журнала ничего не отображается. Может быть, просто нужно время...
Проблема в том, как экранируются кавычки. Способ, который работает для меня, это
'matlab -nodisplay -r "run_holdout_parallel(\\\"{1}\\\", \\\"{2}\\\", \\\"{3}\\\", {4});exit" '
Почему-то воспользовавшись ответом в комментариях
'matlab -nodisplay -r "run_holdout_parallel('"'"{1}"'"', '"'"{2}"'"', '"'"{3}"'"', {4});exit" '
работал нормально, но команды не выполнялись.
Несколько советов, которые не дают прямого ответа на ваш вопрос, но могут быть полезны для более эффективного выполнения вашей работы.
parfor
, чтобы масштабировать свою работу до вашего кластера.parpool('local')
на узле, выделенном вам SLURM.matlab -r
для подобных вещей.Я ненавижу цитировать. man parallel
говорит:
Вывод: если это сбивает с толку, подумайте о том, чтобы избежать необходимости иметь дело с кавычками, написав небольшой скрипт или функцию (не забудьте экспортировать -f функцию) и использовать параллельный вызов GNU.
Итак, в вашем случае создайте функцию:
run_holdout() {
echo This should run_holdout_parallel on $1 $2 $3 $4
matlab -nodisplay -r "run_holdout_parallel(\"$1\", \"$2\", \"$3\", $4);exit"
}
Когда вы можете запустить это в командной строке:
$ run_holdout fs_method3 data_name use_vars 1
и это работает, затем распараллелите с:
$ export -f run_holdout
$ ... | parallel run_holdout {1} {2} {3} {4}
Спасибо, это очень хорошо работает и легче читается!
Можете ли вы поделиться соответствующим разделом журнала и/или выводом консоли?