結論:MySQLのsql_modeには、ONLY_FULL_GROUP_BYを入れておく

ユーザを管理するテーブルを考える。ユーザはa, bという2つの属性を持つ。テーブルはこんな感じ。

CREATE TABLE users (
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  a INT,
  b INT,
  INDEX (a),
  INDEX (b)
);

INSERT users (a,b) VALUES (1,1);
INSERT users (a,b) VALUES (1,2);
INSERT users (a,b) VALUES (1,3);

SELECT * FROM users;

+----+------+------+
| id | a    | b    |
+----+------+------+
|  1 |    1 |    1 |
|  2 |    1 |    2 |
|  3 |    1 |    3 |
+----+------+------+

属性aが1の人数は、次のように求められる。

SELECT count(*)
FROM users
WHERE a=1;

+----------+
| count(*) |
+----------+
|        3 |
+----------+

何かの事情でaの値も取得したいとき、安易に次のように書いてしまうかもしれない。

SELECT a,count(*)
FROM users
WHERE a=1;

+------+----------+
| a    | count(*) |
+------+----------+
|    1 |        3 |
+------+----------+

上のSELECT文は、手元のMySQL 5.0.84と5.1.37-1ubuntu5, 5.4.3-beta-communityでは動作する。しかし、MySQL 5.0.45-logでは次のようなエラーになる。

ERROR 1140 (42000): Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause

リファレンスマニュアルの3.3.4.8. Counting Rowsには、上のようなSELECT文は可能だという記述があるのだが、うまくいかない環境もある(「SET sql_mode='';」としてもだめ)。

次のように書けば、どの環境でも動く。一般的に、集約関数があるときは、SELECTするものはGROUP BYの対象になっていなければならない(最初のSELECT文を実行できたのは、MySQLの独自の拡張のため)。

SELECT a,count(*)
FROM users
WHERE a=1
GROUP BY a;

SELECT a,count(*) FROM users GROUP BY a HAVING a=1;」と書いてもいいが、これを素朴実行したらさすがに遅いだろう(オプティマイザが上の形に変換してくれるとも思えない)。

このようなバージョンによる振る舞いのぶれを無くすためには、「SET sql_mode='ONLY_FULL_GROUP_BY';」として、SQLモードを変更し、MySQLの独自の拡張を無効にすればよい。こうすることによって、以下のSELECT文はすべてのバージョンでエラーになる。(ちなみに、現在のSQLモードは「SELECT @@sql_mode;」でわかる。)

SET sql_mode='ONLY_FULL_GROUP_BY';

SELECT a,count(*)
FROM users
WHERE a=1;

ERROR 1140 (42000): Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause

そもそも、曖昧なSELECT文を実行させるような独自拡張に何の意義があるのだろうか。リファレンスマニュアルの11.11.3. GROUP BY and HAVING with Hidden Columnsには、You can use this feature to get better performance by avoiding unnecessary column sorting and groupingとあるから、パフォーマンスがよくなる可能性はある。本稿の例ではaの値は1しかないため、「GROUP BY a」をしなくて済むならそれに越したことはない。しかし、これはわざと作った例であり、実際にこういうことがうれしいという状況にあるときは、何かおかしなことをしているという自覚があるべきだろう(先に書いた「何かの事情」とはそういうことだ)。

それよりも、何か間違ったことをしているのに、MySQLの寛容さのためにその発見が遅れることがこわい。そういうことにならないための安全策として、普段から、曖昧なSELECT文を許容しないようにMySQLを設定しておくといいだろう。具体的には、my.cnfあるいはmy.iniの[mysqld]のセクションに、「sql-mode="ONLY_FULL_GROUP_BY"」と書いておけばよい。

もっと非寛容にしたい向きは、リファレンスマニュアルの5.1.7. Server SQL Modesから、それらしいものを見繕ってくればいい。TRADITIONAL(STRICT_TRANS_TABLES, STRICT_ALL_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USERをまとめたもの)あたりから試すのがおすすめか。

Chikirinさん曰く(実践女子大学と青山学院大学、同志社大学、京都大学を例に)

背景はよくわかるよ。私立大学はどこもJALと同じくらい経営が厳しい。顧客集めに四苦八苦だ。応募数を増やすにはそりゃあ田舎よりは都会にキャンパスを集約したい。だけど全員を都心に呼ぶのは無理。じゃあ、文系だけ分離して移そうという話になる。

(中略)

これ、本当に教育目的に照らして、いいことだと思います?

たいていの学生は、入学した時点ですでに、人間を理系と文系に分けるという考え方に慣れてしまっているわけですが、そういうものではないということを、大学教員が丁寧に教えていければいいと思います。そう考える教員はあまり多くはないかもしれないので、キャンパスを統合するよりは、かなりチャレンジングだと思いますが。

学問分野と学生の男女比には密接な関係があり(これが望ましいことがかどうかはともかく)、分野によって場所を分けることは、場所による男女比の差の拡大にも繋がります。悪いことにいわゆる理系には、女性とコミュニケーションを取るのが苦手な男子が多くいます。彼らのための自然な出会いの場が少なくなることのほうが深刻な気もします。

「出会いを求めに行かない奴はダメ」というのは、対象が学問であれ異性であれ正論なのかもしれませんが、今日の教育は、もう少し面倒見がよくてもいい気がします。

私は間違っていました。

「CGに興味があるから」と言って観に行ったはずの『タイタニック』の、ストーリーのあまりのひどさにぶち切れていた私は間違っていました。

ジェームス・キャメロン監督は、CGで豪華客船をひっくり返したかっただけなのです。だから観るほうも、純粋にCGを楽しむべきだったのです。

『Avatar』を観てよくわかりました。彼は最先端のCG技術を観客に見せつけたくてしょうがないのです。そして、今回は私もその意図を正しくくみ取れたと思います。すごかったです。

写真が活動写真になったことや、活動写真に音声が付いたこと、映像がカラーになったことには劣るかもしれませんが、映画を観たジョージ・ルーカスをして「スター・ウォーズも3Dにしたい」と言わしむのですから(eiga.com)、エポック・メイキングな作品であることは間違いありません。(ストーリーはどうでもいいと言いましたが、ジェダイの騎士たちのまぬけっぷりは、もう少しどうにかしてほしいです。)

ジェームス・キャメロン監督の次回作は、広島と長崎への原爆投下を題材にするらしいので(eiga.com)、「ストーリーはどうでもいい」とは言いにくいんじゃないかと少し心配してます。

しばらくは、この映画のような意味での「3D」と、いわゆる3D CGの「3D」が混乱して使われることでしょう。でも、近い将来に両者は同じものになるはずで、ちょっとわくわくしますね。

47968706364781603025

画像がゲーム制作者になるための3Dグラフィックス技術 (単行本)『ゲーム制作者になるための3Dグラフィックス技術』の表紙で採用されていましたが、ゲームの方は、どうなんでしょう。

B002QUYQUCB002QUYQU2

注意:劇場で観る時は、メガネが壊れていないことをちゃんと確認しましょう。

追記:アニメと実写を比較して、実写の方を3Dと呼ぶこともありますね。いい使い方とは思いませんが。

「自分の木」の下で (単行本)の表紙大江健三郎さんの小説を読んだことがないという人に、彼がどういう作家かということの私なりの解釈を伝えたいときに引用する挿話。エッセイ集『「自分の木」の下で』のp.13より。高熱で瀕死の状態にあった大江健三郎さんと彼の母上との間で、次のようなやりとりがあったという。

---もしあなたが死んでも、私がもう一度、産んであげるから、大丈夫。

---......けれども、その子供は、今死んでゆく僕とは違う子供でしょう?

---いいえ、同じですよ、と母はいいました。私から生まれて、あなたがいままで見たり聞いたりしたこと、読んだこと、自分でしてきたこと、それを全部新しいあなたに話してあげます。それから、いまのあなたが知っている言葉を、新しいあなたも話すことになるのだから、ふたりの子供はすっかり同じですよ。

私はなんだかよくわからないと思ってはいました。それでも本当に静かな心になって眠ることができました。

こういうことを幼い頃の記憶として語る小説家に興味を持つ人はけっこういるんじゃないかと思う。

瀕死の子供以外にも、この挿話で救われる人はいるんじゃないかとも(キリスト教原理主義者のことではない)。

やねうらおさんによると、「広く知られているinsertion sortのコードは駄目すぎる」らしい。Wikipediaに載っているコード(2009.08.06版)を、

どこの馬鹿なアルゴリズムの教科書から引用してきたのかは知らないが、こんなものをサンプルとして掲載しないでもらいたい。

というのだから穏やかではない。

私の座右の書『コルメン』も、

一連の劣悪なコードはこいつが犯人かも知れない。

と非難されてしまっている。

実際のところ、どのくらいの性能差になるのか、実験してみた。

こんな感じ(codepad)。

C++の標準ライブラリ(std)のsortとWikipedia版、やねうらお版の比較。単位は秒。挿入ソートの2つ(つまりWikipedia版とやねうらお版)は、実行時間の比も計算した(1より小さい値はやねうらお版が速いことを意味する)。

size	repetition	std	wiki	yane	y/w
4	1048576		0.3512	0.1576	0.1333	0.8459
8	233016		0.1148	0.06757	0.07265	1.075
16	65536		0.111	0.02996	0.1191	3.976
32	20971		0.1388	0.1141	0.09537	0.836

Timeout

codepadはすぐにタイムアウトしてしまうから、ベンチマークにはちょっと使えない(そもそも、ほかにどんなプロセスが動いているかわからないし)。

手元のCore i7 940 2.93GHz、主記憶9Gのマシンで実行してみる。

GCC 4.4.2(64ビット)の場合(コンパイルオプションは「-O3」のみ)

size    repetition      std     wiki    yane    y/w
4       6291456         0.3001  0.1896  0.1957  1.032
8       1398099         0.1766  0.1374  0.1427  1.039
16      393216          0.1201  0.09756 0.09972 1.022
32      125829          0.1045  0.08267 0.08463 1.024
64      43689           0.08399 0.07897 0.08637 1.094
128     16047           0.07033 0.09022 0.1061  1.175
256     6144            0.06053 0.118   0.1466  1.243
512     2427            0.05325 0.1704  0.2192  1.287
1024    981             0.04746 0.263   0.3447  1.311
2048    405             0.04273 0.4241  0.5613  1.323
4096    168             0.03847 0.697   0.9245  1.326
8192    72              0.0356  1.187   1.582   1.333
16384   30              0.03148 1.978   2.623   1.326
32768   12              0.02696 3.157   4.208   1.333
65536   6               0.02857 6.37    8.425   1.323

配列のサイズが64くらいまでなら、std::sortを使うよりも挿入ソートのほうが速いようだ。その範囲では、Wikipedia版とやねうらお版にあまり差はない(Wikipedia版が若干速いか)。

インテルC++コンパイラ 11.0(64ビット)の場合(コンパイルオプションは「-fast」のみ)

size    repetition      std     wiki    yane    y/w
4       6291456         0.2103  0.2164  0.2285  1.056
8       1398099         0.1464  0.1455  0.1447  0.9947
16      393216          0.107   0.106   0.1072  1.011
32      125829          0.1034  0.08955 0.09303 1.039
64      43689           0.08693 0.08898 0.09369 1.053
128     16047           0.07405 0.1059  0.1113  1.051
256     6144            0.06446 0.1456  0.1503  1.032
512     2427            0.05672 0.218   0.2219  1.018
1024    981             0.05066 0.3439  0.3462  1.007
2048    405             0.04571 0.5608  0.5618  1.002
4096    168             0.04118 0.9253  0.9255  1
8192    72              0.03799 1.578   1.579   1
16384   30              0.03406 2.628   2.629   1.001
32768   12              0.02887 4.197   4.208   1.003
65536   6               0.0307  8.464   8.46    0.9995

GCCのときよりstd::sortが速くなるのが早い。サイズ64ならもうstd::sortでよいようだ。GCCの場合より、std::sortが有利になるのが少し早い。Wikipedia版とやねうらお版にあまり差はない(やはり、Wikipedia版が若干速いか)。

Visual Studio 2008(32ビット)の場合(Releaseモード。オプションはデフォルトのまま)

size    repetition      std     wiki    yane    y/w
4       6291456         0.329   0.184   0.171   0.9293
8       1398099         0.209   0.14    0.142   1.014
16      393216          0.136   0.114   0.111   0.9737
32      125829          0.105   0.1     0.098   0.98
64      43689           0.103   0.099   0.097   0.9798
128     16047           0.093   0.113   0.115   1.018
256     6144            0.083   0.141   0.155   1.099
512     2427            0.075   0.195   0.226   1.159
1024    981             0.066   0.295   0.35    1.186
2048    405             0.061   0.469   0.568   1.211
4096    168             0.057   0.77    0.937   1.217
8192    72              0.051   1.313   1.617   1.232
16384   30              0.045   2.207   2.72    1.232
32768   12              0.038   3.57    4.398   1.232
65536   6               0.04    6.966   8.513   1.222

配列サイズ64くらいまでは、挿入ソートがstd::sortより速い。その範囲では、Wikipedia版よりやねうらお版のほうが若干速いか。

いずれにしても、配列サイズが小さいなら、挿入ソートを試す価値はありそうだ。しかし、GNUやインテルのコンパイラをよく使う私には、挿入ソートの細かいチューニングは早すぎる最適化になりそうだ。

小さい配列限定のすごく速いソートなら、ソーティングネットワークはどうだろう。サイズ7の場合はこんな感じ(codepad)。batcherがソーティングネットワーク。単位は秒。codepadだと遅いか。

GCC 4.4.2(64ビット)では、ソーティングネットワークが速い。

std::sort: 0.411432
wikipedia: 0.3258
yaneurao: 0.331935
batcher: 0.28106

インテルC++コンパイラ 11.0(64ビット)の場合

std::sort: 0.324813
wikipedia: 0.331058
yaneurao: 0.298131
batcher: 0.228164

ここで使っている関数bathcersortは、CPANにあるAlgorithm::Networkで作った。次のようなコードでASCIIアートを描ける。

use Algorithm::Networksort qw(:all);
$inputs=7;
my @network = nw_comparators($inputs, algorithm => 'batcher');
print nw_graph(\@network, $inputs), "\n";
o--^--------^-----^-----------------o
   |        |     |                  
o--|--^-----|--^--v--------^--^-----o
   |  |     |  |           |  |      
o--|--|--^--v--|--^-----^--|--v-----o
   |  |  |     |  |     |  |         
o--|--|--|-----v--|--^--v--|--^--^--o
   |  |  |        |  |     |  |  |   
o--v--|--|--^-----v--|--^--v--|--v--o
      |  |  |        |  |     |      
o-----v--|--|--------v--v-----|--^--o
         |  |                 |  |   
o--------v--v-----------------v--v--o

仕組みを知りたいという向きにはKnuthの第3巻が、「サイズ7限定じゃ意味ないし、任意のサイズでできるようにしたらコンパイルできないじゃん」という向きには『LET OVER LAMBDA Edition 1.0』がおすすめ。

47561461474434133632

公式サイト

USAの女性の10人に1人がよむらしいファッション誌VOGUE。1988年からその編集長を務めるアナ・ウィンター。『プラダを着た悪魔』のモデルとしても有名な彼女についてのドキュメンタリー。

原題はThe September Issue。直訳すれば『九月号』。タイトルの通り、映画の大部分はVOGUE 2007年9月号の制作風景。その中で、彼女の力(影響力、決断力、・・・)が披露されていく。ちなみに、9月号というのは、1年の中でもっとも重要なものらしい。映画で扱われた2007年9月号は、Amazon.comでプレミア価格になっている

ファッションが教えてくれることももちろんあるわけだけど(「ちゃんとプラダ着てる」とか)、他にも印象に残ることはいろいろあった。ずっとサングラスかけてる人が「色が大事」とか言うとかっこいい、「怒りが抑えられなくなったら引退する」などなど。

とりあえず、「ファッションが教えてくれること、それは人の本質」なんていう作品ではなかった。

Windows 7は、32ビット版と64ビット版のどちらを使うのがいいのでしょうか。

絶対欠かせないソフトウェアが64ビット版では動かない場合、32ビット版を使うしかありません。そのソフトのためだけにVirtualBoxのようなを使ってもいいのですが、たいていの人はそんなことはしたくないでしょう。

4GB以上の主記憶を使いたい場合には、64ビット版を使うしかありません。32ビット版ではそれだけのメモリを使うことはできないからです。

上記2点のどちらにも当てはまらない場合はどうしたらいいでしょうか。

Mathematicaが大好きな人には(あるいは大好きじゃなくても、Mathematicaをよく使う人には)、64ビット版がおすすめです。変わらないという話もありますが、少なくともベンチマークでは圧倒的な差が出ます。

OSをクリーンインストールして(Vistaの場合はマザーボード付属のCDで各種ドライバをインストール)、本稿執筆時点でのWindows Updateで自動的に選択される更新をすべて適用した状態で、Mathematicaをインストールし、MathematicaMark7を実行した結果は次の通りです(利用したマシンはIntel Core i5 750 2.67GHz, 主記憶4GB)。

  • Windows Vista SP2 (32 bits): 5.05(ちなみに、インストール直後は4.98)
  • Windows 7 (32 bits): 5.21
  • Windows 7 (64 bits): 5.95

Mathematicaに関して言えば、64ビットにすることの効果はかなり大きいようです。

とはいえ、どんな計算でも速くなるというわけではありません。ベンチマーク結果とソース(省略)を詳しく見ると、計算が速くなるのはデータフィッティングやπの計算、離散フーリエ変換、ガンマ関数、大きな整数の計算、行列のべき乗、行列の転置などだということがわかります。

項目Vista SP2(32 bits)7 (32 bits)7 (64 bits)
Total17.0816.5314.49
Data Fitting1.230.970.69
Digits of Pi0.640.610.39
Discrete Fourier Transform0.560.470.36
Eigenvalues of a Matrix1.151.081.06
Elementary Functions0.941.051.00
Gamma Function0.500.470.27
Large Integer Multiplication0.800.800.50
Matrix Arithmetic2.122.141.78
Matrix Multiplication1.091.081.20
Matrix Transpose1.341.360.84
Numerical Integration1.841.701.75
Polynomial Expansion1.231.191.14
Random Number Sort1.371.371.23
Singular Value Decomposition1.081.001.05
Solving a Linear System1.191.281.25

とある事情でMySQLを何度もビルドしなければならなくなりました(『MySQLデータベース構築バイブル』を読んだからではありませんが、そういうことにしておいてもらってもいいです)。

利用できる最速のマシン(Core i7 GHz)でMySQL 5.4.3-betaをビルドするのにかかる時間は1分40秒ほどです。1回だけならいいのですが、何回もすることを考えると、少しでも早くビルドできる環境を用意しておきたくなります。

Windowsの場合は知りませんが、GNU/LinuxやMac OS Xでは、C言語とC++の分散コンパイルのためのdistccが簡単に利用できるので試してみました。

手順は以下の通りです。

  1. すべてのマシンで同じコンパイラを利用できるようにする
  2. distccのインストール
  3. 環境変数CC、CXXの設定
  4. ./configure
  5. 環境変数DISTCC_HOSTSの設定
  6. make -jジョブ数

もう少し詳しく説明します。

利用したマシンは以下の通りです(A, D, Eのネットワークは1G、それ以外は100M)。

  • A: Core i7 940 2.93GHz
  • B: Core i5 750 2.67GHz
  • C: Core2 Quad Q6600 2.4GHz
  • D: Core2 4300 1.8GHz
  • E: Athlon 64 X2 5400+
  • F: Pentium D 3GHz

クライアント側で必要なのはdistcc、サーバ側で必要なのはdistcc-serverだけなのですが、マシンをどのように利用するかが確定しているわけではないので、まとめて入れておきます。

yum install distcc*

本稿執筆時点では、パッケージで配布されているdistccのバージョンは2.18でした。Googleによって改良されたバージョン3系列のほうが、パフォーマンスはいいはずなのですが、私の環境ではそれを確認することはできませんでした。

今回利用したGCCのバージョンは4.4.2です。すべてのマシンで、同じフルパスで同じバージョンのgcc, g++を利用できるようにしておきます(binutilsも?)。その上で、クライアントで次のように環境変数を設定します。

export CC="distcc gccのフルパス"
export CXX="distcc g++のフルパス"

さらに、利用するサーバとジョブの数を設定します(クライアントはIPではなくlocalhostと書くべきです)。ジョブ数のデフォルトはIPに対しては4、localhostに対しては2なので、その場合は「/ジョブ数」は省略することができます。「IPアドレス/ジョブ数,lzo」と書くとデータを圧縮するようになりますが、私の環境ではその効果は確認できませんでした。

#distcc Ver. 2の場合
export DISTCC_HOSTS="サーバ1のIP/ジョブ数 サーバ2のIP/ジョブ数 ... localhost/ジョブ数"
#distcc Ver. 3の場合
export DISTCC_POTENTIAL_HOSTS="サーバ1のIP/ジョブ数 サーバ2のIP/ジョブ数 ... localhost/ジョブ数"

すべてのサーバ用マシンで、次のようにしてサーバを起動します(受け入れるジョブの最大値を指定することもできますが、この例のように省略すると、CPU数+2になります)。サブネットは192.168.0.0/24のように指定します(毎回これを行うのが面倒なら、distccdが自動的に起動されように設定しておいてもいいでしょう)。このサーバがポート3632を利用できるようにファイアウォールを設定しておいてください(利用するポートを指定することもできます)。

distccd --daemon --allow サブネット --log-stderr

マシンBをクライアントにして、DISTCC_HOSTSを「AのIP/6 EのIP CのIP localhost」にしたときのビルド時間は1分17秒でした。マシンA単体でのビルド時間1分41秒、マシンD単体でのビルド時間6分54秒と比べると、「速くなってよかったね」という感じです。

投入するジョブの数は微妙な調整が必要です。デフォルトの「CPU数+2」が最適というわけではありません。また、明らかに遅いマシン(ここではマシンF)は入れない方がよさそうです。

Macでも試してみました。Macの開発環境にはdistccがはじめから含まれているので、準備の手間が一つ省けます。

手元のMacBook Pro (Core2 Duo 2.16GHz)単体では、ビルドに7分57秒かかりました(GCCのバージョンは4.2.1)。

MacPortsという常にソースからビルドするシステムがデファクトになっているのでとても困ったことなのですが、私のMacのビルドは遅いです(MacPortsの待ち時間は大嫌いです)。たとえば、CPUはこのMacBook Proより遅いはずのマシンD(上述)のビルド時間は6分54秒でした(ディスクの書き込み速度の差はあまり関係ないでしょう)。

このMacBook Proをクライアントに、Core2 Duo 2GHzのMacBookとMacMiniをサーバにして(DISTCC_HOSTSは「MacBookのIP MacMiniのIP」)ビルド(make -j8)した結果は5分53秒でした(localhostをDISTCC_HOSTSに追加したら遅くなりました)。

確かに速くはなりましたが、「MacPortsがすごく速くなるかも」という期待は裏切られた感じです。

もちろん、GNU/Linuxマシン上にクロスコンパイル環境を構築してサーバにすればよいというのはわかっているのですが、Appleが開発環境を微妙にいじっているせいで、クロスコンパイル環境の構築はちょっとやっかいだったりするのです(そのためのプロジェクトがあるくらいに)。

『ジェネレーティブプログラミング』『C++ Template Metaprogramming』で紹介されているテンプレート/メタプログラミングのコードを使えば、分散コンパイルのインフラ上で並列計算ができたりするわけですが、そういうネタはまた別の機会に。

追記:Cプリプロセッサメタプログラミングで、文字列系泥沼関数型プログラミングというのもすごいですね。

闘うプログラマー[新装版] ビル・ゲイツの野望を担った男達 (単行本(ソフトカバー))G・パスカル・ザカリー著, 山岡洋一訳『闘うプログラマー』(日経BP, 2009)

副題:ビル・ゲイツの野望を担った男達。

1994年に出た翻訳が最近復刊して話題になっていました。私の手元にある旧版は2巻なので、それが1冊になっただけでも新しい読者にはいいことでしょう(旧版のほうがかなり安く入手できるでしょうが)。

これはWindows NTの開発現場を描いたノンフィクションです。NTの初期バージョンであるWIndows NT 3.1が発売されたのは1994年。その後、NT 4.0 (1996)と2000 (NT 5.0)とXP (NT 5.1), Vista (NT 6.0), 7 (NT 6.1)と続いています。この系列に属さないWindows 95などは、安定性に大きな問題がありましたが、95から98ではなくNT 4.0に移行した私は、「OSが不安定だからこまめにセーブしよう」などということにはならずに生きてきました。95→98→Meだった人は大変だったと思います。

現在の最新OSであるWindows 7は、1994年のNT 3.1とアプリケーション及び操作性において、かなりの互換性を保っています。後方互換性をあまり重視しないMacと比べて、どちらがいいかということは一概には言えませんが、すごいことではあります。「MacとWindowsではMacのほうが進んでいる」ということがよく言われますが、現在の基準から見れば必須と思われる機能の多くは、当時のWindows NTにはあって、Mac OSにはなかったことを忘れてはいけません。本書を読むと、そのことを改めて思い出させられます。

そのほかにも、史上最大規模のソフトウェア開発がどのように進められたのか、Windows NT開発におけるビル・ゲイツの役割、マイクロソフト社員の仕事と家庭など、興味深い話題はたくさんあります。

わたしは電子の歌をうたう―マイクロソフトがマルチメディアに挑んだ1年 (単行本)そもそも、世界最大のソフトウェア会社におけるソフトウェア開発の裏側ですから、興味深くないはずはありません。エンカルタの開発現場を描いたフレット・ムーディ『わたしは電子の歌をうたう』(早川書房, 1997)を楽しめた人は、本書もきっと楽しめるでしょう(本書を楽しめた人は、『電子の歌』もきっとたのしめます)。

原題はShowstopper。辞書を引くと「演技を中断させるほどの長い喝采を受ける演技[歌、役者]」とありますが、ここでは「オペレーティング・システムが実行する『ショーがストップする』ほど深刻なバグ(上p.33)」の意味で使われています。

邦題は『闘うプログラマー』。「Showstopperでは売れない」という判断があったのでしょうが、プログラマー以外にも多くの人が重要な役割を演じる本書にこの邦題はふさわしくありません。ソフトウェア開発の現場での職種による差別は本書の話題の一つではありますが、邦題でそれを際立たせる必要はないでしょう。

「ビル・ゲイツの野望を担った男達」という副題も、複数の女性が活躍する本書にはふさわしくありません。Showstoppingだとまでは言いませんが。

『ヒカルの碁12巻』での佐為のセリフです。「いい碁盤はカヤなんです!」(ちなみにヒカルの碁12巻では日本の元総理大臣をモデルにしたキャラクターが、とても重要な役で登場しています。)

私が今使っている碁盤はコンピュータのディスプレイ、将来使う予定なのはElectronic Go Board by Tommy Chenなので、高価な榧の碁盤を持つことはないだろうと思っていたのですが。

榧盤デビューしました。

七路盤

五路盤はすでにコンピュータで解かれていますが、七路盤はどうでしょう。

Google PageRankの数理 ―最強検索エンジンのランキング手法を求めて― (単行本)Googleがウェブページの順位付けに用いている指標の一つであるPageRank。最近ではその重要度が下がっていて、“Googe Pagerank is Dead!”などと言われたりもするのだが、アイディアはとてもシンプルで、(対象ページが少なければ)実際に計算するのも簡単なため、「ウェブページの順位付けと言えばまずPageRank」という状況はまだ当分続くだろう。(「Google検索アルゴリズムで生態系崩壊を予測」などという応用もある。)

PageRankについての概説と言ってまず思い出すのは「Google の秘密 - PageRank 徹底解説」だが、さらに徹底的に解説した書籍『Google PageRankの数理』が翻訳された。

数学的な細部も詳しく説明されていて便利なのだが、コーヒーブレイク的なコラムも充実していておもしろい。

たとえばGoogle Bomb。

実際にウェブページの順位付けをしようとすると、PageRankのような数学的に整理されたきれいなものだけでなく、いろいろと細かい調整をしなければならなくなる。Google Bombはその一例だろう(参考:ブッシュ大統領もひと安心? グーグルが無力化したネット上の「爆弾」

『Google PageRankの数理』によれば、Googleは2004にはこの問題への対応を始めている(原書p.55)。不思議なことに、それからずいぶん時間が経っているにも拘わらず、MicrosoftのBingやYahoo! Japanは、現時点で、Google Bombのもっとも有名な例「miserable failure」にさえ対応できていない(Yahoo.comは大丈夫)。

使っているのは整数の加算と乗算だけで、オーバーフローしているわけでもないのに正しく計算できない例を先日紹介しました(フェルマーの最終定理の「反例」(電卓編))。

文明が発達しすぎた果てに電卓を作れなくなってしまうというのはSFでよくありそうな話ですが、時代の先を行っているというAppleの主張は確かに正しいのかもしれません。(参考:ロストテクノロジー(Wikipedia)

小数が出てくればいろいろ問題があるのは知っていても、電卓を使った整数の計算を疑う人は少ないのではないでしょうか。しかし実際には、WindowsやMac OS Xの標準的な電卓は、つい最近まで整数の計算を正しく行えませんでした。

1992年に発売されたWindows 3.1の電卓には、下のような普通の電卓と関数電卓の2種類のモードがありました(下はWindows 3.1の電卓をWindows 7上で実行した様子です)。

この、普通の電卓と関数電卓という構成は、2007年に発売されたWindows Vistaまで、基本的には変わりません(下はWindows Vistaの電卓。Windows 3.1のものと違って、Windows 7上では実行できないというのは皮肉なことです)。

Windows 7では、電卓のUIが変更され機能も大幅に拡張されるため、ちょっと話題になっていました。

Windows 95以来、スタートメニューのアクセサリには、電卓が含まれていた。その機能はVistaまでほとんど変わることなく続いてきた。(Windows 7ソフトウェアレビュー - 大きく進化した電卓編

これは大間違いです。まあ、見た目がほとんど変わっていないので、そう思われるのもしかたがないのですが。私が試した限りでは、Windowsの電卓は、1995年に発売されたWindows 95と1999年に発売されたWindows 98SEの間では、その機能が大きく変わっています。計算の精度を高めることによって、フェルマーの最終定理の「反例」(電卓編)のような問題が起こらなくなったのです(参考:When you change the insides, nobody notices)。

一方Macはと言えば、1996年に発売されたMac OS 7.5.5の電卓は、下のような感じでした。1992年のWindows 3.1にかなり後れを取っている感じです。

Mac OS Xの電卓は、下のような基本・科学計算・プログラマの3つのモードを備えており、Windows Vistaのそれより優れているように見えます。

しかし、先に述べたようなMicrosoftが遅くとも1999年には修正できていた問題が、Macで修正されたのは2007年のMac OS X 10.5でのことでした(PowerPC版Mac OS X 10.4では、基本モードと科学計算モードで結果が異なり、しかも、両方とも間違っていました)。

同じくApple社のiPhoneの電卓はもっと大変で、Ver 2.0のバグはかなり大きく取り上げられましたし(参考:iPhone 2.0 の「計算機」アプリにバグが発見される)、本稿で扱っているような、大きな整数の計算を正しくできないという問題は、バージョンが3.1になった現在でも残っています。端末を回転させるとモードが切り替わるのもかっこよくていいのですが、その前にやるべきことがたくさんありそうです。

見た目をよくするのは大事なことです。でも、電卓でもっとも大切なことは「正しく計算できること」であるということに疑問の余地はありません。

「正しく計算できること」を完璧に実現するのはもちろん不可能です。どのあたりで妥協するかが重要なわけですが、フリーソフトウェアのGNU bcの、「メモリが許す限りの桁数を確保する」というのは一つの目安になるでしょう。

やってはいけないのは、「整数はいわゆるintで計算し、その範囲を超えたり1未満の数が必要になったらいわゆるdoubleを使う」というような実装です。こういうことをしてしまうと、フェルマーの最終定理の「反例」(Perl, awk, JavaScript, PHP編)も発生してしまいます。

もっとも、電卓をちゃんと作るのは以外と難しいようで、2008年にはGoogleも計算ミスをしていました(参考:グーグルの電卓機能が計算ミス)。そのときには次のような解説がありましたが、その筆者が考える電卓の実装は、先に述べた「やってはいけないこと」そのままのようです。

コンピュータでの正確な計算は、コンピュータが一般的に0または1の数字しかない2進数で計算をしていることに基づいている。一方、人は0から9までの数字を使った10進数計算を行う。正確性に問題が生じるのは、コンピュータが数字を2進数に変換して処理し、結果を10進数に戻して表示するためだ。

このようなことが、電卓において問題になるはずはありません。

プログラミングの入門書などで、「電卓を作ってみよう!」なんていうのをたまに見かけますが、入門者に電卓はあまりいい題材ではありません(RubyやPythonなら問題ありません。他の言語でも、GMPを紹介するなら大賛成です)。

電卓を作るのもなかなか大変です。

メモ

電卓で整数の計算がある程度正確にできるようになった時期

  • Unix (GNU bc): 1994年(遅くとも)
  • Windows: 1999年(遅くとも)
  • Mac: 2007年

portrait

 

Translation

著書

schedule

 

2010年2月

  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28            

関連商品(Amazon)

関連サイト(Google)

アーカイブ

twitter

  •