Заставить gnu -rallel рассматривать строку замены как команду - PullRequest
0 голосов
/ 17 января 2019

Я хочу передать файл, содержащий список команд, в gnu -rallel при использовании замещающих строк (например, {%}).

К сожалению, если используются замещающие строки, gnu -rallel интерпретирует команды в файле как аргументы для /bin/bash.

Вот что я хочу сделать:

parallel -j 8 'CUDA_VISIBLE_DEVICES=$(({%} - 1)) {}' < commands.txt

где содержание commands.txt равно:

/path/to/binary -arg1 a -arg2 1.0
/path/to/binary -arg1 a -arg2 1.1
...
/path/to/binary -arg1 z -arg2 9.9

Однако возникает следующая ошибка:

/bin/bash: /path/to/binary -arg1 a -arg2 1.0: command not found

Я надеялся, что GNU Parallel запустится:

CUDA_VISIBLE_DEVICES=0 /path/to/binary -arg1 a -arg2 1.0

Назначение переменной среды CUDA_VISIBLE_DEVICES - заставить каждый процесс работать на другом GPU (по умолчанию все процессы выполняются на одном GPU). Если бы мне не нужно было CUDA_VISIBLE_DEVICES, следующий код работал бы отлично:

parallel -j 8 < commands.txt

Как мне обойти это?

Ответы [ 2 ]

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

Хотя --colsep может иногда работать, это не всегда правильный выбор. Это создаст файлы abc и def:

echo 'touch abc\ def' | parallel -v --colsep ' ' A=B {}

Обычно лучше декоквартировать выражение, используя eval:

echo 'touch abc\ def' | parallel -v eval A=B {}

Итак:

parallel -j 8 'eval CUDA_VISIBLE_DEVICES=$(({%} - 1)) {}' < commands.txt

Если вы много используете $(({%} - 1)), рассмотрите возможность создания собственной строки замены:

echo '--rpl {%-1}\ $_=slot()-1' >> ~/.parallel/config
parallel -j 8 'eval CUDA_VISIBLE_DEVICES={%-1} {}' < commands.txt

Или даже:

echo '--rpl '"'"'{CUDA} $_="CUDA_VISIBLE_DEVICES=".(slot()-1)'"'" >> .parallel/config
parallel -j 8 'eval {CUDA} {}' < commands.txt
0 голосов
/ 18 января 2019

Использование --colsep ' ' делает трюк:

parallel -j 8 --colsep ' ' 'CUDA_VISIBLE_DEVICES=$(({%} - 1)) {}' < commands.txt
...