はてなインターンを終えて2008年09月24日 21時25分

先に書いたように 8 月は株式会社はてなのサマーインターンシップに参加していました。もう第 2 回も終わろうかというころですが、遅まきながら私の場合についてまとめたい思います。

インターン生の 1 日

「インターン生の」とつけましたが、特に後半 2 週間は何らかのチームに参加しての開発だったのであまり社員と変わらないかと思います。就業時間は 10 時から 19 時となっており、朝は東京オフィスとビデオでつないだ全体ミーティングから始まります。ここでは前日のリリース報告やはてな社に関する活動報告、当日の予定確認があります。その後はチームミーティングで、チーム (数人) の各員が前日の作業内容、当日の作業予定を報告します。私が配属されたキーワードチームには近藤社長も所属しており、社長自ら各自の報告に質問や感想をはさむことも多々ありました。これらのミーティングは不必要に長引くのを避けるためかすべて立ったままで行われ、時間は合わせて 30 ~ 50 分ほどでした。キーワードチームは人数が多めだったため、ややチームミーティングの時間が長かったかもしれません。

ミーティングが終わると開発に移ります。インターン生は基本的に二人一組でチームに配属されるので、配属後しばらくは相方の ninjinkun とのペアプログラミングが中心でした。後の方になるとリリース予定日に追われて二人が別の作業を進めることも増えてきました。私はインターン生だったのでミーティング後はひたすら開発、一区切りついたら、あるいは行き詰ったら社員を訪ねて、サーバーでの確認やアドバイスを求めるという感じでした。社員の人は単純な開発作業に加えて、サーバー調整のためにインフラ・運用チームの人とのミーティングなど、小さなミーティングをいくつかこなしていたようです。

お昼は 13 時からで、週 3 回はオフィスランチが出ます。オフィスランチがないときもご飯だけは炊いてもらえ、別途お弁当屋さんからおかずだけ買って一緒に食べることもできます。炊き立てのご飯が食べられることによる開発意欲の向上は目覚しいものがあり、私などは「初日に来たときは今にも死にそうなくらい顔色が悪かったが、毎日オフィスランチを食べているうちにどんどん顔色が良くなっていった」(伊藤直也氏談) と言われるほどでした。ランチ後もお昼休みはゆったり過ごすことができ、私の場合は社内に転がっているクッションでお昼寝することもしばしばでした。

午後も開発は続きますが、ここで重要なのがフリードリンク・フリースナックです。パイの実やチョコボールといった甘いものをつまむことで脳に糖分を補給し、万全の状態で開発に臨むことができるのです。私はもっぱら緑茶 (ハトムギ茶系のお茶がなかったので) とチョコレート菓子で午後を乗り切っていました。と、ここまで書いて思い出したのですが、ドリンクやお菓子の種類はリクエストもできます (必ずかなえられるとは限りませんが)。十六茶や爽健美茶がほしければそうリクエストすればよかったんですね。

夜は大体 20 ~ 21 時くらいまで残っていました。オフィスランチが残っていればそれを夜食にすることもあります。私はそのまま家に帰ることが多かったですが、インターン生同士 (+ α) でインドカレーやラーメンを食べに行ったり、銭湯に行ったりもしました。

インターンに参加して

このインターンで、これまであまり経験がなかったサーバーサイドでのプログラミングとチームによる開発を体験することができました。成果であるランキング機能については ninjinkun の記事も参照してください。チームの皆さんに助けられつつ、自分がチームに、会社に、ひいては社会に少しでも貢献できたかもしれないと考えると、インターンに参加して本当によかったです。おかげでよりいっそうプログラミングを楽しいと思えるようになりました。

また、会社は顔が見える人たちだけで回っているのではないということも実感しました。はてなのエンジニアといえば伊藤直也さん田中慎司さんが有名ですが、それ以外にも多くの有能なエンジニアによって各サービスは支えられており、さらにエンジニア以外のスタッフも一体となってはてなは成り立っているということがダイレクトに伝わってきました。

ほかの会社を知らないので比較はできませんが、ユーザーにじかに使ってもらえるサービスを Web 上で提供したいというときに、はてなは開発者にとって素晴しい環境を提供してくれる場所であると思います。

はてなインターンに参加しています2008年08月19日 03時35分

現在株式会社はてなのインターンシップに参加しています。期間は全 4 週間で、前半 2 週間で製品レベルのコードを書けるようにし、後半 2 週間で実働中の開発チームに所属し実際のサービス開発に携わるという流れです。

前半の詳しいカリキュラムは「0×0018 till I die ? はてなインターンのカリキュラム」に紹介されていますが、実務に関われるようにするというだけあって密度の濃い内容となっています。特に大規模データ処理は私にとって未知の分野であり、はてなの実データを使った演習が受けられるというだけでも大きな経験となりました。

基本的にはてなでは Perl が用いられますが、私自身の Perl の経験は 6、7 年前にゆいちゃっとを改造し、4、5 年前にオブジェクトの作成をやったくらいで止まっていたので、今回インターンに参加するに当たって再入門として perldoc を読み直しました。といっても目を通したのは各種チュートリアルと構文、データ型、サブルーチン、演算子、関数などの一部だけですが、各課題についていける程度にはなったと思います。ちなみに perldoc を選んだのは、一番入手が簡単 (さらに無料) で信頼性が高い (なんといっても公式) と思ったからです。

また、文法的なことは perldoc を読めばすぐわかるのですが、意外とわからないのがライブラリパスの設定やテストの実行方法。私が見聞きした範囲だけでも私も含めたインターン生 4 人が prove コマンドの存在を口伝で知ったとのことで、言語自体に比べそれを取り巻く環境の情報は共有が遅れているのではないかと思います。perl-users.jp は真っ先に

  • アプリケーションディレクトリ
    • lib
      • モジュール.pm
    • t
      • テスト.t

というディレクトリ構成と use FindBin::libs と prove コマンドと cpan コマンドの使い方を教えてもいいのではないでしょうか。

話をはてなに戻すと、社内は開放的であり、静かではあってもほかの人に話しかけづらいという雰囲気ではありません。見渡せば小規模ミーティングもあちらこちらで行われています。京都は美人が多いですし、Web アプリケーションの作成、またはその裏側に広がる大規模データ処理に興味がある学生はぜひとも参加してみることをお勧めします。第 2 回の応募締め切りは明日 20 日までなので、迷っている方は急いで申し込みましょう。

SICP 読書会 #22008年06月10日 23時23分

yukky さん主催の SICP 読書会、その第 2 回に参加しました。今回はあらかじめ予習範囲を提示し、最初の 30 分間でそこを読み進めた上で、後はもっぱら範囲内の問題にあてるという形式でした。私の分も含め各人の解答は当日のチャットログから参照できます。

開始前の空き時間で最初のほうの問題をやっておいたのですが、それでも時間がぜんぜん足りなくて息切れしてしまいそうでした。予習復習をしっかりしておかないとちょっとつらいかもしれませんね。

丸括弧と角括弧

Gauche では (Scheme では?) 丸括弧の代わりに角括弧も使えるので、cond の条件節に使うと読みやすいと教えてもらいました。確かに読みやすくはなりますが、なんだか美しくないような気がするのは私だけでしょうか。

(define (square x) (* x x))

; b の n 乗を求める
(define (expt b n)
  (cond [(= b 0) 1]
        [(even? b) (square (expt (/ n 2)))]
        [else (* b (expt b (- n 1)))]))

ユークリッドの互除法

最大公約数を求めるアルゴリズムとして有名なユークリッドの互除法ですが、英語では Euclidean algorithm といって、「互いに割る」というようなニュアンスは直接的には含まれてないのですね。

反復的プロセスへの変換

累乗と乗算を求める関数を、再帰的プロセスから反復的プロセス (末尾再帰) に直せという問題が出てきます。いろいろ悩んだすえ、以下のように考えにたどり着きました。

; b の n 乗を求める
(define (expt a b)
  (define (iter b n acc)
    (cond ((= n 0) acc)
          ((even? n)
           ; ここをどう書くか
           )
          (else
           ; ここをどう書くか
           )))
  (iter b n 1))

iter はどういう関数かを考えます。S 式表記から離れますが、acc = 1 のとき exp-iter(b, n, 1) は b^n を返します。n = 0 のとき、iter(b, 0, acc) は acc を返します。これらから考えていくと、iter は iter(b, n, acc) = b^n * acc という関数であることが推測されます。n が偶数のときは n / 2 が整数ですから、

  b^n * acc
= b^(n / 2 * 2) * acc
= (b^(n / 2))^2 * acc
= (b^2)^(n / 2) * acc

という変形が成り立ちます。n が奇数のときは、

  b^n * acc
= b^(n - 1 + 1) * acc
= (b^(n - 1) * b) * acc
= b^(n - 1) * (b * acc)

となります。つまり、

  • n が偶数なら iter(b, n, acc) = iter(b^2, n / 2, acc)
  • n が奇数なら iter(b, n, acc) = iter(b, n - 1, b * acc)

となるのです。後はこれを S 式に戻してやれば以下のように完成します。

; b の n 乗を求める
(define (expt a b)
  (define (iter b n acc)
    (cond ((= n 0) acc)
          ((even? n) (iter (square b) (/ n 2) acc))
          (else (iter b (- n 1) (* b acc)))))
  (iter b n 1))

フィボナッチ数の対数的ステップでの計算

問題 1.19 は線形写像の行列表現を利用してフィボナッチ数を O(log N) のステップ数で求める問題です。(bq+aq+ap bp+aq)T = Tpq (a b)T から行列 Tpq が求められるので、Tp′q′ = Tpq2 より p′、q′ も求められますね (行列の右肩の T転置を表します)。

四元数

なぜか SICP とはあまり関係のない四元数の話も出ました。四元数は応用として 3 次元空間での回転を表現するのに用いられますが、四元数そのものは実 4 次元ですよね。

SICP 読書会 #12008年05月17日 02時45分

書くのが遅くなりましたが、先日開かれた snow-bell さん主催の SICP 勉強会 (計算機プログラムの構造と解釈の読書及び演習) に参加しました。SICP 勉強会は午後からだったのですが、同じ会場で午前中に Gauche 勉強会 (私は不参加) も開かれており、チャットログも合同となっています。他の参加者の記事はSICP勉強会のまとめと異業種交流会 - snow-bellの日記からどうぞ。

組み合わせと合成手続き

Scheme の式 (expression) には組み合わせ (combination) と合成手続き (compound procedure) がある。式を評価したとき、組み合わせならば部分式 (リストの各項) が再帰的に評価されるが、合成手続きでは部分式が組合せとして評価されるとは限らない。

たとえば、手続き定義 (関数定義) (define (square x) (* x x)) は合成手続きであり、この式中の (square x) は組み合わせとして評価されるわけではない (ここでは関数 square に値 x を適用しているわけではない)。

作用的順序と正規順序

引数をすべて評価してから関数にそれらを適用するのが作用的順序の評価 (applicative-order evaluation)。関数の内容を先に展開し、引数が必要になった時点でその引数を評価するのが正規順序の評価 (normal-order evaluation)。

評価順 言語例 SICP 別称
引数が先 Scheme、C 作用的順序の評価 正格評価 (strict evaluation)、先行評価 (eager evaluation)、値呼び出し (call-by-value)
関数が先 Haskell 正規順序の評価 非正格評価 (non-strict evaluation)、遅延評価 (lazy evaluation)、名前呼び出し (call-by-name)

それにしても normalregularcanonicalstrict にそれぞれ正規、正則、正準、正格と別個の訳語を割り当てていった人たちはすごいと思う。

1.1.6問題1.3

演習問題三つの数を引数としてとり,大きい二つの数の二乗の和を返す手続きを定義せよ.、私の解答は以下。

(define (f1.3 x y z)
  (cond ((and (>= x z) (>= y z)) (+ (* x x) (* y y)))
        ((and (>= y x) (>= z x)) (+ (* y y) (* z z)))
        ((and (>= z y) (>= x y)) (+ (* z z) (* x x)))
        (else -1))) ; must not come here

基本的な考え方としては一番小さな数を見つけ、それ以外の二つの数の二乗の和を返すというもの。比較に等号を入れているのは同じ数が複数含まれているときのため。しかし二乗の和を求める部分をまとめてないなど無駄が多い。

雑感

ちょうど書籍を買って積んでいたところだったので、一から読む勉強会はいいタイミングでした。各人の演習問題の解答を見ると、こんな風に書けたのかと思うところが多々あり勉強になります。

第 2 回は 5 月 31 日に Vim 勉強会、Kansai.pm と合同で行われるそうです。また、5 月 24 日には Kanasan.JS JavaScript 第 5 版読書会 #4 も開かれるので、関西の方は是非 (もちろん関西以外からでも) 参加してみてはいかがでしょうか。

Google の大規模データ処理2008年01月25日 19時59分

Google の鵜飼文敏さんによる講演会「大規模データ処理を可能にする Google の技術」に行ってきました。内容的には筑波大学で開かれたものと同じではないかと思います (「新ビジネスモデル」がそのままだったことなどから)。以下、上記記事に載っていないことを中心にメモから抜書きを。

此頃 Google にはやる物
現在 Google では Google の使命 (Google's mission is to organize the world's information and make it universally accessible and useful...) の早打ちが流行中。鵜飼さんは 50 秒程度、一番速い人は 30 秒程度。
Google の扱う情報
Google のいう「情報」はインターネット上のものだけに限らない (例: Google ブック検索)。
データセンター構築の方針
初期のころは「いかに狭い部屋にマシンを詰め込むか」、現在は「いかに故障した部品を交換しやすくするか」。
電力コスト
ハードウェア性能は向上したが、性能あたりの電力消費量は改善していない。
4 年間の電力コストがハードウェアコストの半分を超える。
スケール = コスト
大規模なソフトウェアは大規模なハードウェアを要求し、大規模なハードウェアはお金 (コスト) を要求する。
SQL DB は使わない
データの分析は単純なもの (合計、最大値、最小値、上位 k 個、フィルタリングなど) がほとんどで、DBMS の高度な機能は必要ない。
これらの分析処理は可換的、結合的なため処理順は任意。
MapReduce
Google の開発した大規模データ処理のためのプログラミングモデル。自動的並列分散化、耐障害性、I/O 最適化に優れている。
日本語での解説は Radium Software Development に詳しい。講演中に使っていた図及び例もほとんどそのまま。
Map、Reduce 関数は C++ で記述。
Map から Reduce に渡す処理を「シャッフル」と呼んでいた。内容的には「ソート」のほうが適切な気がするのに、なぜ「シャッフル」というのか?
Sawzall
MapReduce 上で動くデータ分析用言語。強い静的型のスクリプト言語。
限定詞によるループ、if の簡略化が可能。when (i : each int; queries[i].language = JAPANESE) { ... } (foreach (queries 中の query) { if (query.language = JAPANESE) { ... } } より最適化しやすいのか?)
Google での利用に最適化されている (フィンガープリントや日付が組み込みのデータ型になっているなど)。
例外処理はなく、異常時には undefined を返す。undefined は無視して処理を進めることも可能。
Bigtable
数千台のサーバ、テラバイト規模のメモリ、ペタバイト規模のディスクを扱い、毎秒 100 万 Read/Write を可能にするデータベースシステム。
疎な分散多次元表。(行, 列, タイムスタンプ) でアクセス。
行に対する操作はアトミック。
連続する数行をタブレットという単位にまとめて管理。
GFS (Google File System)、Chubby、SSTable といった Google のシステムの上に構築。
日本語での解説は steps to phantasien に詳しい。
タブレット
SSTable (不変二次元マップ) とログデータ (SSTable からの更新分) の組み合わせ。
SSTable は書き換えできないので、追加、削除分はログデータに記録する。ログデータがたまってきたら SSTable を作り直す。
データ量がもたらすもの
計算能力が増えると難しい問題が解けるようになるというのはよく知られているが、データ量が増えると解決不能だった問題が解けるようになるというのはあまり知られていない。
データ量の増加が可能にしたアプリケーションの例
スペル訂正 (「もしかして」機能など)。Web を文脈つきの辞書とみなす。
Google が公開している論文など
以上の技術の概要については Papers Written by Googlers で参照できる。
東京オフィスの位置づけ
東京オフィスはローカライズオフィスではない。

質疑応答では「もしかして」機能に関する質問が多く出ていました。「答えられない」という回答もちらほら。

「もしかして」で間違った結果をどう直すか
間違った結果を目視で直したりはしない。すべて機械処理。
テキスト処理は言語非依存。
BM 法を検索したら KMP 法が引っかかった
ユーザによってはそれが正しい。究極的にはパーソナライゼーションで解決すべきこと。
1 日にコードを書く時間は
日によって違うが、1 日 5 時間くらいコードを書く。レビューなどでコードを読む時間も多い。
日本語の処理に使っている知識は
日本語の知識の利用は皆無。品詞情報なども使っていない。
C++ をどのような言語として使っているか
基本的にオブジェクト指向言語として使っているが、部署によっては better C として使ったりテンプレートを使ったりすることも。
例外は使わない。Google の規模だとほぼすべての実行パスを通るため、見た目がわかりやすくなっても処理を追いにくくなる。
Android に関して、Java 言語を使いながら、Java ME 上のライブラリとしてではなく、既存のものと互換性のないプラットフォームとして作り出す必然性は
開発責任者がそのほうがいいと思ったのだろう。

終了後、鵜飼さんとのじゃんけんに勝って Google T シャツをゲット。さらに残って話を聞いていたところ、余った Google T シャツももらったので、結局白黒 2 枚の T シャツ (前面に Google ロゴ、背面に「I'm Feeling Lucky!」)をいただくこととなりました。