【SAS】SPDEとTHREADによる並列処理

今まで、大規模なトランザクションデータについてはパススルークエリを投げてDB側で処理をしてもらってからSASに持ってくるようにしていたので、SASでの並列処理は考えなくても不便はありませんでした。
今回、諸事情によりSAS側で大きな(100GB程度)のトランザクションデータを処理しなければいけなくなり、実際にやってみると実行時間が気になってきたので、並列処理ができないか検討しました。
その結果、割と簡単なやり方で実行時間が2/3程度には圧縮できたのでメモとして残しておきます。

やったこととやらなかったこと

SPDEを利用したデータセットの分散とTHREADによるCPUコアに処理を分散させることをしました。
SPDサーバの導入や、DS2によるTHREADはやっていません。
非常に簡易な分散処理です。

THREADについて

THREADについては、デフォルトでオンになっている環境もあるかもしれません。
BASE SASのINDEXINGと、BASE SASの一部のプロシジャ(SORT、SUMMARY、MEANS、REPORT、TABULATE、SQL)、SAS/STATの一部のプロシジャについて、処理をCPUコアで分散してくれます。
設定方法は、オプションに以下の様に書くだけです。

OPTIONS THREADS CPUCOUNT=ACTUAL;

「CPUCOUNT」はCPUのコア数で数値で指定することもできますが、その場合でも普通は実際のCPUコア数を指定するみたいです。
実際のCPUコア数よりも多い数を指定すると、実行速度が遅くなる場合もあるみたいです。

SAS(R) 9.4 Language Reference: Concepts, Fifth Edition

SPDEについて

SPDサーバというのがデータセットを分散して格納するSASサーバらしいのですが、SPDE(Scalable Performance Data Engine)というのはその簡易版だと思えば良いらしいです。
SASがデータセットにどのようにアクセスするかはLIBNAMEを設定する際のエンジンに依存するのですが、そのエンジンを通常使っているV9からSPDEに変更することで、データセットが分散して格納されます。
データサイズが小さい場合は、SPDEの方がアクセス速度が遅くなる場合もあるらしいので、どのような場合にSPDEを使えば良いかは、下記を参照してください。

When Should You Use the SPDE Engine

SPDEを使用するにはLIBNAME宣言を以下の様にすれば良いです。

LIBNAME mywork SPDE "C:\folder";

そうすると、ログに以下の様に出ると思います。

NOTE: ライブラリ参照名myworkを次のように割り当てました。
エンジン:SPDE
物理名:C:\folder\

ちなみに、SPDEを付けないでLIBNAME宣言をすると、以下の様なログが出ます。

NOTE: ライブラリ参照名myworkを次のように割り当てました。
エンジン:V9
物理名:C:\folder\

SASの環境によりエンジンは異なるかもしれませんが、SPDEではないエンジンだと思います。ぱっと使った中で、いくつか気づいた点があります。

SPDEとV9の互換性

SPDEとV9は厳密には互換性が無いです。
V9エンジンで宣言したライブラリ内にデータセットを作成すると、sas7bdat形式のファイルが1データセットに1つ対応して作成されると思います。SPDEで宣言したライブラリ内にデータセットを作成すると、大量のspds9形式のファイルが作成されると思います。よく見るとmdf.0.0.0.spds9という拡張子のファイルがあるので、おそらくこれが分割されたファイル間の関係を記述しているもので、他の連番のファイルが分割されたデータだと思います。

EGとかからだと、どちらも一つのデータセットに見えるのですが、物理的な保存形式が違うため単純な読み書きの互換性もありません。例えば、「C:\folder\test.sas7bdat」というファイルがあったとして、「LIBNAME mywork SPDE "C:\folder";」とSPDEでライブラリを宣言すると、このデータセットは存在しないように見えます。つまり、同じようなデータセットに見えてしまうのですが、sas7bdatとspds9はSASを介して変換してあげる必要があります。

試していないので分からないのですが、sas7bdat形式のデータセットとspds9形式のデータセットのjoinは、spds9形式のデータセット同士のjoinよりも遅くなると思います。SAS EMでハイパフォーマンスノードと通常のノードに互換性が無いのは、裏側でのデータの持ち方に違いがあるせいですかね。

その他にも、オプションや関数で違いが出てくる場合もあります。FIRSTOBSは使えないみたいです。options dlcreatedirもダメでした。

Syntax for the SPD Engine

SPDEのWORK領域

おそらく、SPDEを使用するのであれば、全てのデータセットをSPDEで参照できる形にしておかないと、全体の効率は落ちると思います。そうすると、WORK領域もSPDEにしないといけないのですが、コンフィグの変更になってしまう気がして面倒くさいので、なにかないかと思って探していたらありました。LIBNAMEの宣言時にTEMPオプションをYESにするとWORK領域のように使えます。

LIBNAME mywork SPDE "C:\folder" TEMP=YES;

このように宣言すると、指定したフォルダ配下にSASセッション一つに付き一つのサブフォルダを作成して、そのSASセッションが終了するときにはサブフォルダを削除するということをしてくれます。SASセッションごとに固有の名前のサブフォルダが生成されるので、複数のSASセッションから同じフォルダをLIBNAME宣言しても、お互いが影響を与えることはありません。