サンプル・プログラムの実行例
サンプル・プログラム
Moore.php | サンプル・プログラム本体。 |
バージョン | 更新日 | 内容 |
---|---|---|
1.4.1 | 2023/06/06 | Apple M2 Ultra追加 |
1.4.0 | 2023/05/05 | グラフにフッタを追加 |
1.3.1 | 2023/01/20 | Z80, MOS 6502, MC68000 など追加 |
1.3.0 | 2023/01/20 | 同じ年のCPUがあったら,トランジスタ数が多い方を採用する. |
1.2.3 | 2023/01/18 | Ryzen 9 7950X, Apple M2 Max 追加 |
解説:準備
解説:マイクロプロセッサ情報
47: //マイクロプロセッサの情報
48: //年 マイクロプロセッサ クロック(Hz) プロセス(m) トランジスタ数
49: // *印のマイクロプロセッサはグラフ上に名称表示
50: $DataCPU =<<< EOT
51: 1971 *4004 7.40E+05 1.00E-05 2.30E+03
52: 1972 8008 5.00E+05 1.00E-05 3.50E+03
53: 1974 *8080 2.00E+06 6.00E-06 4.50E+03
54: 1975 MOS 6502 3.00E+06 8.00E-06 3.51E+03
55: 1976 *Z80 6.00E+06 4.00E-06 8.50E+03
56: 1979 *8086 5.00E+06 3.00E-06 2.90E+04
57: 1980 MC68000 2.00E+07 3.50E-06 6.80E+04
58: 1982 *80286 1.20E+07 1.50E-06 1.34E+05
59: 1985 *80386 1.60E+07 1.50E-06 2.75E+05
60: 1986 R2000 1.50E+07 2.00E-06 1.10E+05
61: 1987 MC68030 5.00E+07 8.00E-07 3.00E+05
62: 1989 *80486 1.60E+08 1.00E-06 1.19E+06
63: 1991 R4000 1.50E+08 1.00E-06 1.20E+06
64: 1993 *Pentium 6.00E+07 8.00E-07 3.10E+06
65: 1994 PowerPC 603 3.00E+08 2.90E-07 2.60E+06
66: 1995 PentiumPro 1.50E+08 6.00E-07 5.50E+06
67: 1997 *PentiumII 2.33E+08 3.50E-07 7.50E+06
68: 1999 PentiumIII 4.50E+08 2.50E-07 9.50E+06
69: 2000 *Pentium4 1.30E+09 1.80E-07 4.20E+07
70: 2005 *PentiumM 9.00E+08 1.30E-07 7.70E+07
71: 2006 CoreDuo 1.07E+09 6.50E-08 1.51E+08
72: 2006 Core2 Duo 1.60E+09 6.50E-08 1.67E+08
73: 2009 *Core i7-860 2.80E+09 4.50E-08 7.74E+08
74: 2011 Core i7-2700K 3.50E+09 3.20E-08 1.16E+09
75: 2012 Core i7-3770K 3.50E+09 2.20E-08 1.40E+09
76: 2014 Core i7-5960X 3.00E+09 2.20E-08 2.60E+09
77: 2016 *Core i7-6950X 3.00E+09 1.40E-08 3.20E+09
78: 2017 Ryzen 7 1800X 4.00E+09 1.40E-08 4.80E+09
79: 2018 A12 Bionic 2.49E+09 7.00E-09 6.90E+09
80: 2020 *Apple M1 3.20E+09 5.00E-09 1.60E+10
81: 2021 Apple M1 Max 3.20E+09 5.00E-09 5.70E+10
82: 2022 Ryzen 9 7950X 5.70E+09 5.00E-09 1.31E+10
83: 2022 Apple M1 Ultra 3.20E+09 5.00E-09 1.14E+11
84: 2022 Apple M2 3.49E+09 5.00E-09 2.00E+10
85: 2023 Apple M2 Max 3.49E+09 5.00E-09 6.70E+10
86: 2023 *Apple M2 Ultra 3.49E+09 5.00E-09 13.40E+10
87:
88: EOT;
129: /**
130: * 指定したCPUデータ文字列を分解し,配列に格納する.
131: * 文字列の行区切りは改行,列区切りはタブ(複数可).
132: * @param string $sour 入力文字列
133: * @param array $dest 結果を格納する2次元配列
134: * @return int 分解した行数
135: */
136: function str2matrix($sour, &$dest) {
137: $arr1 = preg_split("/\n/ui", $sour);
138: $cnt1 = 0;
139: foreach ($arr1 as $val1) {
140: $str = preg_replace("/\n/ui", '', $val1);
141: if (mb_strlen($str) < 1) continue;
142: $arr2 = preg_split("/[\t]+/ui", $str);
143: $cnt2 = 0;
144: foreach ($arr2 as $val2) {
145: $dest[$cnt1][$cnt2] = $val2;
146: $cnt2++;
147: }
148: $cnt1++;
149: }
150:
151: return $cnt1;
152: }
グラフ描画の前に、これを行×列の2次元配列に展開する目的で、ユーザー関数 str2matrix を用意した。他の用途でも使えるだろう。
解説:描画用配列に変換
154: /**
155: * CPUデータ配列をJpGraph描画用配列に変換する.
156: * 同じ年のCPUがあったら,トランジスタ数が多い方を採用する.
157: * @param array $matrix CPUデータ配列
158: * @param array $items 描画用配列
159: * @return array(最小年,最大年) 描画用配列
160: */
161: function matrix2items($matrix, &$items) {
162: //データの分解
163: $year_min = 99999;
164: $year_max = 0;
165: foreach ($matrix as $val) {
166: $year = (int)$val[0];
167: if ($year < $year_min) $year_min = $year;
168: if ($year > $year_max) $year_max = $year;
169: //同じ年のCPUがあったら,トランジスタ数が多い方を採用する.
170: if (isset($items[$year])) {
171: if ((float)$val[4] > $items[$year]['transistors']) {
172: $items[$year]['CPU'] = (string)$val[1];
173: $items[$year]['clock'] = (float)$val[2];
174: $items[$year]['process'] = (float)$val[3];
175: $items[$year]['transistors'] = (float)$val[4];
176: }
177: //同じ年のCPUがなければ,そのまま採用する.
178: } else {
179: $items[$year]['CPU'] = (string)$val[1];
180: $items[$year]['clock'] = (float)$val[2];
181: $items[$year]['process'] = (float)$val[3];
182: $items[$year]['transistors'] = (float)$val[4];
183: }
184: }
185:
186: return array($year_min, $year_max);
187: }
そこで、ユーザー関数 str2matrix で変換したデータを、さらに、西暦年×列名という2次元配列に変換するためのユーザー関数 matrix2items を用意した。
解説:グラフを描く
209: /**
210: * 指定した描画用データ配列によりJpGraphに対数グラフを描画する.
211: * @param array $items 描画用データ配列
212: * @param int $year_min 最小年
213: * @param int $year_max 最大年
214: * @return object graphオブジェクト
215: */
216: function drawGraph($items, $year_min, $year_max) {
217: $plotdata = array();
218:
219: //横軸(西暦年)の作成
220: $x0 = floor($year_min / 5) * 5;
221: $x1 = ceil($year_max / 5) * 5;
222: $i = 1;
223: for ($year = $x0; $year <= $x1; $year++) {
224: $data_x[$year - $x0] = $year;
225: }
226:
227: //グラフ描画処理開始
228: $graph = new Graph(600, 500, 'auto');
229: $graph->SetScale('linlog'); //X軸:整数,Y軸:対数
230: $graph->SetBackgroundGradient('#FFFFCC','#FFFFCC', GRAD_HOR, BGRAD_MARGIN);
231:
232: //タイトル、凡例などの設定
233: $graph->img->SetImgFormat('png');
234: $graph->img->SetMargin(60, 60, 20, 40);
235: $graph->title->SetFont(FF_PGOTHIC, FS_NORMAL, 16);
236: $graph->title->Set('ムーアの法則');
237: $graph->xaxis->title->SetFont(FF_PGOTHIC);
238: $graph->xaxis->SetTitle('年','center');
239: $graph->xaxis->SetTickLabels($data_x);
240: $graph->xaxis->SetTextTickInterval(5);
241: $graph->xaxis->SetTextLabelInterval(2);
242: $graph->yaxis->title->SetFont(FF_PGOTHIC);
243: $graph->yaxis->title->Set('トランジスタ数');
244: $graph->yaxis->SetTitleMargin(40);
245: //フッタを設定する.
246: $graph->footer->right->SetFont(FF_PGOTHIC, FS_NORMAL, 10);
247: $graph->footer->right->Set('produced by JpGraph');
248:
249: //プロット配列を作成
250: for ($year = $x0; $year <= $x1; $year++) {
251: $data_y1[$year - $x0] = isset($items[$year]) ? (double)$items[$year]['transistors'] : '-';
252: $data_y2[$year - $x0] = 2.30E+03 * pow(2, ($year - $year_min) / (double)(18 / 12));
253: $data_y3[$year - $x0] = 2.30E+03 * pow(2, ($year - $year_min) / (double)(24 / 12));
254: }
255:
256: //ムーアの法則:18ヶ月ごとに2倍
257: $plotdata = new LinePlot($data_y2);
258: $graph->Add($plotdata);
259: $plotdata->SetWeight(2); //太さ
260: $plotdata->SetColor('royalblue'); //色
261: $plotdata->SetLegend('18ヶ月ごとに2倍'); //凡例
262:
263: //ムーアの法則:24ヶ月ごとに2倍
264: $plotdata = new LinePlot($data_y3);
265: $graph->Add($plotdata);
266: $plotdata->SetWeight(2); //太さ
267: $plotdata->SetColor('green'); //色
268: $plotdata->SetLegend('24ヶ月ごとに2倍'); //凡例
269:
270: //マイクロプロセッサ
271: $plotdata = new LinePlot($data_y1);
272: $graph->Add($plotdata);
273: $plotdata->SetColor('deeppink'); //色
274: $plotdata->SetWeight(2); //太さ
275: $plotdata->mark->SetTYPE(MARK_DIAMOND); //プロット記号
276: $plotdata->value->SetFormatCallback('CPUname');
277: $plotdata->value->show();
278: $plotdata->SetLegend('マイクロプロセッサ'); //凡例
279:
280: //凡例
281: $graph->legend->SetFont(FF_PGOTHIC); //フォント
282: $graph->legend->SetColumns(1); //表示列数
283: $graph->legend->SetPos(0.12, 0.9, 'right', 'bottom'); //位置
284:
285: return $graph;
286: }
まず、X軸を用意する。西暦年を5年刻みで、最小年と最大年を設定する。
次に、グラフ描画処理の開始とタイトル、凡例などの設定を行う。このあたりは「インフルエンザ患者数のグラフを作る」とほぼ同じである。
続けて、プロット用の配列を3つ $data_y1, $data_y2, $data_y3 作る。
配列 $data_y1 には、マイクロプロセッサのトランジスタ数を代入する。最初に与えられたデータにない年は、'-' を代入することで、折れ線グラフを自動的に繋げてくれる。ここで空文字 '' を代入すると、グラフは途切れる。
1971年(昭和46年)に発売された4004のトランジスタ数を基準に、18ヶ月ごとに2倍にした値は配列 $data_y2 に、24ヶ月ごとに2倍にした値は配列 $data_y3 に、それぞれ代入する。2のべき乗を計算するために組み込み関数 pow を用いている。
ちなみに、当初のムーアの法則では「18ヶ月ごと」だったが、その後のトランジスタ数の増加が減速し、「24ヶ月」に訂正したという経緯がある。
最後に、プロット用の配列を描画していく。
配列 $data_y1 を描く際に、$plotdata->value->SetFormatCallback を使ってデータポイントにマイクロプロセッサ名を表示させている。本来、データポイントにはY値(ここではトランジスタ数)が表示されるのだが、コールバックされるユーザー関数 CPUname において受け取ったトランジスタとデータ表を照合し、マイクロプロセッサ名を返すようにしていることで、グラフ上にマイクロプロセッサ名が表示されるという仕組みである。
すべてのマイクロプロセッサ名が表示されると重なって見にくくなるので、冒頭にアスタリスクが付いているマイクロプロセッサ名だけを表示するようにしている。
解説:画面出力
コマンドライン・オプション img が指定された場合は、出力データをimgタグの中に画像データを埋め込むための文字列を生成する。詳しくは、「PHPでTrueTypeフォントを利用する(その2)」-「解説:画像をHTMLコンテンツに埋め込む」を参照のこと。
参考サイト
- JpGraph公式サイト
- アシアル株式会社
- PHPとJpGraphで人口ピラミッドを表示する:ぱふぅ家のホームページ
- インフルエンザ患者数のグラフを作る:ぱふぅ家のホームページ
- Transistor count:Wikipedia
- 2021年、ムーアの法則が崩れる?:ITmedia
- ムーアの法則の終焉:bibble-babble
- 「ムーアの法則」と「パラダイス鎖国」:地図屋の視点
- ソフトウェアもムーアの法則で巨大化する:プログラマの思索
- ムーアの法則は2014年で終焉を迎える …らしい。:ひでのブログ
(2023年6月6日)Apple M2 Ultra 追加
(2023年5月5日)グラフにフッタを追加した。
(2023年1月20日)同じ年のCPUがあったら,トランジスタ数が多い方を採用する.Z80, MOS 6502, MC68000 など追加.
(2023年1月18日)Ryzen 9 7950X, Apple M2 Max 追加