スタンフォードの単位は通わなくてもリモートで取れるよ、テストとかの難易度は同じで
スタンフォード大学にはSCPD(Stanford Center for Professional Development)という社会人向けのプログラムがあって、仕事をしたままパートタイムで授業を受けることができるようになっている。授業のビデオをオンラインで見て、課題を期限内に提出して、テストだけはキャンパスに受けに行くというもので(遠隔地の場合はテストもリモートでできるらしい)、成績は普通の生徒と一律につけられるし、単位も普通にもらえるという仕組み。まあなんというか、ただ後ろの方に座って大学院の授業を受けているのと同じような感じというか。
時間もあるので、コンピュータサイエンスでちょっとそういう勉強にも手を出してみるかなと思って、今年に入ってからSCPDを始めてみた。目安によれば1単位あたり4時間ほど時間を取ればよいらしく、1授業で4単位の授業がほとんどだから、週16時間確保できればいい、と書いてあった。週16時間なら週末を使えばできるはず。学費は1単位1400ドルくらいで、費用は高いけどアメリカの大学だしそんなものかなと思った。
第1クオーター
一番最初に取った授業はProgram Analysis and Optimizations (CS243)というもの。コンパイラでのプログラムの解析と最適化の授業で、データフロー解析とかソフトウェアパイプライニング、自動並列化とかを学ぶというもの。コンパイラの標準的教科書、通称「ドラゴンブック」を教科書として使う。ドラゴンブックは僕はすでに持っていたのだけど、かなりの章が積読になっていたので、この機会に読み進めることもできるし、これをとりあえず受けてみるかと思って履修してみた。
初回の授業を見て知ったのが、Monica Lam先生がドラゴンブックの筆者の一人だということ。教授が自分の書いた本を生徒に買わせるというよくある話。でもドラゴンブックならみんな納得。というか、さすがだな。
最初の何週間かは簡単だった。課題の締め切りも随分先で、内容もそんなに進んだ話になってないし、適当にビデオを見て本に目を通していればそれで十分だった。
が、3週間目くらいからだんだん難しさが増してきた。まずなんといっても本を読んでこないといけない分量が多すぎて、課題の前提になっている章を読むだけで週末が終わってしまう。そこから課題をやるのだけどよく理解していないと答えがよくわからないから、これもまた時間がかかる。
プログラミング課題もとても時間がかかった。謎の初見のJavaデータフロー解析フレームワークが与えられて、これを使って定数伝播などの解析を行ってください、というような課題がでるのだけど、まずそのフレームワークの使い方を試行錯誤で調べるだけでとても時間がかかる。広く使われているものでもないのでドキュメントも貧弱で、思ったように動かない時にどうすればいいのかなかなかわからない。これはある意味実際のエンジニアリングの訓練になっているといえるかもしれないけど。
結局気づいたら週30〜40時間は授業と課題に費やすようになっていた。それくらい使わないと終わらないのだ。最後の方では試験対策に有休を取って一日中やっていた。
授業の最後のほうでは線形代数を使って依存性を解析して自動ベクトル化、みたいな面白いテクニックを習ったのだけど、面白いのはいいけどこれもやたらと複雑だった。
最後に、ここまでで習った最適化を適用して命令数を減らしてみましょう、という課題がでた。やらなくてもいいのだけど、うまくやれば追加点がもらえるというもので、僕は果敢に挑戦して自分ではこれはなかなかよいと思うものを実装してみた。ところが結果は追加点0。テスト用のプログラム(非公開)でミスコンパイルがあった場合は無条件で0点という無慈悲なルールだったのだ。アグレッシブに攻めすぎるとミスを犯しやすく、そうするといきなり部分点なしに0点になるという、ちょっとどうかというルールだったけど、まあなんというか、いまさら言っても仕方がない。
結局この授業ではAマイナス評価だった。悪くはない・・半分よりは上の評価だし・・でもこれは正直悔しかった! 最後の課題と期末試験がしくじったところが多かったのだけど、それさえなければAだったんじゃないかと思う。
第2クオーター
次のクオーターではリベンジを期してIntroduction to Compilers (CS143)を履修することにした。
前回の反省点は、最初にあなどってかかってしまったことと、ペアでやってもよいといわれていた課題をペアを組んでやらなかったことだと思ったので、今回はペアを組んでやることにした。ペアは社内で探した。
CS143はコンパイラ入門なのでCS243ほど難しくはなかった。授業を通して、教育用のオブジェクト指向言語をMIPSアセンブリにコンパイルできるようになろう、という感じで、lexを使ったレキサー、yaccを使ったパーザ、意味解析、コードジェネレータを書く課題が出る、といった感じ。
yaccとlexはほとんどまじめに使ったことがなくて食わず嫌いだったから、授業でやってちょうどよかった。手書きのパーザとパーザジェネレータのどちらが好きかというのは、良し悪しというよりどちらに慣れ親しんでいるかどうかというだけの話だったりすることが多いんだよな。yaccがどういう仕組みで動いているのか理解したらyaccとかを使うほうが普通に良いような気がしてきた。
lexとyaccを使うという2つのプログラミング課題がでたのだけど、僕が集中して即座に数日で仕上げてしまったので、パートナーはほとんど何もすることがなかった。実際のところはお互いが仕上げるまで待ったのだけど、相手がギブアップして、仕方がなく僕のやつを共同で提出することになった。相手があまりに何もやってくれないので、この関係は3回めくらいで破綻して、最後のプログラミング課題は別々にやるようになってしまった。パートナーが「自分はプログラミングあんまり得意じゃないから・・」と弱音を吐き始めて、キミはG社にエンジニアとして勤めていてそういう弱音を吐くか・・と思って多少あきれたというのもあった。
この授業もやたらと時間がかかったけど、課題はどれも大変よい点が取れたし、中間試験もほとんど満点だったし、使っている時間は結局同じくらいだったと思うけど、前回みたいな感じではなく十分自分で制御できている範囲内での忙しさという感じだった。プログラミング課題は、文法的に正当なランダムなプログラムを出力するプログラムをテスト用に書いて、ランダムな入力に対して動作をチェックするといったテクニックなども駆使して徹底的にテストを行ったので、ほとんど完璧に近かった。
仮想関数テーブルを持っている継承のあるオブジェクト指向言語を実装してみるというのも、理屈では理解していても実装するのは初めてだったので、なかなか面白かった。
最後の課題はエクストラポイントが取れるオプショナルな課題がでた。最適化してなるべく少ない命令数でプログラムを実行できるようにしてみましょう、というもの。定数伝播やループ不変式の除去(きちんとやろうと思うとかなり難しい)などをしてください、という意図だったのだと思うけど、僕はここで前回の反省を踏まえて、なるべく馬鹿みたいな簡単な最適化で点数を稼げないかと考えてみた。そうしてみるととても簡単なチェックでオブジェクトの初期化の関数が大幅に削減できるということがわかったので、それを実装してみたら、何割か速くなった。これでよしとして提出したらそれがまたクラスで最高得点だった。まあエンジニアリングでは凝ったことをやるよりも簡単なことをやるほうがずっと効果的というのはよくあるのだ。
期末試験も相当手応えがあったし、成績発表日には今か今かと結果をチェックしたら、今回はA+だった! A+だと上位数パーセントには入っているはずだし、それまでの点数とその分布を勘案してみると僕はたぶんクラスでトップだったんじゃないかと思う。スタンフォードのコンピュータサイエンスの授業でトップクラスに入るというのもやればできるものだ。とはいえスタンフォードの実態をよく知らないうちは良い成績を取るのはすごく難しそうに思ったけど、僕の友達とか同僚も同じようにやれば同じようにできるだろうから、これくらいは普通といえば普通な気もする。
ここまでで8単位稼いだし、GPAは4.0をキープした。なかなかいい調子。コンパイラは得意分野だから当然といえば当然で、別の分野だとこんなに簡単にはいかないと思うけど、次はなんの授業を取ろうかなぁ。