ラベル [▼ 効率を意識したプログラム の投稿を表示しています。 すべての投稿を表示
ラベル [▼ 効率を意識したプログラム の投稿を表示しています。 すべての投稿を表示

2018年10月1日月曜日

【効率を意識したプログラム】WHEREとサブセット化IFの使い分け




「WHERE」と「サブセット化IF」の違いを知って使い分けようっていう話です。



「WHERE」と「サブセット化IF」の比較


Sample data
data test;
   length col1-col200 $200.;
   array ar(*) col:;
   do i=1 to dim(ar);
       ar(i) = "abcdefg";
   end;
   do i=1 to 50000;
      output;
   end;
run;



サンプルデータから「WHEREステートメント」を使ってオブザベーションを抽出したときの処理時間とCPU時間を見てみます。

data out1;
   set test;
   where i<100;
run;

ログ
       処理時間           0.33 秒
       ユーザーCPU時間    0.02 秒
       システムCPU時間    0.32 秒


同様のオブザベーションの抽出を「サブセット化IF」を使って処理時間とCPU時間を見てみます。

data out1;
   set test;
   if i<100;
run;

ログ
       処理時間           0.53 秒
       ユーザーCPU時間    0.12 秒
       システムCPU時間    0.41 秒

WHEREステートメントの方が処理時間が短いですね。何故このような違いが起きたのでしょうか。





「WHERE」と「サブセット化IF」の違い


・実行されるタイミングが違う
 WHERE

 データを読み込む前に実行される
 サブセット化IF 

 データを読み込んだ後のデータステップ内で実行される

WHEREの方が実行されるタイミングが早いんで、処理時間が短くなるというわけですね。



・実行できる環境の違い
 WHERE

 データステップおよび(ほとんどの)PROCステップで実行できる
 サブセット化IF 

 データステップでのみ実行できる





「サブセット化IF」の利点


サブセット化IFが効果的な例として、以下記事の例②で紹介しているようなケース。
【サブセット化IF】条件に一致するオブザベーションのみ処理を継続する。

data out2;
  set dt1;
  c = a + b;
  if c >= 10;
run;

この例ではデータステップ内で計算した変数Cをサブセット化IFで使用しています。
WHEREステートメントだと「where c >= 10」と書くことは出来ませんよね(データを読み込む前には、まだ変数Cが導出されていないので)




2018年8月30日木曜日

【効率を意識したプログラム】KEEPやDROPの利用




DROPとKEEPを活用しようっていう話です。



Sample data
data test;
   length col1-col200 $200.;
   array ar(*) col:;
   do i=1 to dim(ar);
       ar(i) = "abcdefg";
   end;
   do i=1 to 50000;
      output;
   end;
run;


上記、変数を沢山持つ50000obsのデータセットを作りました。



このデータセットを以下のようにSETした時の処理時間とCPU時間を見てみます。

data out1;
   set test;
run;

ログ
       処理時間           1.95 秒
       ユーザーCPU時間    0.32 秒
       システムCPU時間    1.64 秒



ここで例えば変数col1~col10だけが必要な変数だったとしたら、、

data out1;
   set test (keep=col1-col10);
run;

ログ
       処理時間           0.85 秒
       ユーザーCPU時間    0.03 秒
       システムCPU時間    0.83 秒


SETする時にKEEPやDROPで読み込む変数を絞っておくと、処理時間などが少し短くなります。





また、データステップ中に作成した一時変数や、使わなくなった変数は出力データセットから除いておくと、、

data out1;
   set test ;
   drop col1-col10;
run;


または

data out1 (drop=col1-col10);
   set test ;
run;

サイズが軽量化されて、その後このデータセットを読み込む時の処理時間なども短くなる事が期待できますよね。




このように効率を意識しながら、KEEP・DROPを指定する場所を使い分ける事がポイントです。

まぁ軽いデータだったり、実行に時間がかからないプログラムだったら、ここまで意識してKEEP・DROPを使わなくてもいいと思います。(多用しまくるとプログラムがごちゃっとした見た目になりがちだし)



【DROP・KEEPステートメント】データセットから特定の変数を削除または残す



2018年8月27日月曜日

【効率を意識したプログラム】FULLSTIMERオプション





プログラムをちょっと工夫して、実行時間を少しでも短縮しようっていうシリーズ記事です。



まずは「FULLSTIMERシステムオプション」について。

このオプションを指定すると、データステップやプロシジャを実行した時の処理時間やメモリなどの詳細なパフォーマンスがログに表示されるようになります。




以下は「SAS OnDemand for Academics」での実行結果です。

 options fullstimer;

 proc means data=sashelp.class;
    var height;
 run;


ログ
 NOTE: データセットSASHELP.CLASSから19オブザベーションを読み込みました。
 NOTE: PROCEDURE MEANS処理(合計処理時間):
       処理時間           0.02 秒
       ユーザーCPU時間    0.02 秒
       システムCPU時間    0.00 秒
       メモリ             8707.03k
       OSメモリ           36040.00k
       タイムスタンプ     2018/08/27 午後12:25:17
       ステップ数                        26  スイッチ数  0
       ページフォルト回数                0
       ページリクレーム回数              1973
       ページスワップ回数                0
       自発的コンテキストスイッチ回数    14
       非自発的コンテキストスイッチ回数  0
       ブロック入力操作回数              0
       ブロック出力操作回数              8


うるさいくらい表示されますね。(ていうかSAS OnDemandだとFULLSTIMERがデフォルト設定になってます)
ただ、Windows環境で実行すると表示されるのは8つくらいなので、そんなに多くはないです。



「NOFULLSTIMER」でオフにできます。

 options nofullstimer;




プログラムの書き方によってどのくらいパフォーマンスが変わるんだろうって調べる事があるんで、結構使うオプションです。