非力なマシンでは Scratch が重くて落ちた、と書いたところ、日本での Scratch 普及の第1人者でもある、阿部 和広さんから直接情報をいただきました。
@wizforest Raspbian Jessieに同梱のNuScratchは最新のSqueakとJITを使って3〜10倍高速化されています。他プラットホームではパッケージを入れるだけの手軽さはありませんが、試す価値はあるかもしれません。
— Kazuhiro Abe (@abee2) October 24, 2015
というわけで、NuScratch をキーワードに検索してみるけど、RaspberryPi 関連のページしか見当たらない。
探すうちにだんだん理解できて来たので、以下僕による補足。
この世界はそれほど詳しくないので、間違えていたらごめんなさい。
Smalltalk は当初の設計より「仮想CPU」(Virtual Machine : VM と呼ばれます)上で動作しています。
リンク先に書いてあるのだけど、当時 ARPANET の構築が始まっていて、まだ実際に接続に必要なソフトは PDP-11 用しかありませんでした。
Xerox の技術者は、ARPANET に参加したかったのだけど、Xerox は「シグマ7」という PDP-11 の対抗機種を作っている。
会社に PDP-11 を買ってくれ、とは言えない。
そこで、Alto を作ります。Alto は CPU の命令を「マイクロコード」で実際の演算回路に変換する仕組みだったのですが、このマイクロコードを可変にしたのが特徴でした。
PDP-11 互換、とは会社には言っていないのですが、PDP-11 互換に「することも」できます。
Alto 上ではいくつかの OS が作られ、OS ごとに都合のよい命令を作るようにマイクロコードを設計しました。
つまり、Alto 上の OS はどれも、「仮想的な CPU」である、 VM 上で動く設計なのです。
Smalltalk も Smalltalk 用の VM の上で動きました。
そして、この構造は Smalltalk が別のハードウェアに移植されたときにも変わりませんでした。
Smalltalk が必要とする VM をそのハードウェア上に移植すれば、Smalltalk の移植は完了。
仮想 CPU を挟むので多少動作は遅くなりますが、移植性の非常に優れた OS でした。
Squeak も Smalltalk の実装の一つなので VM を使うのです。
この VM は命令を逐次解釈(インタープリタ)実行します。
たとえば、2つの変数(レジスタ)、αとβを足し合わせ、結果をαに残す、という命令を実行してみましょう。
1. VM はメモリから命令データを取り出します。
2. 命令データを調べ、「2つの変数を足す命令」だと認識し、3 以下のプログラムを呼び出します。
3. αに相当するメモリのデータを取り出し、実際の CPU のレジスタ EAX に入れます
4. βに相当するメモリのデータを取り出し、実際の CPU のレジスタ EBX に入れます
5. 実際の CPU で、ADD %EAX,%EBX 命令を実行します。
6. EAX の内容をαに相当するメモリに格納します。
7. 1 に戻ります。
これで終わり、5 は実際に計算している部分で、それ以外は「仮想 CPU」と、「本物の CPU」の間で、すり合わせをやっている作業。
実際にやりたいことから見ると、無駄が非常に多く、遅いです。
商用の Smalltalk を作成している会社は、もっと高速に実行できる JIT (Just-In-Time: 即時)コンパイル VM を使います。
仮想 CPU の命令を、実行する瞬間に解釈して本物の CPU の命令に変換し、その後は同じ場所を実行する際には常に本物の命令を使う、という方法です。
先に書いたのと同じ例でいえば、「αは EAX 、βは EBX」のように、ある程度現実の CPU と VM のレジスタを一致させてしまい、加算命令を ADD %EAX,%EBX という命令に変換します。
そして、周囲の命令も含めて、連続して「変換した」内容をメモリにおいて、そのメモリ内容を実行します。
初回のみ解釈が必要ですが、以降は解釈なしで実行できるため高速です。
しかし、本物の CPU に変換した命令を覚えておくためのメモリを必要としますし、技術的に高度になるためバグも混入しやすくなります。
2010年に、商用 Smalltalk を作成している会社が、VM 部分を無償公開したそうです。(Cog VM と呼びます)
より厳密にいえば、JIT VM を作っていた人が商用 Smalltalk の会社に売り込みをかけたが、さらにフリーウェアとして公開することを承諾してもらった、ということなのかな。
いずれにせよ、他社に対するアドバンテージを入手したのに、それを公開するというのは英断です。感謝。
そして、この VM は Squeak でも使用することができます。
最初に書いた通り、Smalltalk は最初に設計されたマイクロコード上で動作するようになっていて、複数ある Smalltalk 処理系で共通になっているためです。
とはいえ、細かな部分…例えば、動作のタイミングなどまで厳密に同じか、といえば異なります。
「速くなっている」というのは、つまり「全く同じ」ではないのだから。
だから、Squeak で使用するのは保証外。
Cog VM はまだ開発途上で、2010 年に最初のリリースが行われた後、2014年にも大きな機能追加があり、大幅に高速化したようです。
さらに高速化のアイディアを現在実装中で、2015年中にはリリースしたい、とのこと。
速度は条件により異なるが、平均して5倍速になるだろうと目標を立てています。
そして、現状の Cog VM 上で動作するように調整した Scratch が NuScratch のようです。
保証外だけどうまく動いているし、非力な RaspberryPi では速度を稼げるほうがずっと大切です。
#Nu は New の意味。よくあるスラングです。
…というわけで、すでに Scratch が動く環境なら Squeak の VM 部分を Cog VM に交換すれば「NuScratch 相当」になるはず。
挑んでみましたが、「簡単ではない」ことがわかり、成功はしていません。
まず、日本語版Squeakは、Squeak を日本語対応にして再パッケージしたものですが、Cog と公式 VM の両方が使えるようになっています。
Scratch は Squeak 上で作られて、VM の命令レベルのバイナリで配布されているもの。
なので、理論的には VM を取り換えれば話は済むはずです。
でも、VM とバイナリには、それぞれ「命令のバージョン」が入れられていて、バージョンが違うとエラーになって動作しません。
日本語 Squeak の VM のバージョンは 6505。Ubuntu 12 で入れられる Squeak のバイナリのバージョンは 6502 です。
バージョン違いで動きません。
Squeak は、Smalltalk の(つまりは Squeak の)ソースコードでも配布されています。
でも、僕が Smalltalk に詳しくないので、このソースコードを読み込ませ、バイナリにコンパイルする方法がわかりません。
多分、Cog で動く Squeak の上で Scratch のソースコード読ませて、バイナリで保存すればよいのだと思うのだけど…
最初に情報頂いた阿部和広さんの解説記事にScratch の改造方法があります。
ここでは、ソースを用意して改造しているのだけど、「ソース入りのバイナリ」を使っているのね。
バイナリを使うとバイナリバージョンに依存してしまうので、純粋なテキストソースから読み込まないといけないと思うのだけど…
#Squeak のプログラムは、「VM 上のメモリイメージのスナップショット」として配布されることが多い。
Smalltalkには「ファイル」という概念がないので、プログラムのバイナリファイルを配布、というわけにいかないのね。
そして、スナップショットなので、メモリにソースを読み込んだ状態で配布すれば、ソースを見られる。上記ではそれを使っている。
純粋なソースも配布されているようなのだけど、VM 上にどうやって読み込ませるのか知りません。
(先に書いたように、ファイルという概念がないので、ソース「ファイル」を読み込ませる方法もない)
というところで昨日は時間切れ。
あと少し作業すればできそうな気もするし、まだ先があるかもしれません。
興味のある方もいるかな?
でも、再コンパイルしたものの再配布は禁じられているようなので、完成したとしても再配布はできません。
成功したら、「やり方」を示すだけでも意義は大きいとは思うのだけど、先行き不透明です。
同じテーマの日記(最近の一覧)
関連ページ
別年同日の日記
申し訳ありませんが、現在意見投稿をできない状態にしています。 |