Cベース設計 3分間クッキング(5) ――ライフタイム解析
子どものころのこと.親に呼ばれて台所に行くと,「ちょっとこれ食べてごらんなさい」との指示.見るとお皿の上に食べかけのシュークリームがある.食べてみると「飲み込んじゃだめ!」.ちょっとすっぱい.「ふっぽい」と答えると,「これが腐っているシュークリームの味です.覚えておきなさい.たぶん良い菌だと思うけど...」.
いちいちこのようなことをしているとたいへんなので,普通は消費期限を信じるものである.流通している加工食品には,「消費期限」と「賞味期限(品質保持期限)」が設定されている.消費期限は飲食可能な期限を表しており,お弁当やサンドイッチなど,品質が保たれる期間がおおむね5日以内のものに表示される.これに対して,賞味期限は品質が落ちるのが比較的ゆるやかな缶詰やレトルト食品などに使用され,品質が十分に保持されていておいしく食べられる期限を示す.
要冷蔵で期間の短いものは冷蔵庫に,缶詰のように長持ちするものは台所の隅に保管する.缶詰は密閉してから加熱殺菌するので長期保存が可能.普通3~5年といわれるが,英国で100年以上前の缶詰が発見され,食べてみたら平気だったという話もある.
* * *
コンパイラやビヘイビア合成ツールの処理に「ライフタイム解析」というものがある.ライフタイムとは,値が代入された時点で記憶が生まれ,保持した値が参照されて必要がなくなった時点で終了するという概念.これをもとに,ライフタイムが短いものはレジスタでやりくりし,ライフタイムが長くて参照頻度の低いものはスタックに割り当てるなどの詰め込み処理を行う.コンパイラの最適化能力には限界があるので,性能が要求される部分については,コンパイル処理を支援する気持ちでメモリ割り当てを意識しながらコードを記述する場合がある.通常,このような作業はツールが出力するレポートを見ながら進めるが,自分なりの解析を行いたい場合もある.
リスト1は,実行順に従って変数の代入関係を,旧AT&T社のグラフ描画ツール「Graphviz」のdot形式で出力するサンプル(Graphviz は「http://www.research.att.com/sw/tools/graphviz/」からダウンロードできる).出力をdottyというコマンドで読み込むと,図1のようなグラフが得られる.サンプルでは代入と加算のみを実装している.解析対象は31~33行目で,31行目の定数代入では16行目が呼ばれて定数のノードが作られ,そこから13行目が呼ばれてt0,t1のノードが作られる.加算については,20行目が呼ばれて加算を表すノードが作られ,t0,t1からリンクがはられる.
* * *
缶詰置き場のライフタイム解析を行ったところ,もったいなくて食べていないもの,災害に備えていてそのまま忘れたもの,なぜたくさん買ったのか不明なものが見つかった.ココナッツ・ミルク4缶の消費が今月の課題である.
1 #include<iostream>
2 #include<sstream>
3 using namespace std;
4 struct Reg {
5 int value,nd_n; string my_n; static int nd;
6 Reg(string _n):my_n(_n){ value = 0; }
7 void add_nd(Reg &x){ x.nd_n=x.nd++;
8 cout<<"n"<<x.nd_n<<" [label=\""+x.my_n+"\"];\n";
9 }
10 void add_lnk(const Reg &x,const Reg &y){
11 cout<<"n"<<x.nd_n<<"->n"<<y.nd_n<<";\n";
12 }
13 Reg operator=(const Reg &d){ value = d.value;
14 add_nd(*this);add_lnk(d,*this); return(*this);
15 }
16 int operator=(const int &d){ ostringstream ss;
17 ss<<d; Reg t(ss.str());add_nd(t);
18 t.value=d;*this=t;return(value);
19 }
20 Reg operator+(const Reg &d){
21 Reg t("("+my_n+"+"+d.my_n+")");
22 add_nd(t);add_lnk(*this,t);add_lnk(d,t);
23 t.value = value + d.value; return(t);
24 }
25 operator int() const { return(value); }
26 };
27 int Reg::nd = 0;
28 int main() {
29 cout << "digraph test { rankdir=LR\n";
30 Reg t0("t0"),t1("t1"),t2("t2");
31 t0 = 3; t1 = 4;
32 t2=t0+t1;
33 t0 = 5;
34 cout << "}" << endl;
35 }
(本コラムはDESIGN WAVE MAGAZINE 2004年7月号に掲載されました)
◆筆者プロフィール◆
さめしま・まさひろ.高速ディジタル回路のコンサルティングやEDA ツール関係のしごとに従事.