働きながらアメリカの大学院でCS修士号を取った

4年前に会社の福利厚生を使ってスタンフォードの授業を取ってみたら面白く、 働きながらでも続けられそうだなという実感を得たので、 2年後、受験を経てジョージア工科大学にリモートで通い始めた。 そして先日、ジョージア工科大学からコンピュータサイエンス修士号をいただくことができた。 画像の学位記は卒業式イベント用の非公式のもので、1~2か月すると Masterとちゃんと書いてある本物が来るらしい *1

興味あるしいつかは習得したいんだけどなかなか触る機会がない分野を勉強するついでに、アメリカでは何かと役に立つ *2 学位がもらえ、学費は会社の福利厚生でカバーされたし、 世界ランキング 45位 の良い大学を2年かからずに卒業できたので良いことづくめだったように思う。

この記事では、働きながらコンピュータサイエンスをリモートで学ぶ体験の感想や、授業の面白かった点などをまとめておく。 なお、ジョージア工科大学にも当然ながら普通にキャンパスに通う生徒がいるが、 この記事では本学のCSオンライン受講プログラムOMSCSの話だけ書く。

在学期間

2020秋入学で2022春卒業の計5学期を大学院で過ごした。 生徒だった期間は1年9か月なので、普通に2年かけて修士を取る人たちより少し短い期間で学位を取得できたことになる。

卒業には10個の授業を取る必要がある。1年に3つの学期があり、春と秋は2つ、夏は1つしか授業を取れないのだが、4つ授業を取った後に成績が良ければ各学期もう1つ授業を追加できるようになる。従って、元々の枠をフルに使い続けるとちょうど2年、6学期で卒業でき、この追加枠を使うと最短5学期で卒業することができる。 *3

最初の秋学期は子供が産まれた直後 *4 だったので様子見で1つしか取らなかったが、翌年春2つ取ってみてもそれほど大変さは変わらないなと思った *5 ので、夏に4つ目の授業を取った後は同時に3つ取る学期を2回過ごして卒業要件を満たした。

学費

各学期 $301 かかり、それに加えて各授業 $540 かかる。なので、5学期で10個授業を取ると $6905 で卒業できることになる。

これはとんでもなく安い。 スタンフォードで授業を取った 時は5単位の授業を1つ取るのに $6300 かかり、卒業にはその9倍の単位を取る必要があるが、 ジョージア工科大学はスタンフォードの授業1.1個分の額で卒業できてしまうことになる。

アメリカの無料オンライン大学 University of People という記事を年末見かけたが、これは授業料は無料だが期末試験の受講にトータル $4000 かかるというスキームらしいので、 つまりジョージア工科大学は"無料"の1.7倍しか費用がかからないことになる。 これは学士のコースの話らしい(コメントで気付いた)ので3.4倍と言う方がフェアかもしれない。

英語

僕は4年前に受けたTOEICが845点で、TOEICの点数を公言している友達が大体900点台後半なので英語のリーディングとリスニングはどちらかというと自信がない。 一方で、入学した時の記事TOEFL iBTが「102点でどの程度授業についていけているかを知りたい」というブコメがあったが、授業を聴く時も、教科書や論文を読む時も、グループ課題で他の生徒と話す時も、別にそこで苦労したことはなかった。むしろ、割とゆっくり丁寧に話してくれる先生が多いため、授業を1.2〜1.5倍速で再生していることがほとんどだった。

これは単に、コンピューターサイエンスに関する話であれば単語は大体知っていて、内容も文脈から推測しやすくなるので、日常英会話とかに比べたら簡単になるという現象な気がする。

授業の感想

CS6291 Embedded Software Optimization

組み込みシステムの最適化。コンパイラの授業と同じ先生がやっている。 僕はコンパイラの中だとバックエンドにしかほぼ興味がなく、この授業はコンパイラの授業のバックエンド特化版であるという評判を見て、コンパイラの方ではなくこっちを取ったのだった。 後に結局コンパイラの方も取ったのだが、レジスタ割付はどちらの授業でもやるものの、命令パイプライニングや分岐予測を考慮した命令のスケジューリングに関して議論されるのはこちらだけなので、その評判は間違ってはいない。ただ、僕の感覚では、コンパイラをまるごと作った方がやっぱり面白いなと感じた。この授業ではレジスタ割付の課題はどのオペランドをどのレジスタに割り当てるかを決めたら終わりだが、コード生成してベンチマークが改善するのを眺める方がよっぽど楽しめる。

CS6200 Graduate Intro to Operating Systems

修士向けOS入門。学部の時にOSの授業を取りたいと思いつつもいろいろな事情 *6 があって取らなかったのだが、この機会にちゃんと基本を抑えておきたいと思って取った。プロセス、スケジューラ、スレッド、メモリ、IOといったそれっぽい話題に大体触れる。OMSCSにはOSの授業が2つあってこれも両方取ったのだが、もう一方はOSそのものについての授業はほとんどないので、OSについて勉強したい人はこちらを取ると良い。が、普段ある程度低レイヤープログラミングをやっている人だと、まあ大体勉強したことあるねみたいな感じの内容ではある。学部時代にOSの授業を取らなかったことから来る不安のようなものが払拭できたのはよかった。

CSE6250 Big Data for Health Informatics

ビッグデータ。授業の名前にあるようにビッグデータのヘルスケアへの活用に直接興味があるわけではないが、機械学習ビッグデータについて学べる授業なので取った。微分線形代数は久しぶりに触れて、大学数学を復習するのに丸一日使うといったことがあった。 この授業を取る前は機械学習はやったことがなかったが、かなり広範な技術を一通りカバーする内容になっていて、とても良い入門になった。具体的には、課題を通してNumPy、pandas、scikit-learn、Hive、Pig、Spark、PyTorchの全てに触れるので、機械学習ビッグデータ大体やったことあるなみたいな気分になれる。グループの自由課題では人間の睡眠データから病気になる確率を予測するモデルをPySparkで作ったりした。個人的に面白いと思ったのは生徒間で機械学習のモデルの性能をKaggleコンペする課題が2回あることで、しかも順位が成績に影響するところ。公開データセットでは1位だったが、最終順位が出る非公開データセットでは一気に29位に落ちるとかあった。

CS7643 Deep Learning

ディープラーニング。この手前に取ったCSE6250でもディープラーニングに触れはするしPyTorchの使い方くらいは学べるのだが、この分野一つをとってもたくさんの要素技術があるので、ちゃんとディープラーニングに関して理解したければこの授業を取った方がいいと思われる。人気のある授業で、割と最近追加された授業なこともあり、かなり新しい論文の内容にも触れるのが良い。バックプロパゲーションの基礎、CNN、言語のモデリング、AttentionやTransformerなどについて学ぶ。 この授業にはKaggleコンペはなかったが、現場で最先端の精度を出すのに使われているモデルはこうやって動いているんだなという意識があり、楽しんで取り組めた。グループ課題では食べ物の写真からレシピを生成するモデルを作った。 レシピのデータセットを触ってると、前職クックパッドのレシピも出てきて面白かった。

CS6250 Computer Networks

コンピュータネットワーク。インターネットを支える技術を一通り触る感じ。当然ある程度知ってる話も多かったけど、一度もTCP/IPについて体系的に学んだことがないみたいな不安がなくなって良い。 BGPとかネットワーク屋さんじゃないと普段触れることはなさそうだし。 インターネットで障害が発生した時に原因についての議論がある程度理解できるようになったり、何かをダウンロードしてくる時の速度の変化について後ろでどういうアルゴリズムが動いてそうなってるのか多少想像することができるようになって楽しい。

CS6515 Intro to Graduate Algorithms

修士向けアルゴリズム入門。卒業要件を満たすために重要になるため履修登録的な意味で人気な授業。僕の場合これが実質必修だったので取ったが、アルゴリズムの問題は純粋なパズル的面白さがあるので楽しめた。 動的計画法、分割統治法、高速フーリエ変換RSA、グラフアルゴリズム、最大フロー問題、線形計画法、P vs NPなどを扱う。学士で扱うよく聞くようなアルゴリズムAtCoderで水色を取る活動をしていた時に復習していたのだが、そこでは学べなかったアルゴリズムをここである程度知れたのはよかった。 こういう知識を活用する頻度が普段そんなに頻繁に発生するわけではないが、スケーラビリティとか計算量の複雑性とかを議論する際、ある程度複雑な理論を理解した経験があると、それより少し易しい話をしている時に確かな自信に裏付けされた議論や心の余裕ができる気がする。

CS8803 Compilers - Theory and Practice

コンパイラコンパイラのフロント、ミドル、バックエンドの理論を全部触り、大学教育に使われるTigerというプログラミング言語MIPSコンパイルするコンパイラをスクラッチする課題がある。 正直独学でかなり手を動かしてきた分野なので最初からほとんど知っていたが、あんまりフロントエンドに興味がないのもあり、そこの基礎であるNFAやDFA、LLといったところの理論を抑えられたのはよかったと思う(多分自分では勉強しないから)。Ken Thompsonは正規表現をNFAに変換するアルゴリズムも発明していてすごいなあとか。

僕は過去にいくつか言語処理系を作っているが、大体はインタプリタでコード生成が不要か、LLVMとかを使ってコード生成をしているとかで、アセンブリを直接吐くコンパイラを一から最後まで書き上げた経験がなくて *7、それが今回できたのはよかった。レジスタ割付をやるとバックエンドやってる感が出て良い。TAや他の生徒とコンパイラの性能でランキングを競えるのが楽しかった。

CS6210 Advanced Operating Systems

OSの発展的内容を扱う授業。OSに関しての理解は前提知識とされる授業で、OSそのものに関する授業はほとんどない。 かわりに、OSを使ったシステムデザインや分散システムにひたすら触れるという感じの授業。 毎週3~4つくらいの独立したシステムやアルゴリズムに関する議論が行なわれるので、割と密度が高い。 システムデザインの議論が好きな人は楽しめそうな内容だが、扱われるシステムが結構古かったり、アカデミアの外では使われていないようなものだったりと、よく実用されているシステムの設計について議論する他のクラスに比べるとやや興奮度の低い内容だった。 ただ、分散システムの話題にもある程度触れ、後述する分散システムの授業で何度か言及される授業なので、取っておいたのはよかったと思う。

CS6460 Educational Technology

EdTech。技術の教育への応用という分野には興味はないのだが、これは普通に履修登録できるクラスの中で唯一、多少自由にテーマを選んで研究ぽいことができる授業なので、修士論文を書かずに卒業するかわりにここで多少研究の経験を積んでおくことにした。 学内の教授と知り合いになると、その先生に一筆書いてもらうことでCS8903というコースを取り普通に研究をして単位をもらうことも可能なのだが、特にそういう関係を築くチャンスもなかったので、気軽に取れる方を取った。

実際この授業では論文の見つけ方、論文の読み方などを教わった後、何度も論文ぽいものを書いて添削してもらう経験ができる。ただ、研究そのものの経験はできるものの、研究の成果物は何らかの方法でEdTechに紐付けないといけない。一方、任意のテーマについて教えるコンテンツを作る、といったものでも教育に関連してるとして許容されるため、例えばポーカーの戦略についてまとめるサイトを作っている人もいた。 僕は割と本当にEdTechぽいがちゃんと自分の興味もある課題をひねり出した。具体的には、画像やサイト内のテキストから知らない英単語を抜き出し、任意の辞書で意味を調べ、それを自動で単語帳アプリに登録するみたいなものを作った*8。 英語の語彙が弱いので、単語帳で勉強する労力を下げられるようなものを作れてよかった。

CS7210 Distributed Computing

分散システム。僕が取った奴の中では一番最近追加された授業で、入学時点ではこういう授業がなくてガッカリしていたのだが、取れてよかった。 社内の輪読で割と分散システムに関する論文を読んでいた経験から、これも知っているか業務の経験から理解しているものがちょくちょくあったが、分散システムの基礎的な範囲をいろいろ触っているので知らないものもまあまああり、結構勉強になった。 論理時計、一貫性、レプリケーション、 分散合意などに触れる。Amazon AuroraGoogle Spannerのような、流行りのクラウドが採用しているアーキテクチャに関する議論があるのもとても楽しい。

この授業で良いのは全ての宿題を通して分散KVSを作るところ。スケーラビリティのためにシャーディングが可能で、各シャードを扱うクラスタはPAXOSで書き込みのログをレプリすることで耐故障性を実装し、そしてそのクラスタ間で2フェーズコミットを使うことで複数シャードにまたがる分散トランザクションを実装するというもの。で、これを実装する際に分散システムを作るフレームワークのようなものを使うのだが、それを使って実装すると、その実装で発生する状態遷移の組み合わせを全て検証するテスト、つまりモデル検査(TLA+みたいな奴)のようなことが可能になっていて、あらゆるコーナーケースで分散合意と進捗を保証しないとテストが落ちるようになっていて、これが難しい。分散システムの設計力が真に試される課題で、面白かった。

おすすめ

僕のお気に入りは CS7210 Distributed Computing と CS8803 Compilers。 単に僕個人の好みの分野で選んでいるという感じもあるが、上述したような課題の実装はやったことがなくてやってみたい、という人が受けたら確実に楽しめる内容だと思う。 ちなみに OMSCentral という授業レビューサイト上では、これらはそれぞれWorkload 1位の授業とDifficulty 1位の授業なので、最難関の授業でもある。楽な授業を取るより、本気で取り組んでやっと満足な成果が出る方が面白い。

成績

GPA: 3.90 / 4.00 だった。Deep Learningがあと0.55点あれば完璧な成績表 *9 になってたのが惜しい気持ちだが、もっと余裕でボーダーを超えられる実力をつけられていなかったので仕方ない。

学期 番号 名前 Grade 点数 A要件
2020 Fall CS6291 Embedded Software Optimization A 94.96 86
2021 Spring CS6200 Graduate Intro to Operating Systems A 87.2 80
CSE6250 Big Data for Health Informatics A 96.36 90
2021 Summer CS7643 Deep Learning B 88.95 89.5
2021 Fall CS6250 Computer Networks A 90.54 90
CS6515 Intro to Graduate Algorithms A 96.12 85
CS8803 Compilers - Theory and Practice A 94.23 87
2022 Spring CS6210 Advanced Operating Systems A 93.78 89.5
CS6460 Educational Technology A 96.75 90
CS7210 Distributed Computing A 89.2 84

まとめ

比較的安い授業料でいろいろ学べて楽しい。 修士を持っている人や、博士を持っていて他の大学で教師をやっている人もここで生徒をやっていたりするので、もう学位は持ってるという人も気軽に学び直しに来れる場だと思う。

*1:この部分は元々注釈で説明していたけど、読まれていなくて誤解が発生していたので、追記で本文に変更した。

*2:例えばソフトウェアエンジニアがH1Bという就労ビザを取ろうとすると、アメリカのCS修士があると2回抽選を受けられるが、学士や日本のCS修士では1度しか受けられない。また、グリーンカードを取る際も、学士ではEB-3、修士ではEB-2、博士ではEB-1という風に使える申請カテゴリが変わり、当然より良い学位を持っている方が一般には申請が早く済む。

*3:どうも基本的に皆フルタイムで働いてるからか、この枠をフルで使い続ける人は少ないようで、多くの人は3-4年かけて卒業するらしい。このプログラムのディレクターであるDavid Joynerに見せてもらったグラフの年では、最短の5学期で卒業したのはたった1%、6学期で卒業したのは5%しかいなかった。YMMV。

*4:なので、授業は子供が寝てから自分が寝るまでの時間だけ取り組んでいた。従って平日か休日かに関わらず20-24時の1日4時間が基本という感じだった。

*5:僕は締切が近付かないとあまり生産性が出ない人間なので、同時に3つ授業を取ると締切の数が3倍になり、従って生産性も3倍になるため効率がよかった。

*6:学部の4年間ずっとプログラミングのアルバイトをしていたのだが、さっさと卒業要件を満たして業務のプログラミングに専念する学期を作って社会人に備えたいという謎の危機感があり、3年前期までにほとんどの卒業要件を満たし、3年後期は実際必修を水曜朝1つ取ったらそれ以外はバイトをするという生活を始めたのだった。で、OSの授業はたまたま3年後期に予定されている授業だったため、自分個人の予定と折り合いがつかなかったという感じ。

*7:学部の授業で、先生が用意したx86アセンブリを吐く実装を少し拡張するみたいな課題はやった

*8:個人開発を黒字にする技術 https://k0kubun.hatenablog.com/entry/surplus で話していた奴はこれのこと

*9:点数は残らず、公式な記録はletter gradeしか残らないため

個人開発を黒字にする技術

最近は個人開発は自分のOSSのメンテで手がいっぱいになってしまったのでサービス開発のようなものは普段あまりやらないのだが、大学院*1で今学期、何作ってもよいという感じの授業を取ってWeb/iOS/Androidアプリ*2を全て作るという体験をする中で、たまたま個人開発のコストを抑える活動をしたので、その時に調べたり考えたりしたことを書いておく。

Herokuで無料にする

Herokuでは毎月550時間free dynoが使え、クレジットカードを登録しておくと更に450時間、合計1000時間無料で使える。Herokuは30分アクセスがないと一旦停止するが、今回授業で作ったサービスでこれを使い切らないことは明らかだったので最初はこれでセットアップした。セットアップも簡単だし、PostgreSQLも無料でついてくる。

ただ、コールドスタートに10秒くらいかかり、これがこのサービスではUX的に致命的だったため、元々運用していたVPSに同居させることで高速化を図った。

安いVPSの選定

個人VPSは10年くらい持っていて、これまで様々なVPSサービスを試してきたが、今回いろいろ整理する前はConoHaを使っていた。最初はDBサーバーとVPS 1台で2484円という感じだったが、安くするためにDBをVPS同居にして1848円までは圧縮した。

ただ、今回もう一つサービスを足すにあたって、当時のVPSではもう一つWebサーバーを立てるほどキャパシティに余裕がなく、かといって家計を削って値段を上げるのもなあという気持ちもあった。そもそも、USに移住したので日本のVPSだとレイテンシにやや不満があった。

そこで、安くてリソースが多く、可能なら自分に近いリージョンのVPSを真面目に調べ直した。結論を書くと、個人開発のコストはDB次第という記事のブコメにも書いた vCPU 4コア / 8GB RAM / 100GB NVMe *3 で月 $8.24 のVPSを発見し、それを使っている。ContaboのCloud VPS SのUnited States (Central)がその値段で、EUだと月 $6.99、Asiaだと月 $9.99 になる。

他にもいくつか有望ぽい奴は見つけたが、VPSCOMPというサイトで見つけたものが多かった気がするので、とりあえずこのサイトで好みのやつを探していただくのが良いかもしれない。

サーバーメンテの労力を最小化する

Kubernetesをやめる

4年前に練習用途で個人サーバーをKubernetes化したのだが、ある日突然クラスタがクラッシュして再起不能になったこともあったりと管理コストが無ではないし、Kubernetesそのものがめちゃくちゃリソースを使うのでサーバー代はかさむし、会社で自分のチームがEKSを使い始めて触りたければ触れる状態になったので個人サーバーではやめることにした。今はものすごく素朴に動かしているので、突然何かがクラッシュするみたいな状況は見ないし、したとしてもsystemdがサービスを再起動して勝手に直ると思われる。

式年遷宮を自動化する

自作プロビジョニングツールであるmitamaeを使って個人サーバのセットアップを自動化しており、これは何年も秘伝のタレ的に使い続けられている。Ubuntuのバージョンを上げる時にdist-upgradeで済ませたこともあるが、サーバーを立て直す労力がそこまで高くないので、VPSごと立て直してしまう*4ことが割とある。これでついでにDBサーバーのバージョンも上がりDBメンテ相当になるが、個人サーバーなので多少のダウンタイムは許容できるし pg_dump してrestoreしてくるけど、9GBほどのDBではすぐ終わる。そんな頻繁に必要なわけじゃないし、例の記事がいうほどDBサーバーのメンテナンスは大変ではない気がしている。

Let's Encryptの自動化

Let's Encryptの証明書が3か月おきに失効するので、これの更新がうまくいっていないのを誰かに指摘されるということが多く、プロビジョニングが自動化された環境下ではこれが一番運用労力がかかっていた印象がある。普通はcertbotを使えばいいと思うのだが、何か割とセットアップに手こずった記憶があり、Ruby製のacmesmithを使っていて、自分の得意な言語かつ読みやすいサイズなので何かうまく動かなくてもコードを読むことでどうにかしやすくなった。ここ最近は壊れることがなくメンテナンスフリー。

Google AdSenseの設置

サイトに広告を一切貼っていなかったころ、VPSの運用負荷を下げすぎてほとんど触ることがなくなり、しかもそこで動かしているアプリもそんなに触る動機がない状態になり、金の無駄なのでVPSを止めるか検討したことがあった。ただ、多少アクセスのあるサイトを動かしていたため、止める前に試しに広告を貼ってみたところ、ConoHaのVPS代より売上がコンスタントに出る感じだったので、そうすることにした。

Gitstar Ranking *5 という、GitHubのスターの合計数でランキングを出すという非常に浅ましいサービスを8年前に作ったのだが、1日1000~2000PVくらいしかアクセスがないのに毎月$20-30くらい売り上げている。画面全体に出る広告は使っておらず、自分のPCの画面サイズではトップページでファーストビューに入ってこない程度に控えめにしか貼っていないのだが、それでもクリックしてくれる人がいるらしい。

モバイルアプリの公開費用

授業の成果物のため、React Nativeを使ってiOS / Androidアプリを作ろうとしたところ、作ろうとしているものの要件上やや厳しい感じになり、そこがFlutterでは問題なさそうな感じなので、今回Flutterを使って簡単なモバイルアプリを作った。

DartとFlutterに関する感想はこの記事ではおいておくが、他の生徒にアプリをテスト公開するにあたり必要になったコストの話を書く。金はかかったが、元々動かしていたサーバーから発生している利益の中には収まってそう。

Firebase

今回作ったアプリではGoogleアカウント認証を使っていて、これは本来Web Viewを使うと別にFirebaseとか使わなくても実装できるのだが、それを実装しているサードパーティのFlutterプラグインが壊れており、公式が提供しているFlutterプラグインを使ったところ、流石Google、これは裏側にFirebaseが使われており、途中から有料になるサービスをまんまと使い始めさせられてしまった。ユーザー100人までは無料で、それに到達しなさそうなのでそのままやっているが、まあいざとなったらFirebaseを気合で外せばよさそう。

Google Play Developer Program

Androidアプリの評価に関してはapkを配布するというのでもよかったのだが、他の生徒がアプリの評価に参加する障壁を下げるため、Google Playが公式に提供しているTesting機能を使うことにした。これは $25 払ってGoogle Play Developer Programに入らないと使えないが、1回払ったらそれで終わりだし、額的にもAppleのそれに比べたらとても良心的だと思う。なおProductionのレビューも通したので今は普通に公開リリースして使っている。

Apple Developer Program

iOSアプリの開発でお賃金をもらうのをやめてから9年くらい経つが、少なくともTestFlightにアプリを公開しないとiOSユーザーの生徒にテストしてもらえないため、9年ぶりに再加入した。これはもう更新しないつもりで使っているが、年 $99 というのは高いなあと思う。今はPixelユーザーで次はiPhoneにしようか検討しているのだが、自分でアプリを作って使いたくなった時に年 $99 払わされるのは厳しいのでうーむという気持ちになっている。

確定申告

USに住んでるのでありとあらゆるものを確定申告しているのだが、この辺のコストをAdSenseの売上の経費として申請すると節税で更にコストが抑えられる。

まとめ

特にマネタイズに気持ちがなくて大して使われてないサービスでも、ほぼ無の運用労力と控えめな広告だけで黒字にでき、それで残りのサービスは自由にやることができる。

*1:今週期末試験が終わって、点数はまだ確定してないけど、明日卒業式。家庭の事情により出席しないけど

*2:厳密にはそれと連携するChrome拡張も作って公開している

*3:本来50GB NVMeか200GB SSDの2択なのだが、契約した当時はその時契約すれば同じ値段でNVMeが2倍の容量使い続けられるというキャンペーンがやっていた

*4:これを式年遷宮と呼んでいる

*5:元はGitHub Rankingという名前だったのだが、GitHubに怒られたので変えた

2021年にやったこと

というわけでこれ毎年書いてるんですけど、 なんか参戦したくなったので Rubyist近況 Advent Calendar 2021 24日目です。 入居者募集 記事があるくらいですし、自由に書こうと思います。メリークリスマス。

発表

1歳児がいる状況で家を留守にしたり夜に声を出したりすると家族に負担がかかるので、録画提出できるカンファレンスにしか基本参加しないことにしているのだけど、コロナが長引いていることにより今年も登壇しやすい状況が続いた。

とはいえ、ハイブリッド開催だったRubyConfに関しては、国内の渡航だけでShopifyのYJITチーム全員 (や当地のRubyフレンズ) と対面で話せる貴重な機会だったので、行けなかったのは惜しいなあと思う。シリコンバレーっていうテックっぽい田舎があるんですが、全てのカンファレンスをここで開催しませんか?

2015年は10本、2016-2019年は6-7本、2020-2021年は3本というトレンドになってきており、若さからくる勢いを失った感じがするが、そんなことより家族との時間の方が大事である。

あとRuby RoguesというPodcastでまた話した。2018年に2回話してるので、今回で3回目。5年前にtimakin社長と僕がやっていた幻のPodcastがあって、今も自分でホストできる状況にはないものの、各所からワンショットでゲストとして呼ばれるみたいなのはいつでもお待ちしております。

仕事

初めて職業プログラマ(ただしアルバイト)になったのが2011年5月なので、プログラマ歴10年になった。プロプログラマ。前前前職と前前職は真面目に大学とサークルをやっていたころだったので勤務時間はあまり長くなく、さっさと単位をほぼ取り終えてサークルをやめ*1、2013年10年から週に1コマだけ取って残りは全部働く社畜*2になりそのまま新卒になったのが前職なので、そういう意味では実質の経験は8年。いやあ、2004年にまだプログラミングも知らず、HTMLをFFFTPでinfoseekにアップロードしてスーパー正男を使ったゲームを公開していたころからここまで長かったですね。

で、やっと現職の話をすると、おかげ様で現職よりも待遇が良い会社がシリコンバレーですら見つけるのが大変な状態まで厚遇されている上、元々やりたかったような仕事に手が届く社内地位を得つつあり、グリーンカードのプロセスをリセットしたくないというのもあって辞めるモチベーションがなさすぎる状態*3になり、入社してもう4年半経った。2度目の昇進をしてSeniorの上のStaffというタイトルがつき、今年は1年中とあるプロジェクトのリードをしつつ、その裏で分散システムのスケーラビリティや性能改善のための新コンポーネント開発をやっている。もう触ってないのも含めて、僕が一番コミット数が多いか詳しいみたいなリポジトリが社内に結構ある*4けど、僕個人のリソースがスケールしないので知識のトランスファーを年中やっている状態なのだが、今のチームで僕の仕事の一つを引き継いだ人が辞めてしまったので、その人がその後やり始めた仕事も増えつつ、結局僕に返ってきた*5。前職でeagletmt先生が僕に知識を引き継いでいたところを、何故か僕が先に辞め、先輩が僕の書いたジョブキューを日々メンテするのを眺めている立場なので、文句は言えないと思う。

大学

成績発表〜!

  • Spring 2021
    • CS-6200 - Graduate Intro to OS: A (87.2%)
    • CSE-6250 - Big Data for Health: A (96.36%)
  • Summer 2021
  • Fall 2021
    • CS-6250 - Computer Networks: A (90.54%)
    • CS-6515 - Intro to Grad Algorithms: A (96.12%)
    • CS-8803 - Compilers Theory and Practice: A (94.23%)

ノルマクリア失敗! 全部Aを取るというのを今年の目標にしていたのだが、やらかしてしまった。ほとんどのクラスでは僕のやる気と余力と能力が点数に反映されている感じがするが、Deep Learningに関してはもう不服オブ不服である。授業で説明された理論はおおむね理解しているし、プロジェクトでもものすごい時間を費やしてかなりの理解が得られたが、残念ながら論文のクオリティを上げるといった作業より、コードをいっぱい書いてより多くの成果を出すというあまり点数に関係ないところに時間を使いすぎたようで、他のチームは大体成績がよかったところで大幅に点を削られてしまい、Aに0.55%*6だけ届かない結果となった。僕は学部時代もコードを一切書かないコンパイラの授業*7では点数が悪かったし、コードを書く以外の作業にやる気を出すのが得意でないことは自覚していきたい。

これらの授業を通して、OSのアーキテクチャ機械学習、pandas、scikit-learn、MapReduce、Pig、Spark、Scala、DNN、CNN、Transformer、pytorch、TCP/IPRSAFFT、P vs NP、LP、NFA、DFAレジスタアロケーションの実装、MIPSアセンブリ、その他多くを1年で学んだというのは、すごいインプットに倒した1年だったなと思う。学部のプログラミングに関する授業は(元々知ってる)CとJavaを1年かけて学ぶくらいの速度だったので、フルタイムで学生をやっていた当時よりむしろフルタイム社会人の今年の方がプログラミングについて圧倒的に多くのことを学んだと思う*8。成績表でも見せない限り「えー適当に流してたんでしょ?」とか言われそうな詰め込み具合である。全部完全に理解しました™ *9

個別の授業の感想は卒業した後にまとめて書こうと思うが、ハイライトとしては、同じ授業をたまたま同時に取ってた同僚と機械学習の宿題でKaggleコンペで競ったり、2人グループでTigerMIPSコンパイラを書くプロジェクトにソロ参戦して竹内関数のベンチマークでランキングを競う奴あたりが個人的に一番楽しかった。春学期にあと3つ授業を取ると卒業できるので、何事もなければトータル5学期(1年9か月)で卒業できる見込み。

US生活

ビザステータスでアメリカに入国してから2年が経った。コロナで家賃が下がって、立地も治安もよいリノベ直後の2ベッドルーム*10を $2,550/mo という安すぎる意味不明の家賃で確保してからというもの、更新の時に賃上げするんじゃないかとビクビクしていたが、今月の更新で家賃は上がらなかった。便利すぎる。グリーンカードのプロセスも大変そうだなあというイメージがあったけど、既に最終ステージで指紋採取も健康診断も終え、コロナで面接はないことになってるので、早ければ来年グリーンカードが取れそうな状態になった。トランプ政権が終わったので途中でビザのプロセスが遅くなったり厳しくなったりするみたいな可能性も低くなってそう。

車に子供を長時間乗せると睡眠や機嫌のコントロールが大変なので、家から車で10分以上かかるところにはほぼ行ってなくて、基本的に公園とスーパーと外食のテイクアウトにしか行かない生活をしている。外食は育児上の苦労が多いのとそもそも僕がケチなところもあり、コロナもある状況下の楽しみとして、料理に大分凝るようになった。これまで手を出してなかった揚げ物や低温調理など。いい奴を作りたい時は結構料理系YouTuberの動画を見てるんだけど、ステーキの焼き方が一番改善した気がする。同僚のtaroleoさんのfacebook記事を読んでreverse sear的な焼き方を学んだ時は「焼き目をつける」という工程をちゃんと理解できてなかった感じがするが、中に火を通す工程をじっくり終わらせて、その後表面だけを超高温で短時間加熱してカリカリにすると、食感が大分おいしい感じになる。

ところで去年は、ゲーセンが治安が最悪のところにしか音ゲーが置いてあるゲーセンがないと書いたが、SFベイエリアにいながらIIDX両皆伝を維持しているnobu_kさんに僕が懸念していた地域は実際には治安が良いと教えてもらった。ワクチン摂取が急速に進み全てがオープンになったころ、家族が留守にしていたタイミングでRound 1に行って、IIDX SP八段は取ってきた。ちなみにアメリカではコンマイのネットワークをラウワンが独占契約してるらしく、型落ちでない*11音ゲーをするには今はラウワンに行くしかないらしい。あと、テキサスホールデムのルールを覚えたので、ついでにカジノにも行って、一番レートの低い4/8 Limit卓のMin Buy-in $40 をそのままスッて来た。

ポーカーは地獄のようなセンスだが、資産運用はどうやら人並程度にはできるようになってきたようで、東京のソフトウェアエンジニアの年収くらいの利益はカタい状態になった。まあ、それでは家族3人ベイエリアで暮らしていくというのはできないので、まだまだ無限にお金を稼がないといけない感じがある。

ブログ

CI/CD Conの発表 数時間かかる週一リリースを毎日何度も爆速でできるようにするまで / CI/CD Conference 2021 - Speaker Deck が一番伸びてて、ブログの方はボチボチという感じなのだが、その中では以下が伸びた方。

ところで、学生のころにQiitaに書いた ActiveRecordのjoinsとpreloadとincludesとeager_loadの違い - Qiita が今でも色な人にincludesとかの説明資料として使っていただけているらしく、これを含めたその他いくつかの昔の記事が伸びていたおかげで、10k subs YouTuberの盾みたいな奴をIncrements社からいただいた。

しかし最近は人気YouTuberかのような活動は一切しておらず、超純粋に自分の備忘録としてのみQiitaを使っているため、ブログより多く書いてる割には最近の記事はLGTMが0とか1みたいな記事がほとんどである。ただ、もとからそういうコンセプトで続けていることによって、書くクオリティにプレッシャーがかからず自由に書けるのが便利なので、自分の記憶のためにこのスタンスは続けていきたい。それだけだとフリーライダーっぽいので、たまに記事がヒットしてIncrements社に利便性の対価が還元できると良いですね。

OSS活動

MJITでRailsを速くできるようにしたいというのは2017年から毎年毎年本当に毎年目標にしていたのだが、今年ついにそのパズルを解き、4年間にわたって取り組み続けていた目標を達成した。だが、逆説的に、なぜ遅かったかを理解した瞬間、「ああ、この方針はダメだな」と悟ったので、CRubyではCコンパイラ+dlopenでJITをするのはやめようという方針で活動している。で、YJITという別のJITを開発し始めたShopifyチームが、たまたま同時期にJITRails高速化を達成したため、MJITを置き換えようとしているMIRはもっと時間がかかりそうなこともあり、第一ステップとしてMJITはYJITに置き換えて(Cコンパイラ+dlopenを発破解体して)いこうという風になった。というか去年の末の時点ではShopifyチームがこの速度で成果を出してくるとは全く予想できなかったので、去年考えていたJITのロードマップとはかなり違う結末になったが、僕一人でメンテする状況ではなくなった上、MJITと違って極めて短いwarmupでRailsbenchで性能改善ができるようになったのはとても素晴らしいことだと思う。4月に最後の授業が終わったら時間に余裕ができるけど、YJITの発展が結構速くて春ごろの状況の予測が困難なので、今後どこに投資するかはその時になってから考えたいと思う。

CRuby以外の点では、主にsqldefrspec-openapi、その他もいろいろ、で継続的にissueやPRが来るのでその対応などをやっていた。Haml 6をHamlitが乗っ取るというのを作者にお願いされてそのパッチを書いてマージされたけどまだリリースされてないという活動もあった。今年、他の人がxremapをRustで書き直すという試みが2回行なわれたが、これは実は大分前から僕自身がやろうと温めていたアイデアでもあったので、今月の期末テストが終わったタイミングからの時間を使ってxremapをRustに書き直すというのをやった。スターもまた伸びて嬉しい。

GitHub Sponsorsで支援をいただいている方々には大変お世話になっております。OSSは、仕事で給料が十分いただけてるのとは別腹というか、割と真面目に全てのissueやPRに対応している分、趣味とはいえど、僕がその時最も興味があるプロジェクトとは独立してそこそこメンテ作業にプライベート時間を割いているため、ここで少なからずお金をいただけているのは当初の想定を超えるほど精神的な支えになっています。特に、Comcastで1Gbpsのインターネットをする料金が月$100とバカ高い*12のが経費になったり、生産性のためにマシンスペックを上げたりする時にこれも経費になったりするので、すごいケチな性格の僕としてはとても助かっています。

2021年は

今年は子供が寝てから朝5-6時まで宿題をやって提出して、朝7時に起きて子供と過ごすみたいな日が毎週ある感じだったけど、頭と腹は毎日痛くて、睡眠不足は寿命が縮まるしハゲるらしいので、来年は春学期でさっさとGPA 3.9*13で卒業して、その後は健康に過ごすことを目標にしたい。あとはこれ:

*1:大学公認サークルである学園祭実行委員をやめただけで、それと同時に非公認の東工大音ゲーサークルを立ち上げたので、勤務後や休日のゲーセン通いという名のサークル活動はやっていた

*2:バイトの時は有給を取ってなかったので、社会人の時より普通に勤務時間が長かった。実際この時が一番本来の新卒ぽい成長をしていたし、新卒と会社が同じだったことを利用してこの期間がまるでフルタイムのように履歴書やLinkedInで書きがちなのはそのため。書かなかったとしても必要以上に実力を低く見つもられてお互い損するだけな気がする。

*3:僕の給料を決める権限がある人にこういうのを読まれてしまうと交渉の立場が悪くなるのでこういうのはあまり書かない方が良いのだが、これを読んだとしてもフェアに決めてくれるだろうという信頼が既にある。

*4:特にTD APIって奴は、3年前までに1年だけ在籍していたチームのリポジトリなんだけど、何故かそのチーム内にはこれまで僕よりコミットしている人がいなくて、在職者の中で過去に僕よりコミットしたのは古橋さんだけ、僕の次はもうやめたkamipoさん、という渋い状態になっている。僕がリファラルしたmakimotoさんがそろそろkamipoさんを超えそうなので僕も抜いていって欲しい。

*5:倍返しだ!! というのはおいといて、この辺をやる僕のチームのSeniorポジションが2月くらいに開くっぽいので、これを読んでる人どうですか? Railsのコードを眺めたりちょっかいを出したりしながら、KotlinでバックエンドのAPIをバリバリ書きまくるみたいなのに興味があるルビーストがいたら是非リファラルしたいのでDMしてください

*6:予告通りAのボーダー90%はcurveしなかったが、roundはして89.5%以上がAとなったため

*7:コンパイラを書かないコンパイラの授業とは…? これで実際コンパイラ書けるようになるのか…? と思ったものだが、今もその教科書は持っているので眺めてみたところ、全てコンパイラフロントエンドの理論の話で、これは今回の授業の3つのパートのうち1つ目でカバーされていた。実際、コードを書く授業かに関わらずもともとフロントエンド側には興味がなくてそこだけ知識が薄かったので、実際に(Aを取るために)真面目に勉強してみると勉強になった。それ以外のパートは、特にレジスタアロケーションも何故か同じ教授の授業で全く同じレクチャー(完全にコピペだったので「[違うクラスの名前]にようこそ!」みたいな導入だった)を試聴済みだったのもあり、「知ってた」みたいな感じだった。

*8:プログラミングについて「は」、というのが正しくて、数学とか物理とか文系科目がその他の時間を占めていたため。

*9:まあBを取ってしまったディープラーニングに関してはもう何も言えませんが………

*10:西日暮里で住んでた2DKの1.5倍くらい広い

*11:型落ちDDRとかIIDXじゃないbeatmaniaは結構ある

*12:高い割には雨がちょっと降った程度で使えなくなるので意味がわからん

*13:もうBを1つ取って0.1削ったため

Linux用キーリマッパーxremapをRustで書き直した

このエントリはRust Advent Calendar (3) 22(-10)日目 の記事です。

5年前にxremapというLinux向けのキーリマッパーを作った (Linux向けの最強のキーリマッパーを作った - k0kubun's blog) のだが、X11のレイヤーで実装したため、GNOMEのActivitiesでリマップが効かなかったり、WaylandではXWayland内でしか動かないといった問題があった。

これらの問題を解決すべく、xkeysnailwayremapといったツールが後に作られたのだが、xkeysnailはWaylandで動かずwayremapはX11で動かない方針なのと、やはり全てのキー入力を中継するようなツールはPythonのような遅い言語よりRustみたいな速い言語で書かれるべきだと思ったので、後発のツール*1の良いところ取りをしながら今回xremapを作り直した。

github.com

Rust版xremapの設計思想

JSON互換な設定ファイル

mitamaeのように、宣言的な記述だけでなくlocal_ruby_blockといった動的な処理をサポートすることを念頭に置いたツールもあるが、xremapに関してはほとんどが静的な設定で十分で、キーの入力以外に必要な処理もそこにごく少数の拡張をいれれば十分であると考えた。Rust版xremapの設定は、あるキー入力を別のキー入力にリマップする設定は以下のようにできるが、

keymap:
  - name: example
    remap:
      M-c: C-c

文字列をキー入力を表現する型として使いつつ、キーを1つだけ持つ連想配列を関数呼び出しのように使うと、ある程度リッチな機能も静的な設定で表現できる((注: この記事を書いている時点ではこの launch 関数は実装してないが、すぐに実装できるようにはしてあって、割とすぐ実装する予定))。

keymap:
  - name: example
    remap:
      M-c: { launch: 'google-chrome' }

なお、C-x C-s のようなキーシーケンスをリマップする場合も、同じ仕組みでremapという関数を利用することで実現されている。

keymap
  - name: example
    remap:
      C-x:
        # 直後の入力でのみ以下のremapを適用
        remap:
          C-s: C-w

そして、JSON互換なことにより、RubyPythonのような言語内のDSLから生成したオブジェクトをxremapの設定にシリアライズするといったことが極めて用意になり、好きな言語が設定に使えるようになる。他のツールはPythonでしか設定できないけど、Rubyの方が好き、という人はいると思う。あと、Ruby DSLを維持するためにmrubyを使い続けようとすると、mrubyのビルドシステムで苦労したり、Rust<->Ruby間のブリッジを書かないといけないのが面倒そうだったので、設定を境界にツールを二分した方がメンテしやすそうだとも考えている。

なお、PoCとしてxremap-rubyxremap-pythonを作っていて、前者はmruby版xremapのDSLに近く、後者はxkeysnailのDSLに近いように作った*2。ただ、一旦リリースしてしまいたかった都合、現時点ではYAML用のドキュメントが一番充実している状態なので、ひとまずYAMLで使い始めていただく方が楽かもしれない。

Wayland対応

Xlibからevdev+uinputベースの実装に切り替えたことで、基本的な機能はWaylandプラットフォームでも動くようになった。ここはxkeysnailやwayremapも同じ。

問題なのが、これらのツールは「現在フォーカスしているウィンドウ」に応じてリマップする機能を提供していることで、これをポータブルにするのが難しい。Waylandはプロトコル内に「現在フォーカスしているウィンドウ」という概念がないようで、これをWaylandで動くコンポーザ全てでポータブルに判定するというのがどうも難しいらしい。Swayが使っているwlrootsというフレームワークを使っているコンポーザは多くあり、wlrootsのプロトコルを話すとそれらのコンポーザには対応できるのだが、GNOMEとかはwlrootsを使っていないので、2021年現在ではそれらに個別対応していく必要がありそう。

で、特にGNOME Waylandはxkeysnailもwayremapも対応してないようなので、それらとの差別化として、xremapはGNOME Waylandの個別対応をいれた。GNOME特有のJavaScriptD-Busに流し込むという奴なんだけど…まあ一切ポータブルじゃないのでその辺のツールがこれに対応してなくても文句いえなさそう。あと、GNOME 41以降では更に違う対応をしないといけないらしい。とりあえずUbuntu 20.04で使われているGNOME 3.36では動くようにしてある。

wayremapはSway向けの個別対応が入っているのだけど、wayremap作者のacro5pianoさん向けに、同じ対応をxremapにも入れた。

ちなみにこれらの個別対応は --features を使って別バイナリとして実装していて、これは何故かというと、libX11は静的リンクが困難ぽいので、動的リンクの依存が非X11向けバイナリには不要なようにするため。

Rustを使ってみた感想

実はRustは5年くらい前に使ってみたことがあるのだが、その時は今回ほど複雑なツールを作らなかったのでまともに入門したわけではなく、実際何も覚えてなかったので、今回初めてRustを学んだ状態に近い。せっかくなので、初学者のフレッシュな感想を書き残しておこうと思う。

難しすぎワロタ

参照以外の方法で値を読もうとするとmoveが発生して、それによりコンパイルが通らなくなる場面には多々遭遇するが、かといって clone()copy() で解決すると負けたような気持ちになるので、なるべく速そうなコードでコンパイルを通すパズルに頭を悩ませる時間が長い。とはいえ、これは他の言語では単にコピーが無限に発生して遅かったりスレッドセーフではない方法で参照を共有したりみたいな方法で解決されているだけの問題に見えるので、ここをサボらないようにするにはどうすればいいか考えること自体は人間が考えるに値する本質的な作業という感じがする。

しかし、これはかなりテクが必要な感じがしており、ある程度便利イディオムのようなものを吸収するまでは、実装しているアプリが解決しようとしている問題とはあまり関係ないところでかなり時間を消費させられる感じがある。例えば、&mut selfなメソッドがあるstructでは、&mut selfでmutableなborrowをしているせいでselfの他のフィールドをimmutable borrowすることができなくなる(と理解している)が、そもそもmutしないようなフィールドはそういうstructの外側で管理するようにすると、そのselfとは独立してimmutable borrowが(複数)可能になり、いろいろやりやすくなる、とか思ったけど、そういうプラクティスをあらかじめ知ってないと辿りつけない設計が必要だったりするように思う。

特にlifetime parameterはなかなか他の言語でお目にかかれない概念なので難しくて、これを使いこなしている人たちは本当にすごいと思う。Goとかは仕様がとてもシンプルな分、ある程度期間をあけて触ってもすぐに理解できる良さがあるが、Rustは高度な言語機能で全てを解決する方に振り切れている感じがしており、Rustで何かを書いた後少し離れて少し忘れてしまった時のことが心配ではある。

コンパイラのエラーメッセージがよくできてる

Ruby 3.1にもerror_highlightというエラー表示を見やすくする機能が入るが、Rustに関してはムーブセマンティクスとlifetime parameterがあちこちで干渉しあってる時にそれらの原因を可視化するというのが明らかに大変そうなのにちゃんと実装されている。lifetime parameterのエラーはコンパイラの指示に従っているだけで一旦コンパイルが通るといったこともあった。まあちゃんと理解してないと次のステップでコンフリクトして詰みとかも普通にあったけど…。

IDEはあった方がいいけどやや不便

Kotlinを書き始めたころ、Vimで快適にKotlinを書くための良い環境がなかったのでそこからIntelliJを併用するようになったのだが、特に学び始めでよくわかってなかったり、importなどそもそも全てを手動で書くのが面倒な感じの言語ではIDEは便利だと思う。モジュールとかimportのやり方をまだ完璧には理解できてないのだが、他の言語とかでも使えるインポートのキーバインドを叩くだけで勝手に適切なimportが挿入されるのは初学者には嬉しい。

で、これはJetBrainsのIDE特有の話なんだけど、JetBrains製エディタのRustプラグインは基本的な機能は揃ってるものの、KotlinやJavaのようなIntelliJの本命っぽい言語に比べるとややサポートが弱い感じがする。例えばunused importをIDEが教えてくれなくて、コンパイラのwarningがIDE上ではどの行のことなのか丁寧に追って消すみたいな作業が必要になる。とはいえ、IntelliJの操作に慣れている点が便利なので、他に便利なRust開発環境が現れることよりもJetBrainsがRustに投資してくれることを祈るばかりである。

? 便利

基本的に難しくて大変だし ; 書くの面倒だなあという印象が強かったけど、Rustのシンタックスで唯一感心したのが ? で、これは例えばGoで以下のように書くよくある奴が、

foo, err := bar()
if err != nil {
  return err
}

以下のように短く書けるという奴。

let foo = bar()?;

僕はどちらかというとエラーバケツリレーよりは例外がある言語の方が基本的には好きなのだが、バケツリレーのための追加記述が ? の1文字で済むというのはとても良いと思う。

まとめ

xremapお試しください。既に常用できているけど、まだ足したいと思ってる機能がいくつかあるので、現時点ではないけど欲しい機能などあればコメントをいただければ優先度を上げたりできるかもしれない。

*1:xkeysnailやwayremapに加え、xremapをRustに書き直したrumap https://dawn.hateblo.jp/entry/rumap もその一つ

*2:が、特にPythonの方はlambdaでのマッチングをJSONに変換するといったことは難しいので、完全互換という風には作っていない

アメリカのビザ取得からグリーンカード申請まで

先週、会社のサポートによりアメリカのグリーンカード申請の最後のステージの提出が終わり、それが処理されるのを待った後少し事務手続をこなすとグリーンカードがもらえる状態まで来た。アメリカ移住に興味があるけど大変そうと思ってる人や、どの程度学歴が求められるか不安な人の参考になるよう、忘れないうちに全体のプロセスについてざっとまとめておく。*1

Diversity Visa

移民多様化ビザ。まず一番敷居が低い申請方法として、Diversity Visa Lottery (DV Lottery)というのがある。これは申し込むと抽選で誰でもグリーンカードが当たるという奴で、私もビザで渡米する前に2回挑戦し、両方外した。

申請条件

以下の2つを満たす必要がある。(詳細)

  1. 出生国がアメリカへの移民率が低い国であること (日本はok)
  2. 高校卒業か、最低2年の研修や経験が必要な仕事を2年経験していること

これを読めている多くの人は申請資格を有しているのではないかと思う。会社にアメリカビザをサポートしてもらえる状況にはない人も、これに申し込んで祈ることはできる。

所要時間

10月上旬から11月上旬の間にインターネットで申し込みが完結し、結果は翌年5月上旬から9月末にかけてわかる。 用意する書類の中で面倒なのはせいぜい写真くらいしかない。写真の条件はやや厳しいので、アメリカビザ用写真に対応しているカメラ屋さんに行って写真を撮ってもらって電子データをもらっていた。会社でまともにビザとグリーンカードを申請するのに比べるとすごく手間が少ない印象がある。

当選確率

DV-2021は全世界で11,830,707人、日本は30,565人の申し込みで、全世界で132,404人、日本は532人当選したので、当選確率は 全世界で1.1%、日本は1.7% といった感じ。10回申し込んで一度も当たらなかった同僚もいたりする反面、実際当たってる人もインターネットでは見かける。

Non-immigrant Visa

非移民ビザ。DV Lotteryを当てる強運を持っていない限り、最初にアメリカに移住する時普通はこれを取得することになる。全て挙げるとたくさんあるのだが、ソフトウェアエンジニアが使ってると聞くようなものは限られてるので、それらについてまとめる。

H-1B

就労ビザ。転職が可能であるため人気のビザ。ただ、抽選が必要で、必ずしも取れるわけじゃないのが特徴。3年間有効で、3年延長できるので、計6年使えることになる。

申請条件

専門性の証明のために学歴か職歴が必要になる。ソフトウェアエンジニアの場合は、

  • 日本でCS学士以上か、何らかの学士+6年以上の職歴: 通常枠
  • アメリカでCS修士以上: Advanced Degree枠

所要時間

H-1Bは4/1から申し込みができ、抽選結果は5月くらいに出る。6月に会社が追加でお金を出すとPremium Processingができ、面接の後7月ころ審査結果が出て、9月末から10月頭くらいに入国できるのが最速。

ただ、移民に厳しいトランプ政権下では進みが遅い年があって、2018年の人が翌年4月の入国になったり、そこで米国企業から反対が上がって2019年の人は10月に入国できたりしたが、2020年はコロナもあって発給停止になったりしていた。バイデン政権下ではそのようなことは少ないと思うが、進みの速さは運の要素が強そう。

当選確率

通常枠の抽選は一般に3分の1 (33%) の確率で当たると言われており、外れた場合も、Advanced Degreeにあたる場合は再抽選で少し確率が上がる (トータル45%程度)。

L-1B

転職できないが、抽選に依存しないビザ。H-1Bに落ちた場合に備えて、H-1Bと一緒に申し込みの準備を進めてくれる会社もある。3年間有効で、2年延長できるので、計5年間使える。従業員が1000人いるなどの条件を満たす大きめの会社はL-1 Visa Blanket Petitionというのを使うことができ、これがあると速やかな移住が可能になるらしい。そのくらいのサイズの会社に買収されると、ある日突然そういうのが使えるようになったりする。

申請条件

その会社の米国外拠点で1年以上働いていることが必要。

E-2

投資家ビザ。5年間有効。Eビザを発行するためには、ビザを発給される人と同じ国籍の *2 、米国永住権を持たない人たちがその会社を所有している必要がある。つまり、自分が日本人である場合、会社の株式の半数以上をまだグリーンカードを持たない日本人だけで保有していればこれが使える。やや厳しい条件だが、H-1Bのかわりにこれが使われるのを見たことがないでもない。

申請条件

管理職、役員、あるいは専門知識や技能の持ち主であることが必要。

O-1

アーティストビザ。プロスポーツ選手とかノーベル賞取ったみたいなすごい人が使う奴。自分はソフトウェアエンジニアでいうところの大谷翔平だくらい自信がある人が取るのだと思うが、僕は学歴が学士卒*3であることからも最初から諦めていた。

申請条件

卓越した能力の保持者であることを証明する書類を提出する必要がある。海外で著名な人から推薦状をもらったみたいな話を聞く。基本的にはPhDを持ってる人が通してるイメージで、CS修士で通してる人もたまに見る。

F-1

学生ビザ。アメリカの大学を卒業後 OPT (Optional Practical Training) を使うと1年間働くことができ、その間に別のビザにスイッチするといった使われ方をするらしい。

Immigrant Visa

移民ビザ。永住権、グリーンカードのこと*4。通常は大きくわけて3ステージあり、PERM、I-140、I-485 (AOS) に分けられ、これらを終えると晴れてグリーンカード取得となる。なお、これらを全て終えるには大体2-3年 *5 かかり、かつ転職や職務変更などで振り出しに戻ることがあることを考えると、普通はビザ取得直後にグリーンカード申請の準備を始めるのが望ましいと思われる。

申請カテゴリ

申請者のレベルが高い順にEB-1、EB-2、EB-3 ... といった申請カテゴリがあり、EB-1だとPERMは不要になり、一般にプロセスが速くなる。

  • EB-1: O-1を取るような技能があったり、国際企業の管理職であったりすると該当
  • EB-2: 修士以上の学歴か、学士と5年以上の職歴で該当
  • EB-3: 学士以上の学歴が必要

私は申請を始めた時点で5年の職歴があったけど、書類を作り始めた時点ではギリギリ足りなかったので、EB-3になった。ただ、EB-2とEB-3は独立したキューであって、どちらも処理が詰まっていない (Visa Bulletinに C = Current が書いてある) 限りはどちらでも速度が変わらない。

PERM

書類の準備が一番面倒くさいステージ。過去に所属していた会社から職歴を証明してもらう書類を集めたりする必要がある。大学の教授に推薦状をもらうといったことをやっていた人も見た *6

書類を集めたあと、申請者の職務を記載したjob postingをして一定期間放置し、アメリカには該当する技能を持つ人がいないことを証明する必要があり、それに必要な書類を要求して送られてくるまでの期間も含めるとこれに結構時間がかかる。一方、Googleのような年中グリーンカード申請をしている会社ではなんかそれっぽいjob postingをプールしていて、グリーンカード申請者はその後のステップから開始できるという話も聞いた。

なお、PERMは職種に紐付くものであるため、転職するとやり直しで、転職しなくても職務内容が大きく変わった場合やり直しになる。

所要時間

PERMを提出できてから承認されるまでは通常4-6か月かかる。その提出に必要な書類の準備が順調に進めても半年くらいかかるので、実際には1年くらいここで使うことになる。

I-140

これは雇用主の審査で、企業が規定の給料を払う経済的能力があるかどうかが審査される。書類を書いて出して処理されるのを待つ以外のことはあまりない模様。なお、I-140と次のI-485は並行して進めることができる *7

所要時間

ここで見れるが、私のケースでは7.5-8か月程度かかる見込み。

I-485 (Adjustment of Status)

最終ステージ。実際のグリーンカード申請にあたる。戸籍抄本を日本から取り寄せたり、両親の出生地や生年月日や現住所を調べたりする必要がある。健康診断の結果を提出する必要があるのもここだが、処理を待つ間に失効してしまうので、申請時点では健康診断の結果は準備しない。あと指紋採取をしたりするらしい。なお、AOS (Adjustment of Status) は米国内で申請を行なう場合に使うやつで、在外米国大使館で面接を受けるConsular Processingというやり方もあるらしい。

所要時間

11-23か月程度かかる見込み。これがボトルネックぽい。

その他

グリーンカード取得に必ずしも必要なわけではないが、普通PERMの次のステージでI-140やI-485 (AOS) と同時に申し込まれるForm 2つを紹介する。

I-131: Advance Parole

グリーンカード申請中はアメリカを出国できないみたいな話を見かけることがあるが、これがそれにあたる。実際には、H-1B、L-1BなどのDual Intent Visaと呼ばれるものを持っている場合はグリーンカード申請中も出国・再入国できるのだが、このAdvance Paroleはそういったビザが失効してもグリーンカード申請中は再入国できるように申請するもの。なのであくまで保険なのだが、これをI-140やI-485と一緒に出した後承認される前に出国してしまうとAdvance Paroleの申請は無効になり、ややリスクが上がる。そのためこのステージにいる間はアメリカを出国せず過ごすのが望ましい。

所要時間

4.5-6.5か月程度かかる見込み。半年くらい海外出張や一時帰国をしない前提になりそう。

I-765: Employment Authorization

これもAdvance Paroleに似た保険にあたる奴で、グリーンカード申請中に働く許可を得るためのもの。

所要時間

1.5-6.5か月程度かかる見込み。

弊社について

私がビザやグリーンカードの申請をスムーズにできるよう移民弁護士のサポートを受けられているのは全面的に会社のおかげなので、弊社の宣伝をしたい。We're hiring! 面白い仕事がいっぱいある上に金銭的待遇が良いだけでなく、ビザのサポートも手厚い会社だと思う*8アメリカだけでなく、日本からカナダへの移住をした同僚も複数いる。

Jobs - Treasure Data

参考記事

僕が申請前にお世話になったり、申請後見かけたりした関連記事の中でパッと思い出したものを載せておく。

*1:なお、基本的にはまだ何も知らない人向けにゆるめに書いた文章であるため、実際に申請をする人は詳細は必ず移民弁護士に確認を取ること。

*2:この縛りがあることは @yusk_ さんにご共有いただきました https://twitter.com/yusk_/status/1426262331684626434

*3:いまでこそアメリカのCS修士に在学中だが、卒業はしていないので今でも使えなさそう

*4:厳密にはDiversity Visaも当然ながらこのカテゴリに入る気がするが、記事の流れの都合上この構成になってしまった上にいい感じの見出しが思いつかなかったのはご容赦いただきたい。

*5:EB-2およびEB-3を想定している。なお、現在はいくつかの国は申請キューが分かれており日本は比較的処理が速くてこれなのだが、今後それが撤廃されてもう少し遅くなるリスクがあることに注意されたい https://redbus2us.com/hr1044-bill-passed-in-senate-summary/ 。ただ、通った後一気になくなるわけではなく、徐々に適用割合が増えていく感じぽいので、まだ申請してない人がめちゃくちゃ急ぐ必要があるわけでもなさそう。

*6:私は移民弁護士が大学のレベルのようなものを審査する機関から書類を取り寄せていて、それと私のdiplomaとtranscriptがセットで必要書類が揃った感じになっており、私はこれはやらなかった

*7:同時申請にはリスクもあり、特にdual intent visaでない場合は、非移民ビザがI-485を出した瞬間原則失効するので避けた方が良いと @Yuryu さんにご共有いただきました https://twitter.com/Yuryu/status/1426279993122844674

*8:念のため書いておくと、入社していきなり移住というケースは少なくて、入社後に実績が認められ、移住することで会社側に何らかのメリットがある人が移住するということが多い。参考までに、僕は入社直後から移住したいと伝えていた結果、入社2年後にビザの手続が始められた。

おうちで食べる二郎系ラーメン

コロナでラーメン屋が減った

コロナが始まったころ、近所では飲食店がテイクアウトしかできなくなり、好きだったみそラーメン屋近所で唯一二郎系ラーメンを出していた店はその間に閉店してしまった。

ふと二郎系ラーメンを食べたい気持ちになったが、自宅からその次にくらい近い二郎系ラーメンを出す店は飛行機で行くような場所にあるし、デリバリーで自分の家まで二郎系ラーメンが届くサービスもどうやらなさそうなので、自分で作ることにした。

よくある本格二郎系ラーメンレシピ

ちゃんとした味を再現しようとすると、以下のように、ゲンコツや背脂みたいなやや調達が面倒そうな材料を用意して、スープだけで最低2時間半かけて作る感じのレシピが出てくる。 *1

Cpicon ラーメン二郎 (乳化) 完全再現 by ★メタボのレシピ★

これはちょっとやってられないので、とりあえず手抜きで作ることにした。

手抜き二郎

角煮を作ったときに、煮汁の醤油と脂っぽさがなんか二郎っぽいな、と思ったことがあったので、角煮を作ったときにその汁と市販の濃厚豚骨スープを融合させ、醤油を足してカラメにし、二郎っぽいトッピングを使ったところ割りとそれっぽい感じになった。

角煮を普通に作ってこのパックを用意するだけで面倒なパートが大体終わるので、これのコスパは結構よかった。自作二郎のいいところは、もやしとキャベツとにんにくと醤油が味の大部分を占めていて、それらの準備で失敗することはまずない上に、この辺りをマシマシにしておけば結構味がキマるため、料理がヘタクソでも高い確率で二郎っぽくなるところかなと思う。

でも、この市販スープも麺もあんまり二郎っぽくない (かといってそれより二郎ぽいのもない) ので、麺とスープは調達方法変えてもいいなと思ったのだった。

ろたすさんの家二郎レシピ

ラーメンろたすという店をやっている ge-c さんがYouTubeで家で作れる二郎系ラーメンの作り方を紹介している。ge-c さんの 極上のおうちラーメン という本にも、家二郎という章にレシピがまとまっている。

本の家二郎の章の写真は割りと本格的に見えるのに、YouTubeのレシピより材料の調達が簡単かつスープが1時間ちょっとで完成するところに惹かれ、今回それを作ってみた。

前回の手抜きの奴より大分それっぽい味になった。レシピについては本やYouTubeの方を見て欲しいが、特徴的な材料の調達に関する知見だけまとめておく。

麺については、パスタ麺なのだが、リングイネフィットチーネが推奨されている。僕はリングイネを試してみたが、ある程度太麺で、ほどほどに平たいので、たしかに市販パックのラーメンよりぽいなという感じがした。調達は簡単で、Amazonとかで結構ある。僕は乾麺を買ったけど生パスタの方がおいしいらしい。

豚バラ

豚バラ (Pork Belly) は普通の部位なのに何故か置いてなかったりとか (売り切れ?)、なんか皮つきで売られてたりとか、切られたサイズが結構小さめだったりとかして面倒くさい。僕の近所ではマルカイというスーパーで売ってる奴がちょうどいい。

豚足

豚足を買ったことがなかったが、中国系スーパーの99 Ranch Marketに行ったらおいてあった。でも足が3cmおきに切り込みが入った状態で売ってるので、ここで買うとどちらかというと豚骨を使うような感じになる気がする。

背脂

最難関。背脂は普通は破棄する部位なので売っておらず、基本的にはスーパーの肉カウンターか肉屋に行って、店の人に話しかけて出してもらうしかないらしい。僕の近所では、肉屋が全部ハラール屋さんで、どこも豚肉だけはないのでスーパーを使うしかない状態だった。Safewayというスーパーで聞いてみたら、その時は置いてなかったけど、正午までに店に電話して聞いてくれれば用意しておくよと言われた。99 Ranch MarketでPork Fatどれ?って聞いて言われた奴を今回は使ったけど、それは何か背脂とは違うものだった感じがした。

次作るときは

次は手抜き二郎と家二郎レシピの中間くらいの感じにしてみようかなと思っている。特にチャーシューは圧力鍋でやった方がおいしくなるかなと思った。

*1:あとで https://cookpad.com/recipe/6254137 というレシピも見つけた。これはスープの材料的には楽そう。

まだパソコンのOS選びで消耗してるの?

昨日、大学生協推奨のPCが20万のWindowsマシンなのを見てなぜMacじゃないのかという声がTLに流れていたり、それで思い出したのか、逆にMacじゃなくてLinuxを使っている人はなぜそうしてるのかみたいな話がvim-jpで盛り上がったりしていた。

Windowsを使い始めてから17年、Macを使い始めてから8年、Linuxデスクトップを使い始めてから6年経ち、今は用途に応じてその3つをどれも使っているという感じなのだが、個人的にはどれも善し悪しだと思っているので、状況に応じて何を使うべきか自分の考えを書いておく。

大学生は何を買うべきか

特にプログラミングとかやるつもりがない大学生でお金がある人は、素直に推奨されたWindowsマシンを買っておくと、大学側が使わせてくるソフトが動かない可能性も流石に低いだろうし、周りと環境が揃っていて質問とかしやすいので無難だと思う。金がなければ中古で似たような奴を探したり、バイトなどすると良い。

これからプログラミングを始めますという学生は、Mac (中古のIntel MacBook Proか、M1のMacBook Proあたり) を買うのが良いと思う。理由は単純で、開発に使うものはWindowsじゃなくても大体動くし、逆にiOS開発は突然やりたくなってもmacOSでしかできないため。あと、その辺のWeb系企業が社員に貸与するマシンはMacなことが多いので、そういう会社が視野の人は早いうちにそれでの開発に慣れておくと便利。

開発が趣味の人は何を使うべきか

仕事以外でもプログラミングするけど、別に開発環境にそんなに拘りがないという人は、普通に趣味でも会社と同じOSを使っておく方が業務中にハマる時間が短く済むのでそれが良いと思う。

じゃあ、開発環境いじったり開発効率を向上したりする活動そのものが趣味ですみたいな人はどうか。そういう人は、きっとどれを選んでも大体楽しんでなんとかできるので、面白そうと思ったOSを全部試してみるのがおすすめ。そのうち自分のお気に入りが見つかると思う。

まあこれだと何らかの理由で選択肢が複数ある人や、そもそもどれから試すべきか悩んでるステージの人には何の足しにもならないので、現時点での個人の感想を以下に書く。書いてない奴も、単に今思いついてないだけの可能性もあるけど、普通に知らない可能性もあるので何かあったら教えてほしい。特にWindowsは僕が勉強不足な可能性が高い。

Windows

良い所

  • ゲームを始めとして、Windowsにだけ対応してるアプリが結構ある
  • 優秀なキーリマッパー (例えばのどか *1 ) があり、Macっぽいキーバインド *2 もある程度再現できる
  • WSL2ができたのでmacOSよりもLinux寄りの環境が使いやすくなった
  • OSSのWin32やMinGW対応をするときに便利

悪い所

  • ファイルパスの扱いの違いや、ANSIエスケープシーケンスや、ネイティブなシステムコールの違いにより、Windows以外では大体スッと動くがWindows対応には一手間かかる開発用ツールはそこそこあり、Windowsに対応してないか、mattnさんがWindows対応したかみたいな状態になりがち。
  • HiDPI (MacでいうRetina) にOSレベルでは対応しているが、アプリ側が対応してないとそういうアプリだけ文字の解像度が低く汚ない感じになる。

macOS

良い所

  • Retina表示の対応率がすごい。ありとあらゆるアプリがほぼ常に綺麗に表示される。
  • 極めて便利なキーリマッパー (Karabiner-Elements) がある
  • Emacs キーバインドが標準で使え *3、かつCommandキーのショートカットとデフォルトで分離されている
  • Windowsほど対応アプリは多くないが、Linuxは対応してなくてmacOSは対応してるアプリは割りとある *4
  • iPhoneやそのアクセサリとの連携が最も自然に動く
  • OSSmacOS対応をするときに便利

悪い所

  • ターミナルの動作がLinuxのそれに比べて遅かったり、(Intelの) フルスペックのMacBook Proなのに普通にIDE使ってるだけで度々カーソルがグルグルして待たされるので、あまり快適にプログラミングできない。まだ試せてないけど、M1やM2だとこれが劇的に改善されていると期待している。
  • Linuxではない。Linuxサーバーをいじるのが仕事な人は、LinuxにあるけどmacOSにはないか普通使わないツール *5 にも慣れておくと、便利なことがある。
  • homebrewの依存管理がゆるふわなので、brewを使っているとある日突然so名がズレたりしていろいろ壊れることになる
  • ウィンドウの半透明化 *6 が難しい。Deskoveryというアプリでできていたのが、Catalina以降はSIPを切らないといけなくなった。

Linux

過去にはArch LinuxGentooなどのディストリビューションや、Awesomexmonadなどのウィンドウマネージャを試したので自分の環境以外の話もある程度わかるつもりだが、今はUbuntuGNOMEなのでそれ特有の話が混ざってるかも。

良い所

  • ターミナルの動作が速い。エディタなども含め、マシン購入にかかる値段あたりの比較では一番軽快に動作する印象。
  • Dockerを動かすときのオーバーヘッドが小さく、軽快に動作する
  • Linuxサーバーサイドエンジニアの場合、本番環境と手元の環境を揃えられる
  • ある程度機能が揃ったキーリマッパー *7 があり、Macっぽいキーバインド *8 もある程度再現できる
  • WindowsmacOSだけでなくLinuxもサポートしているデスクトップアプリは結構あり、開発以外の用途にも使う場合も、意外とある程度は普通に生活できる *9
  • ウィンドウマネージャの自由度が高い。タイル型WMとかが使える。 *10
  • OSSLinux対応をするときに便利

悪い所

  • ドライバーのサポートが不安。何かケーブルを繋ぐ度に「動くのか…?」とビクビクすることになる。例えばうっかり最新のGPUを買うと、Nvidiaのドライバをいれれば動くがnouveauだと動かず、何らかの拍子にNvidiaのドライバが抜けると、画面が映らない状態でNvidiaのドライバをインストールする必要が発生するみたいな状況に陥ることもある。
  • 動かないアプリが多い。最近、SteamがLinuxに対応してるっぽくて驚いたけど、たとえばAmong UsとかはSteam Play (中身はProtonという、Wineベースの互換レイヤ) を使って起動できたりするのだが、ネットワーク接続が動かなくて、なんかそれをデバッグするRedditスレが盛り上がってたりする。
  • 音を出すみたいな割りと基本的なところがデフォルトで動かなくてハマることがある。まあそういうのを直すのをエンジョイするのがLinuxみたいなところがある。
  • HiDPIに対応してないアプリがある。Windowsと違って、文字が低解像度表示されるのではなく、文字が小さく表示されるか、何か画面を切り替えた時にウィンドウ幅が画面サイズ以上になっていたりする。

まとめ

*1:窓使いの憂鬱の派生プロジェクト

*2:CtrlでEmacsキーバインド、Ctrlじゃない修飾キーでコピーやペーストなど

*3:これ、ほとんどはWindowsLinuxでも再現できるんだけど、じゃあ何が嬉しいかっていうと、例えばHomeやEndでC-aとC-eをエミュレートする時、論理行頭/末じゃなくて物理行頭/末になってしまうという違いがあるため。C-kも同様。ただし、Emacsバインドは様々なWebサイトで奪われるので、キーリマッパーのサポートはEmacsキーバインド自体に対しても結局必要がなことが多い

*4:ライセンス時代の1Passwordとか、Appleなのでやや例外的ながらiTunesとか

*5:具体的にはstrace、perf、gdbなど。gdbは使えないことはないが入れるのが若干面倒な上、普通Clangを使う場合lldbを使うのが無難なのでgdbはなかなか使わない。

*6:これ何に使ってるかというと、シングルディスプレイでエディタを全画面表示しながら、それに透かしてブラウザとSlackやTwitterを同時に眺めるということをやっている。Vimだとターミナルの半透明機能でいけるけど、IntelliJ IDEAとかを使ってるときにそれができなくて不便。

*7:Rubyが好きな人は拙作 xremap や、Pythonが好きな人は xkeysnail など

*8:CtrlでEmacsキーバインド、Ctrlじゃない修飾キーでコピーやペーストなど

*9:参考: https://k0kubun.hatenablog.com/entry/linux-desktop-2017

*10:macOSにもないこともないが、もともとそれを念頭にデザインされてないデスクトップ環境なので、僕が過去に試したものは微妙な挙動だった