SASをマルチプロセスで実行したい - OSコマンドを非同期/同期で実行する systaskステートメント、実行が終るまで処理を止める waitforステートメント

今回は、(現時点では)SAS雲丹(SAS University Edition)で実行できないステートメントのお話。

SAS9.4では、DS2 でマルチスレッドができるみたいですけど、SAS9.3以前で似たようなものができないものか。proc sortとか一部のプロシージャはマルチで動くようになったけど、それだけでは足りない。SPDエンジンは使える環境ではない。どうしたものか。

そんなこんなで探して見つけたのが、systaskステートメントです。systaskステートメントは、OSのコマンドを実行するためのステートメントです。OSのコマンドを実行するには、filenameステートメントのpipe、Xステートメント、call systemルーチンなどがありますが、非同期では実行できません。systaskステートメントならば非同期または同期のどちらかを指定して実行することが出来ます。(同期 = 実行終了を待って後続の処理を実行、 非同期 = 実行終了待たずに後続の処理を実行)

まず、どのように書くのかを見てみましょう。

systask command "pwd" taskname="TASK_1" status=STATUS_1 ;

上記の例では、現在のディレクトリの位置を表示する pwd コマンドを実行しています。

taskname= で指定したのがタスク名です。指定したタスクが実行終るまで待つ、指定したタスクを kill する、といったときにタスク名を使います。

status= ではコマンドの出力結果が、指定したマクロ変数に格納されます。OSやらコマンドにもよると思いますが、例えば、正常終了ならば 0 、異常終了ならば 1 が格納される、といった感じです。

また、コマンドの標準出力の結果は、ログに出力されます。


さて、systaskステートメントでどうやってマルチで動かすかというと、SASのバッチ実行を使います。SASバッチを使うことで、SASの中で、SASを非同期で実行させます。

systask command "sas sample1.sas" taskname="TASK_1" status=STATUS_1 ;
systask command "sas sample2.sas" taskname="TASK_2" status=STATUS_2 ;
systask command "sas sample3.sas" taskname="TASK_3" status=STATUS_3 ;

/* 全てのタスクの状態をログに出力する */
systask list _all_ ;

/* タスクの終了を待つ */
waitfor _all_ STATUS_1 STATUS_2 STATUS_3 ;

/* 処理結果を表示 */
%put タスク1: &STATUS_1. ;
%put タスク2: &STATUS_2. ;
%put タスク3: &STATUS_3. ;

SASプログラム sample1.sas ~ sample3.sas を非同期で実行させています。(UNIX版、Windows版で、バッチ実行の書き方は多少異なるかと思います)

systask list は、タスクの状態をログに出力します。

waitforステートメントで、指定したタスクの処理終了を待ちます。処理結果は、指定したマクロ変数に格納されるので、結果によって、後続を実行するかどうかとか、処理を変えるとかできますね。

SASバッチを使っているので、マルチスレッドではなくて、マルチプロセスですかね。


上の例では、SASプログラムを複数同時実行させています。同じ環境設定ファイルが使われているので、同じWORK領域を指していると、ディスク容量が足りなくなるかもしれません。なので、それぞれ環境設定ファイルを変更するなりして対処する必要があります。SASバッチでは、以下のようにやるとイケルと思います。

/* WORK領域を指定して実行 */
systask command "sas sample1.sas -work /WORK/001" taskname="TASK_1" status=STATUS_1 ;

/* 環境設定ファイルを指定して実行 */
systask command "sas sample2.sas -config /TEST/sas.cfg" taskname="TASK_2" status=STATUS_2 ;

せっかくなので、systaskステートメントの他の機能も見てみましょう。

/* 同期で実行する場合は、wait を付けましょう */
/* 同期 = SASプログラムの実行終了を待つ      */
systask command "sas sample1.sas" taskname="TASK_1" status=STATUS_1 wait ;
/* waitforステートメントを使用しない場合は、cleanup を付けてください。  */
/* cleanup を付けることで、同名のタスク名をもう一度付けることが出来ます */
/* cleanup または waitfor なしに同名タスクを使うと怒られてしまいます。  */
systask command "sas sample1.sas" taskname="TASK_1" status=STATUS_1 cleanup ;
/* 指定したタスクを停止します */
systask kill TASK_1 ;

さて、SASからSASを複数実行することで、マルチプロセスを実現してみました。シェルスクリプトが使えるならば、waitコマンドを使って同じようなことができると思います。


参考サイト

  1. SASを使いやすくカスタマイズしよう SAS環境変数,AUTOEXECなど | うずまき(4th Gen) | Jun-Systems
  2. ディスクに空きがありません
  3. Windows版 バッチ(非対話)モードでの実行
  4. SASをバッチモードで実行する方法
  5. Customizing Your SAS Session By Using System Options | SAS(R) 9.4 Companion for UNIX Environments, Fourth Edition (英語)
  6. Changing SAS System Option Settings | SAS(R) 9.4 Companion for Windows, Third Edition (英語)

コメント

このブログの人気の投稿

日付フォーマットでない文字項目をSAS日付に変換するときにログ出力されるメッセージを抑制したい - SAS

データセット(.sas7bdatファイル)の文字コードを取得したい - SAS

Linuxコマンド: date で◯か月前 / ◯か月後を取得するときの注意