私たちの学校HPCにはスケジューラはありません。したがって、ジョブキューよりも良いことはありません。したがって、qsub
並列ジョブの送信を通過または自動化することはできませんsbatch
。
ジョブを「送信」するために常に使用した方法は、screen:と入力してを押し、次に入力して+screen
を押してから分離することです。Enter./runMyJob.sh
CTRLad
ここで、複数の並列画面セッションを開始し、各セッションでタスクを実行し、最後にすべての画面セッションを分離するプロセスを自動化/スクリプト化したいと思います。
ご覧のように、手動操作中にEnterとCTRL+を押してaから、を押しますd。これらのキーストロークをどのようにスクリプト化しますか?
PS:スケジューラなしでHPCで並列ジョブ送信を実装するのに役立つ提案を歓迎します!
答え1
キーストロークだとは思わず、作業を完了すると思います。キーストロークは相互作用の一形態です。タスクを自動化する方法はスクリプトを書くことです。
画面から作業を開始してすぐに切り離すには、次の手順を実行します。
screen -md ./runMyJob.sh
タスクを見つけやすくするために、-S
セッション名を設定するオプションがあります。
たとえば、タスク実行可能ファイルの名前をセッション名として使用する次のスクリプトを作成できます。
#!/bin/sh
screen -md -S "${1##*/}" "$@"
と同じ名前をsubmit
付けてPATH(シングルユーザーバイナリのインストール場所は何ですか?そしてどのUnixコマンドで見つかったホームディレクトリパスを追加するには?役に立つかもしれません)実行可能にしてください(chmod +x ~/bin/submit
)。タスクを開始するには、次を実行します。
submit ./runMyJob.sh
並列実行の場合は調査できます。GNUパラレル。
ジョブ送信フレームワークは、ジョブを開始する以上の機能を実行します。また、利用可能なCPU時間とメモリがある場所で実行するようにスケジュールし、送信者にログを送信します。管理者にジョブを送信するための適切なフレームワークを設定するように依頼する必要があります。
答え2
Enter、Ctrl- 一般的なASCIIコードをa生成しますd。
pipe()
したがって、考えられる解決策は、名前付きパイプ()を使用してプログラムを作成し、fork()
最初にパイプの読み取り端を標準入力にバインドするサブプロセスを作成し、サブプロセスscreen
(execve()
または同様)で実行することです。プログラムがすでに起動している場合は、生成されたパイプの書き込みの終わりにプロセスを開始するために必要なコマンドラインを作成できます。
タスクをプログラムに入れる方法は別のトピックです。たとえば、小さなスケジューラを直接作成できます(タスクキューとNプロセスを並列に開始するいくつかのコードなど)。
==編集==
Linux(またはUN * Xも一部)の場合、プログラムは次のようになります。
#include <sys/types.h>
#include <sys/linux.h>
#include <unistd.h>
int main(void) {
int fds[2] = {0};
pid_t pid = 0;
pipe(fds); /* Creates an unnamed pipe */
pid = fork(); /* Forks a new process */
if (pid == 0) {
static char const *argv[] = {"/usr/bin/screen", NULL};
/* Note: The array might need to be changed,
* depending on your requirements
* (eg. command-line arguments)
*/
dup2(fds[0], stdin); /* Binds the read end of the pipe to stdin */
execve(argv[0], argv, NULL);
/* If you reach this point, your execve() failed */
}
sleep(1); /* Waits for the child process to execute
* screen */
char const data[] = "./MyJob.sh\n\x00d";
/* Note: You must replace the '\x00' by the
* ASCII code of C-a!
*/
write(fds[1], data, sizeof(data));
/* Writes the name of the job along with the
* control codes to the child process
*/
int retcode = 0;
waitpid(pid, &retcode, 0);
/* Waits for the child process to terminate */
/* Note: WEXITSTATUS(retcode) gets the exit
* status of the child process */
return 0;
}
このプログラムはアイデアを説明する必要がありますが、必要なエラー処理が不足しています。