ポスト・ヒューマン誕生

 

はい。レイ・カーツワイル氏のポスト・ヒューマン誕生をもりもり読んでおります。

あの、俳優のウィル・スミス氏が枕元に置いておかないと落ち着いて眠れないと噂される本でございます。

とても内容が濃い上に辞書並の厚さがあって読み応えがあります。読んでいて頭が良くなっていってる気がするのは攻殻機動隊マスター・キートン以来であります。

科学者の悲観主義

氏は「たいてい、目の前にある問題の難しさや複雑な細部に気を取られすぎていて、自分の研究がもつ長期的意義を見失ったり、研究分野をより広い視野で捉えることを忘れてしまったりしがちだ。」と言う。

ともにひとびとの間に、指数関数的成長収穫加速の法則が頭に入っていないからだと警告する。

また、「今日のあるひとつの傾向から導かれる変化にだけ注目し、他のことがらはなにひとつとして変わらない、としてしまうことだ。その格好な例が、寿命が伸びすぎると、人口が過剰になり、限りある資源が枯渇して生活が成り立たなくなる。と懸念されていることだ。この場合は、ナノテクノロジーや強いAIを用いて、その分に見合った大きな富を算出できることが忘れられている。」と述べている。

技術の進歩による弊害が出る頃には、他の技術の進歩の応用によってかんたんに解決できるとしている。

指数関数的成長

この本を貫く思想がこちらです。

指数関数的成長とは、初期は緩やかに進化し技術が確立すると急速に進化すること。

様々な人がこの指数関数的成長を見落としていて、進化のペースを遅く評価しすぎてしまっているとのこと。

氏、曰く人類の進歩は10年毎に2倍になっているとのこと。

収穫加速の法則

氏の提唱する発明と進歩に関する法則。

一つの重要な発明は他の発明と結びつき、次の重要な発明の登場までの期間を短縮し、イノベーションの速度を加速することにより、科学技術は直線グラフ的ではなく指数関数的に進歩するという法則のこと。

ムーアの法則

インテル社のゴードン・ムーア名誉会長が1965年に予測した、半導体の集積度は2年で倍増するという法則。

予測から52年が経過した、2017年現在もインテル社はこの法則が健在であると主張している。

原子データストレージ

オクラホマ大学の研究チームは、19個の水素原子を含む1個の分子にある陽子間の磁気相互作用の中に、1024ビットの情報を保存することに成功した。

2017年には、IBMが単一の原子にデータを読み書きすることに成功した

人間の脳のシミュレート

氏は、人間レベルの知能を10^16 cpsのコンピューティングと10^13ビットのメモリがあれば再現可能としています。

強いAI

コンピュータが強いAIと呼ばれるのは、人間の知能に迫るようになるか、人間の仕事をこなせるようになるか、幅広い知識と何らかの自意識を持つようになったときである。

ちなみに、やや疑問を持つ声もあるが、2014年にチューリングテストに合格する人口知能が登場している

 

あと、人間の寿命に関しては他の人のまとめ見て下さい。

いやーすごい本だ。

「生産消費者」の時代

アルビン・トフラーの「生産消費者」の時代

を読みました。

以前に言及したジェレミー・リフキン氏の「限界費用ゼロ社会」と同様に未来の社会についての予測をした本です。

トフラーに関しては日本語のWikiでも概要を知ることができます

この本では、トフラーと評論家の田中直毅氏との対談形式で話が進んでおり、「第三の波」や「富の未来」と比べてだいぶ読みやすく情報もまとまっています。

第三の波

トフラーが提唱する、人類が経験してきた大変革のこと。

第一の波は1万年前の「農業革命」で狩猟や採集に頼っていた人類の生活を根底から覆した。

第二の波は18世紀(西暦1701年から1800年)に起きた「産業革命」で工業化による大量生産の時代が開始した。

第三の波は1990年代後半から現在にまで続いているコンピュータとインターネットがもたらした「情報革命」の事で、知識に基づく経済社会への移行をし始めている。

生活スタイルの違い

第一の波で登場した、農業中心の生活スタイルは、集団の単位は家族。時間に縛られることはありません。

第二の波で登場した、工業中心の生活スタイルは、集団の単位は会社や工場。時間を守り会社や工場のルールに従う必要がある。

第三の波で登場した、情報中心の生活スタイルは、集団の単位は個人やコミュニティ。時間の制限や細かなルールは創造性を妨げるため存在しない。

組織形態とそのスピード

企業は時速100kmでトップを走る。創造力豊かな個人とコミュニティをいくつも内包するGoogleやIBM、Amazon、マイクロソフトといった企業は、新しい技術や市場の変化に敏感に対応し、製品や組織内部を即座に変えて対応することができる。

NGOやNPOの社会団体は時速90kmで小回りがきくネットワークを活かして、俊敏に対応することができる。

家族は時速60kmでリモートワークなどの新しいライフスタイルの登場でその機能は急速に様変わりしている。

労働組合は時速30kmで創造力が最重要視される仕事が多くなる中で役割を失いつつある。

官僚機構は時速25kmで工業中心の社会ではうまく機能していましたが情報社会ではただの害悪

公教育制度は時速10km

国際的統治機関は時速5km

政治の構造は時速3km

法律は時速1km

と続きます。これらはそのスピードの致命的な遅さから誰にも相手をされず既に形骸化している。

特に、時速30kmより遅い組織形態に関しては、その組織形態が本当に必要なのかを含めて、抜本的に見直す時期にきている。

世界から孤立する中東

イスラム教徒全体のレベルでシーア派とスンニ派が対立し、

次のレベルで国家間の対立

局地的に武装勢力、軍閥、テロリストが台頭する中東はアメリカでさえもすぐに解決ができない国際的な難問。

プロシューマー

OpenAimの方に書いたので割愛

 

新サイトの構想がいくつか湧いてきたのでとりあえずティザーでも作るかな。

 

限界費用ゼロ社会

限界費用ゼロ社会 〈モノのインターネット〉と共有型経済の台頭 ジェレミー・リフキン  (著), 柴田裕之 (翻訳)

を読んでます。結構、目から鱗が落ちる本なのですが、覚えておきたいことをここに残しておきます。

共有型経済の台頭

資本主義経済の次にくる経済体制。英語でいうところのSharing Economy.

なんと総務省のページに解説がある

「シェアリング・エコノミー」とは、典型的には個人が保有する遊休資産(スキルのような無形のものも含む)の貸出しを仲介するサービスであり、貸主は遊休資産の活用による収入、借主は所有することなく利用ができるというメリットがある。貸し借りが成立するためには信頼関係の担保が必要であるが、そのためにソーシャルメディアの特性である情報交換に基づく緩やかなコミュニティの機能を活用することができる。シェアリング・エコノミーはシリコンバレーを起点にグローバルに成長してきた。PwCによると、2013年に約150億ドルの市場規模が2025年には約3,350億ドル規模に成長する見込みである

え?なんか妙に限定的じゃないか総務省さん?

私は「シェアリングエコノミー」とは

物との関わりが「保有」から「アクセス」に変わった世界

だと思うのよ。

つまり、自動車を「購入」する時代は収束しつつあって、より効率的な「カーシェアリング」が選ばれる時代がゆるやかに到着しつつある。

Iot

IoTとは?|IoT:Internet of Things(モノのインターネット)とは、従来は主にパソコンやサーバー、プリンタ等のIT関連機器が接続されていたインターネットにそれ以外の様々なモノを接続することを意味します。読み方はアイオーティーです。

まあ、この教科書的な用語解説は置いておいて。

私は「Iot」とは

映像・光・音・温度等のセンサーとネットワーク機器が既存の家電に搭載され情報が可視化され蓄積できるようになること

だと思うのよ。

例えば冷蔵庫の中にカメラとwifiが搭載されて買い物中に冷蔵庫の中身をスマホから見れるようになって、ついでに賞味期限切れの食品があることを教えてくれるようなこと。

自動販売機や電飾広告にセンサーとwifiが搭載されて、人が周りに居ない時は電源がオフになったり、節電モードになって効率的に運用ができるようになること。

そして、「シェアリングエコノミー (人と物との関わり方が所有からアクセスへ変わる世界)」はIotによって、色々なタイミングで物が誰によって使用されているのか監視することによって現実化させることができる。

限界費用がゼロになる時代の到来

げんかい‐ひよう【限界費用】生産量の増加分一単位あたりの総費用の増加分。限界生産費。マージナルコスト。MC(marginal cost)

限界費用がゼロになるということは生産量に対してかかる経費がゼロになるということ。つまり生産し放題になる時代。

グリーンエネルギー

グリーンエネルギーとは、太陽光や風力、バイオマス(生物資源)、地熱、天然ガスといった自然エネルギー源です。

使用することで自然環境への負担が大きく、採掘に莫大なコストがかかる化石燃料の時代は終わり、ほぼ無尽蔵のグリーンエネルギーが限界費用ゼロの時代を支えることになります。

日本のどの家でも100万円前後で導入でき、10年ほどで償却ができるソーラーパネルを設置することで各家庭の電気代は0円になります。

また、米国ではGoogle主導のもと、広域無料Wifiの設置が一部地域で進んでいます。

プロシューマーの台頭

プロシューマーとは、consumer(消費者)とproducer(生産者)を組み合わせた造語で、製品の企画・開発に携わる消費者という意味。未来学者のアルビン・トフラー氏が著書『第三の波』で予見した新しいスタイルの消費者。多様化した消費者のニーズに応えるために、企業が消費者の意見を直接取り入れる形で、消費者が商品の企画・開発に関わるようになってきている。

既に、ソフトウェア業界では、ユーザがテストに参加し、そのデータや意見を基に改善点や開発すべき項目を決める手法が王道になってきている。消費者と生産者の垣根がなくなりつつある。

学校教育の時代錯誤

小中高の教育が輩出を目指す理想的な人材は、寡黙な工場労働者である。狭い室内で他の人と同じ工程を文句を言わず行える人材である。

現在、そのような人材を受け入れる町工場がいくつあるだろうか?学校教育は需要の存在しない人材を今日もなんの疑いもなく教育をしている。この無駄を私達が止めなければならない。

 

最後に、私達は「限界費用ゼロ社会と、より平等主義的で豊かで、生態学的に持続可能な時代へと、世界を導くことに十分貢献できる。」と信じております。

達人に学ぶSQL

 

自分の書くSQLがなんだか効率が悪い気がしてきて勉強したくなり、初めてのSQL達人に学ぶSQL徹底指南書を入手して学習してます。

せっかくなので重要そうなところをここにまとめておきます。使ってるSQLはMySqlでCloud9でテスト環境を作成してテストしてます。

■サブクエリ

・情報を取得するための、一時テーブルを生成する。
・一時テーブルは処理が終わったら破棄される。

Cloud9のMySQLにログインします。

masasikatano:~/workspace $ mysql -u root
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 58
Server version: 5.5.54-0ubuntu0.14.04.1 (Ubuntu)

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

それからテストテーブルの作成。

mysql> use c9
Database changed
mysql> CREATE TABLE IF NOT EXISTS users (
    ->   ID int(11) unsigned AUTO_INCREMENT NOT NULL,
    ->   score int(11) NOT NULL default '0',
    ->   name text NOT NULL,
    ->   sex enum('male', 'female') NOT NULL default 'male',
    ->   updated_at TIMESTAMP NOT NULL,
    ->   created_at TIMESTAMP NOT NULL,
    ->   deleted_at TIMESTAMP NULL,
    ->   PRIMARY KEY (ID)
    -> );
Query OK, 0 rows affected (0.02 sec)

mysql> desc users;
+------------+-----------------------+------+-----+---------------------+-----------------------------+
| Field      | Type                  | Null | Key | Default             | Extra                       |
+------------+-----------------------+------+-----+---------------------+-----------------------------+
| ID         | int(11) unsigned      | NO   | PRI | NULL                | auto_increment              |
| score      | int(11)               | NO   |     | 0                   |                             |
| name       | text                  | NO   |     | NULL                |                             |
| sex        | enum('male','female') | NO   |     | male                |                             |
| updated_at | timestamp             | NO   |     | CURRENT_TIMESTAMP   | on update CURRENT_TIMESTAMP |
| created_at | timestamp             | NO   |     | 0000-00-00 00:00:00 |                             |
| deleted_at | timestamp             | YES  |     | NULL                |                             |
+------------+-----------------------+------+-----+---------------------+-----------------------------+
7 rows in set (0.00 sec)

テストデータを挿入します。

mysql> INSERT INTO users (score,name,sex,updated_at,created_at,deleted_at) VALUES
    -> (10,'masasikatano','male','2017-1-11 00:00:00','2017-6-11 00:00:00',null),
    -> (100,'concernedfennel','female','2017-1-12 00:00:00','2017-7-12 00:00:00',null),
    -> (100,'juicysubstr','male','2017-1-13 00:00:00','2017-3-13 00:00:00',null),
    -> (110,'buttheadbaron','female','2017-1-14 00:00:00','2017-4-14 00:00:00',null),
    -> (110,'hauntcyclase','female','2017-1-15 00:00:00','2017-1-15 00:00:00',null),
    -> (130,'profileasked','male','2017-1-16 00:00:00','2017-1-16 00:00:00',null),
    -> (145,'jaguarracer','female','2017-1-17 00:00:00','2017-5-21 00:00:00',null),
    -> (160,'boorishdisplay','male','2017-1-18 00:00:00','2017-3-21 00:00:00',null),
    -> (200,'baseballsecure','female','2017-1-19 00:00:00','2017-2-19 00:00:00','2017-3-20 00:00:00'),
    -> (10,'woundmille','male','2017-2-21 00:00:00','2017-2-21 00:00:00','2017-2-23 00:00:00'),
    -> (-10,'hollandaiseoncology','male','2017-3-11 00:00:00','2017-3-11 00:00:00',null),
    -> (-20,'clotpolestringed','male','2017-4-10 00:00:00','2017-4-11 00:00:00',null),
    -> (-30,'listcampus','female','2017-4-11 00:00:00','2017-4-11 00:00:00','2017-7-10 00:00:00'),
    -> (-100,'teammatemillwright','female','2017-5-11 00:00:00','2017-5-11 00:00:00',null),
    -> (0,'mongoosehalting','male','2017-6-11 00:00:00','2017-6-11 00:00:00',null),
    -> (0,'gashbam','female','2017-7-11 00:00:00','2017-7-11 00:00:00',null)
    -> ;
Query OK, 16 rows affected (0.00 sec)
Records: 16  Duplicates: 0  Warnings: 0

mysql> select * from users;
+----+-------+---------------------+--------+---------------------+---------------------+---------------------+
| ID | score | name                | sex    | updated_at          | created_at          | deleted_at          |
+----+-------+---------------------+--------+---------------------+---------------------+---------------------+
|  1 |    10 | masasikatano        | male   | 2017-01-11 00:00:00 | 2017-06-11 00:00:00 | NULL                |
|  2 |   100 | concernedfennel     | female | 2017-01-12 00:00:00 | 2017-07-12 00:00:00 | NULL                |
|  3 |   100 | juicysubstr         | male   | 2017-01-13 00:00:00 | 2017-03-13 00:00:00 | NULL                |
|  4 |   110 | buttheadbaron       | female | 2017-01-14 00:00:00 | 2017-04-14 00:00:00 | NULL                |
|  5 |   110 | hauntcyclase        | female | 2017-01-15 00:00:00 | 2017-01-15 00:00:00 | NULL                |
|  6 |   130 | profileasked        | male   | 2017-01-16 00:00:00 | 2017-01-16 00:00:00 | NULL                |
|  7 |   145 | jaguarracer         | female | 2017-01-17 00:00:00 | 2017-05-21 00:00:00 | NULL                |
|  8 |   160 | boorishdisplay      | male   | 2017-01-18 00:00:00 | 2017-03-21 00:00:00 | NULL                |
|  9 |   200 | baseballsecure      | female | 2017-01-19 00:00:00 | 2017-02-19 00:00:00 | 2017-03-20 00:00:00 |
| 10 |    10 | woundmille          | male   | 2017-02-21 00:00:00 | 2017-02-21 00:00:00 | 2017-02-23 00:00:00 |
| 11 |   -10 | hollandaiseoncology | male   | 2017-03-11 00:00:00 | 2017-03-11 00:00:00 | NULL                |
| 12 |   -20 | clotpolestringed    | male   | 2017-04-10 00:00:00 | 2017-04-11 00:00:00 | NULL                |
| 13 |   -30 | listcampus          | female | 2017-04-11 00:00:00 | 2017-04-11 00:00:00 | 2017-07-10 00:00:00 |
| 14 |  -100 | teammatemillwright  | female | 2017-05-11 00:00:00 | 2017-05-11 00:00:00 | NULL                |
| 15 |     0 | mongoosehalting     | male   | 2017-06-11 00:00:00 | 2017-06-11 00:00:00 | NULL                |
| 16 |     0 | gashbam             | female | 2017-07-11 00:00:00 | 2017-07-11 00:00:00 | NULL                |
+----+-------+---------------------+--------+---------------------+---------------------+---------------------+
16 rows in set (0.00 sec)

サブクエリでscoreが100以上のmaleのnameを抽出

mysql> SELECT U.name 
    ->   FROM
    ->        ( 
    ->          SELECT * 
    ->          FROM users 
    ->          WHERE score >= 100
    ->        ) 
    ->        AS U
    ->  WHERE sex='male';
+----------------+
| name           |
+----------------+
| juicysubstr    |
| profileasked   |
| boorishdisplay |
+----------------+
3 rows in set (0.00 sec)

合ってそうです。

LaravelのEloquentでのサブクエリの使い方は割愛

■Case式

・CASE式を使用することで、SQL中で条件制御を行うことが出来ます。

mysql> SELECT id,name,sex
    ->       ,CASE sex
    ->          WHEN 'male' THEN '男'
    ->          WHEN 'female' THEN '女'
    ->          ELSE 'another'
    ->        END 性別
    -> FROM   users;
+----+---------------------+--------+--------+
| id | name                | sex    | 性別   |
+----+---------------------+--------+--------+
|  1 | masasikatano        | male   | 男     |
|  2 | concernedfennel     | female | 女     |
|  3 | juicysubstr         | male   | 男     |
|  4 | buttheadbaron       | female | 女     |
|  5 | hauntcyclase        | female | 女     |
|  6 | profileasked        | male   | 男     |
|  7 | jaguarracer         | female | 女     |
|  8 | boorishdisplay      | male   | 男     |
|  9 | baseballsecure      | female | 女     |
| 10 | woundmille          | male   | 男     |
| 11 | hollandaiseoncology | male   | 男     |
| 12 | clotpolestringed    | male   | 男     |
| 13 | listcampus          | female | 女     |
| 14 | teammatemillwright  | female | 女     |
| 15 | mongoosehalting     | male   | 男     |
| 16 | gashbam             | female | 女     |
+----+---------------------+--------+--------+
16 rows in set (0.00 sec)

■変数

・あるステートメント内のユーザー定義変数に値を格納し、あとから別のステートメントでこれを参照できます。

mysql> SET @t1=1, @t2=2, @t3:=4;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @t1, @t2, @t3, @t4 := @t1+@t2+@t3;
+------+------+------+--------------------+
| @t1  | @t2  | @t3  | @t4 := @t1+@t2+@t3 |
+------+------+------+--------------------+
|    1 |    2 |    4 |                  7 |
+------+------+------+--------------------+
1 row in set (0.00 sec)

■OLAP

・OLAP関数というのは,OLAP(OnLine Analytical Processing)という名前のとおり,データベースを使ってリアルタイムに分析を行う処理に対応した関数のことです。DWH(Data Ware House)とかBI(Business Intelligence)の分野でよく利用されます。

・MySQLには未実装なものが多い(MariaDBにもない)

ほげえ・・

↑の変数を利用する方法があるみたいなのでやってみます。

mysql> SET @rank = 0;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT (@rank := @rank + 1) AS rank, 
    -> id ,score,name 
    -> FROM users
    -> ORDER BY score DESC;
+------+----+-------+---------------------+
| rank | id | score | name                |
+------+----+-------+---------------------+
|    1 |  9 |   200 | baseballsecure      |
|    2 |  8 |   160 | boorishdisplay      |
|    3 |  7 |   145 | jaguarracer         |
|    4 |  6 |   130 | profileasked        |
|    5 |  4 |   110 | buttheadbaron       |
|    6 |  5 |   110 | hauntcyclase        |
|    7 |  2 |   100 | concernedfennel     |
|    8 |  3 |   100 | juicysubstr         |
|    9 |  1 |    10 | masasikatano        |
|   10 | 10 |    10 | woundmille          |
|   11 | 15 |     0 | mongoosehalting     |
|   12 | 16 |     0 | gashbam             |
|   13 | 11 |   -10 | hollandaiseoncology |
|   14 | 12 |   -20 | clotpolestringed    |
|   15 | 13 |   -30 | listcampus          |
|   16 | 14 |  -100 | teammatemillwright  |
+------+----+-------+---------------------+
16 rows in set (0.00 sec)

うおお超便利

ついでに、Laravel EloquentでMySQLのユーザ定義変数を使う方法もあるみたいです。

■Having句

・HAVING句はWHERE句と異なりGROUP BY句によってグループ化が行われたデータに対して条件を指定してデータを絞り込む場合に使用します。

↓Havingを使用しない例

mysql> SELECT sex, AVG(score)
    -> FROM users
    -> GROUP BY sex ;
+--------+------------+
| sex    | AVG(score) |
+--------+------------+
| male   |    47.5000 |
| female |    66.8750 |
+--------+------------+
2 rows in set (0.00 sec)

↓Havingを使用して絞込を加えた例

mysql> SELECT sex, AVG(score)
    -> FROM users
    -> GROUP BY sex 
    -> HAVING AVG(score) > 50;
+--------+------------+
| sex    | AVG(score) |
+--------+------------+
| female |    66.8750 |
+--------+------------+
1 row in set (0.00 sec)

便利だ。

Cloud9でMysqlのスロークエリの確認

Cloud9環境でのMySqlのスロークエリの確認方法です。

以下ターミナルのBashからログファイルを作成しておきます。

masasikatano:~/workspace (master) $ touch slow_query.log
masasikatano:~/workspace (master) $ chmod 777 slow_query.log

MySqlからスロークエリ用の設定をします。

masasikatano:~/workspace (master) $ mysql -u root -pXXXXXXXXXX
mysql> set global slow_query_log=1;
mysql> set global long_query_time=1;
mysql> set global log_queries_not_using_indexes=1;
mysql> set global slow_query_log_file ='/home/ubuntu/workspace/slow_query.log';

これで、workspace上のslow_query.logからスローなクエリが確認できます。

Indexを追加するときと削除するときはこんなかんじ

 

# 追加
alter table users add index users_name_index (name);

# 削除
# ALTER TABLE users DROP INDEX users_name_index;

CODE COMPLETEを読みました – コードチューニング

前回と同様、コードコンプリート―完全なプログラミングを目指して (Microsoft PRESS) のまとめです。今回はコードチューニングに関して。

20年前の本なのですがコンピュータに関してのお約束というか基礎的な部分はほとんど変わっていないのでほとんどそのまま実用できると思います。

ループとスイッチング

for_if_test.php

<?php

print("悪い例の処理<br />");
$baseMemoryUsage = memory_get_usage();
$baseTime = microtime(true);

// 0 〜 10000000までを足す処理をする
$flag  = true; // 計算するかどうかのフラグ
$sum = 0;
for ($i = 0; $i < 10000000; $i++) {
    if($flag){
        $sum += $i;
    }
}

$maxMemoryUsage = (memory_get_peak_usage() - $baseMemoryUsage) / (1024 * 1024);
$processTime = microtime(true) - $baseTime;

printf("Max Memory Usage : %.3f [MB]<br />", $maxMemoryUsage);
printf("Process Time : %.2f [s]<br />", $processTime);
printf("Calculation result : %d <br />", $sum);


print("良い例の処理<br />");
$baseMemoryUsage = memory_get_usage();
$baseTime = microtime(true);

// 0 〜 10000000までを足す処理をする
$flag  = true; // 計算するかどうかのフラグ
if($flag){
    $sum = 0;
    for ($i = 0; $i < 10000000; $i++) {
        $sum += $i;
    }
}

$maxMemoryUsage = (memory_get_peak_usage() - $baseMemoryUsage) / (1024 * 1024);
$processTime = microtime(true) - $baseTime;

printf("Max Memory Usage : %.3f [MB]<br />", $maxMemoryUsage);
printf("Process Time : %.2f [s]<br />", $processTime);
printf("Calculation result : %d <br />", $sum);

これをCloud9のPHP環境で実行してみると、こんなかんじになります。

悪い例の処理
Max Memory Usage : 0.035 [MB]
Process Time : 1.88 [s]
Calculation result : 49999995000000
良い例の処理
Max Memory Usage : 0.034 [MB]
Process Time : 1.45 [s]
Calculation result : 49999995000000

ループと直接関係のない処理は、ループの外に積極的に出した方が高速化します。

ループの展開

for_unrolling_test.php

<?php

print("ループ展開前の処理<br />");
$baseMemoryUsage = memory_get_usage();
$baseTime = microtime(true);

// 0 〜 10000000までを足す処理をする
$sum = 0;
for ($i = 0; $i < 10000000; $i++) {
    $sum += $i;
}

$maxMemoryUsage = (memory_get_peak_usage() - $baseMemoryUsage) / (1024 * 1024);
$processTime = microtime(true) - $baseTime;

printf("Max Memory Usage : %.3f [MB]<br />", $maxMemoryUsage);
printf("Process Time : %.2f [s]<br />", $processTime);
printf("Calculation result : %d <br />", $sum);


print("ループ展開後の処理<br />");
$baseMemoryUsage = memory_get_usage();
$baseTime = microtime(true);

// 0 〜 10000000までを足す処理をする
$sum = 0;
for ($i = 0; $i < 10000000; $i+=5) {
    $sum += $i;
    $sum += $i + 1;
    $sum += $i + 2;
    $sum += $i + 3;
    $sum += $i + 4;
}

$maxMemoryUsage = (memory_get_peak_usage() - $baseMemoryUsage) / (1024 * 1024);
$processTime = microtime(true) - $baseTime;

printf("Max Memory Usage : %.3f [MB]<br />", $maxMemoryUsage);
printf("Process Time : %.2f [s]<br />", $processTime);
printf("Calculation result : %d <br />", $sum);

結果はこんなかんじです。

ループ展開前の処理
Max Memory Usage : 0.035 [MB]
Process Time : 4.51 [s]
Calculation result : 49999995000000 
ループ展開後の処理
Max Memory Usage : 0.034 [MB]
Process Time : 2.22 [s]
Calculation result : 49999995000000 

うおーループの展開超はええ

高速な言語で書き直す

PHPよりもC、Cよりもアセンブラ言語のように、ベースとなっている高速な言語を使用することでパフォーマンスが改善します。

この本ではPascalからアセンブラで書き直す例をあげているのですが、同じようにPHPからCを呼び出す方法をやってみます。

<?php

print("PHPでの処理<br />");
$baseMemoryUsage = memory_get_usage();
$baseTime = microtime(true);

// 0 〜 10000000までを足す処理をする
$sum = 0;
for ($i = 0; $i < 10000000; $i++) {
    $sum += $i;
}

$maxMemoryUsage = (memory_get_peak_usage() - $baseMemoryUsage) / (1024 * 1024);
$processTime = microtime(true) - $baseTime;

printf("Calculation result : %d <br />", $sum);
printf("Max Memory Usage : %.3f [MB]<br />", $maxMemoryUsage);
printf("Process Time : %.2f [s]<br />", $processTime);


print("PHPからC言語を呼び出しての処理<br />");
$baseMemoryUsage = memory_get_usage();
$baseTime = microtime(true);

$cmd = '/home/ubuntu/workspace/exec_test';
echo exec($cmd);

$maxMemoryUsage = (memory_get_peak_usage() - $baseMemoryUsage) / (1024 * 1024);
$processTime = microtime(true) - $baseTime;

printf("Max Memory Usage : %.3f [MB]<br />", $maxMemoryUsage);
printf("Process Time : %.2f [s]<br />", $processTime);

exec_test.c

#include <stdio.h>

int main(void) {

    int i = 0;
    long sum = 0;
    /* 0 〜 10000000までを足す処理をする */
    for (i = 0; i < 10000000; i++) {
        sum += i;
    }

    printf("Calculation result : %ld <br />", sum);

    return 0;
}

Cはコンパイルしておき、実行します。結果は、

PHPでの処理
Calculation result : 49999995000000
Max Memory Usage : 0.032 [MB]
Process Time : 1.52 [s]
PHPからC言語を呼び出しての処理
Calculation result : 49999995000000
Max Memory Usage : 0.031 [MB]
Process Time : 0.03 [s]

C言語がとんでもなく早いことがよくわかりました。

CODE COMPLETEを読みました – アナロジー

コードコンプリート―完全なプログラミングを目指して (Microsoft PRESS) を読んでみました。

かなり昔の本(初版1994年)で辞書くらい分厚いのもあってしばらく本棚に飾ってあったんですが読んでみたら現在でも使える内容満載のとっても良い本でした。おすすめ。

初っ端第一部からガツンときたのはアナロジーの話です。アナロジーとは例えばこんなの

抽象的でイメージしずらい数学や物理化学の現象をイメージしやすい身近なもので置き換えて理解しやすくすることです。

この本では以下の例え話をしています。

ソフトウェア ≒ 建築

仕様 ≒ 施工図

パッケージ ≒ ユニットパネルや備え付けの家具

さしずめ、プログラマはパネルや家具を集めて組み立て、人が立ち寄れる電脳商店を作る電脳大工さんといったところ。

プログラムとかソフトウェアってなんだか掴みどころが難しくイメージしずらい感じがするのがこのアナロジーですんなり頭に入るようになります。

身近なものに置き換えるって大事です。

Cloud9でバブルソート

いろいろ勉強したいことが溜まってきてしまっている今日このごろ、一個ずついろいろ試していきたいと思います。

とりあえず、HerokuGoogle App EngineならHerokuの方が無課金ユーザに優しい気がするのは分かった。

そんなわけで前からやってみたかったCloud9を使用してのC言語のバブルソートを書いてみます。

とりあえずC言語のコンパイル方法とかさっぱり忘れてしまっているのでドットインストールのC言語を見たり私の旧ブログを見たりして思い出します。

ほんでソースコード探検隊のバブルソートをやってみます。

C言語でバブルソート

bubble_sort.c

#include <stdio.h>

#define NUM_ITEMS 7

void bubbleSort(int numbers[], int array_size);
void printArray(int numbers[], int array_size);

int main()
{
  int numbers[NUM_ITEMS] = {6,5,3,1,7,2,4};

  printf("Start:\n");
  printArray(numbers, NUM_ITEMS);
  printf("\n");

  //perform bubble sort on array
  bubbleSort(numbers, NUM_ITEMS);

  printf("Done:\n");
  printArray(numbers, NUM_ITEMS);
  printf("\n");

  return 0;
}


void bubbleSort(int numbers[], int array_size)
{
  int i, j, temp;

  for (i = 0; i < (array_size - 1) ; i++) {
    for (j = (array_size - 1); j > i; j--) {
      printf("compare: %d and %d\n", numbers[j], numbers[j-1]);
      if (numbers[j-1] > numbers[j]) {
        temp = numbers[j-1];
        numbers[j-1] = numbers[j];
        numbers[j] = temp;

        printf("\tswap: ");
        printArray(numbers, array_size);
        printf("\n");
      }
    }
    printArray(numbers, array_size);
    printf("\n");
  }
}

void printArray(int numbers[], int array_size)
{
    int x;
    for (x = 0; x < array_size; x++) {
        printf("%d ", numbers[x]);
    }
}

コンパイルと実行

masasikatano:~/workspace $ gcc -o bubble_sort bubble_sort.c
masasikatano:~/workspace $ ./bubble_sort 
Start:
6 5 3 1 7 2 4 
compare: 4 and 2
compare: 2 and 7
        swap: 6 5 3 1 2 7 4 
compare: 2 and 1
compare: 1 and 3
        swap: 6 5 1 3 2 7 4 
compare: 1 and 5
        swap: 6 1 5 3 2 7 4 
compare: 1 and 6
        swap: 1 6 5 3 2 7 4 
1 6 5 3 2 7 4 
compare: 4 and 7
        swap: 1 6 5 3 2 4 7 
compare: 4 and 2
compare: 2 and 3
        swap: 1 6 5 2 3 4 7 
compare: 2 and 5
        swap: 1 6 2 5 3 4 7 
compare: 2 and 6
        swap: 1 2 6 5 3 4 7 
1 2 6 5 3 4 7 
compare: 7 and 4
compare: 4 and 3
compare: 3 and 5
        swap: 1 2 6 3 5 4 7 
compare: 3 and 6
        swap: 1 2 3 6 5 4 7 
1 2 3 6 5 4 7 
compare: 7 and 4
compare: 4 and 5
        swap: 1 2 3 6 4 5 7 
compare: 4 and 6
        swap: 1 2 3 4 6 5 7 
1 2 3 4 6 5 7 
compare: 7 and 5
compare: 5 and 6
        swap: 1 2 3 4 5 6 7 
1 2 3 4 5 6 7 
compare: 7 and 6
1 2 3 4 5 6 7 
Done:
1 2 3 4 5 6 7 
masasikatano:~/workspace $ 

ここであることに気づきます。

思ったよりC言語がしんどい。

というわけで、なんとなくPythonでも書いてみます。

Pythonでバブルソート

をやる前にCloud9でPythonを選択してワークスペースを作成すると、Python2がデフォルトになるためPython3に変更します。

masasikatano:~/workspace $ sudo mv /usr/bin/python /usr/bin/python2
masasikatano:~/workspace $ sudo ln -s /usr/bin/python3 /usr/bin/python
masasikatano:~/workspace $ python
Python 3.4.3 (default, Nov 17 2016, 01:08:31)
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

OKです。↓のようなファイルを作成します。参考にしたのは、Problem Solving with Algorithms and Data Structures の バブルソート回です。

bubblesort.py

def bubbleSort(alist):                       # defで関数を定義
    for passnum in range(len(alist)-1,0,-1): # range()で8から-1ずつ進み0で終了を指定
        for i in range(passnum):
            if alist[i]>alist[i+1]:          # データ配列の前後を比較して前の数が大きい
                temp = alist[i]              # 一時変数に前のデータを格納
                alist[i] = alist[i+1]        # データ配列の前後を入れ替え
                alist[i+1] = temp

alist = [54,26,93,17,77,31,44,55,20] # ソートするデータの入った配列を定義
bubbleSort(alist)                    # 関数を実行
print(alist)                         # 表示

実行してみます。

masasikatano:~/workspace $ python bubblesort.py 
[17, 20, 26, 31, 44, 54, 55, 77, 93]
masasikatano:~/workspace $ 

うまくいきました。

やっぱPythonの方が楽だ・・

シェルに関しての基礎的な用語のまとめ

最近Linux関連の書籍をもりもり読んでいます。特に勉強になっているのは

HOW LINUX WORKS―Linuxの仕組み スーパーユーザが知っておくべきこと (MYCOM UNIX Books)ブライアン ウォード (著), Brian Ward (原著)

入門者のLinux 素朴な疑問を解消しながら学ぶ (ブルーバックス)奈佐原 顕郎 (著)

Linux 怒濤のQ&Aぱぱんだ (著)

という書籍達です。

そこで「シェル」というものに対してなんだか認識がふんわりしていることに気づいてしまったので折角なのでここにまとめておきます。

シェル / Shell

シェルとは、コンピュータのOS(オペレーティングシステム)を構成するソフトウェアの一つで、利用者からの操作の受け付けや、利用者への情報の提示などを担当するもの。

IT用語辞典 e-Words

 

このシェル(殻)という名前は、カーネル(OS)とアプリケーションの中間に位置し、カーネルを包み込むことに由来する。シェルは、ユーザーからのコマンドを対話的に処理するのみならず、シェルスクリプトと呼ばれるファイルを作成することにより、一連の処理をバッチ(一括して連続的に)実行することもできる。

@IT

bash

bashとは、多くのUNIX系OSで標準的に使われるシェル(ユーザからの操作を受け付け、結果を表示するソフトウェア)の一つ。

IT用語辞典 e-Words

シェルスクリプト

拡張子が.shでよく分からんおまじないからはじまるプログラムファイルのこと。

シェルスクリプトとはシェルが解釈できるコマンドを羅列したファイルのことである。
たとえばhelloworld.shというファイルを作成し以下のような内容を記述する。

#!/bin/bash
echo "Hello World !"
exit 0

snowlongの日記

 

実はなんだかよく分からない内に、「シェル」と「シェルスクリプト」を混同してしまっていたことに気づきました。こういう認識違いって怖いなあ。

 

tty

 

linusakesson.net

 

UNIXの仮想的なキャラクター端末のデバイス名

weblio辞書

ttyってドライバのことなのね。