Hatena::Groupcadr

わだばLisperになる このページをアンテナに追加 RSSフィード

2004 | 12 |
2005 | 01 | 02 | 07 | 10 | 11 |
2006 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 11 |

2010-06-18

Getting Started in *LISP (27)

| 23:50 | Getting Started in *LISP (27) - わだばLisperになる を含むブックマーク はてなブックマーク - Getting Started in *LISP (27) - わだばLisperになる

今回は、4.3章 *Lisp Error Checking です。

4.3 *Lisp Error Checking

*Lispには、 *interpreter-safety* という変数があり現在のエラーチェックの度合いを設定したり確認したりできるとのこと。

度合いは、0〜3の整数で表わされ、

0 実行時のエラーチェックは無効

1 最小限の実行時エラーチェックだけ有効。コードのどの位置でエラーが起きたかの通知は不正確かもしれない

2 将来の拡張のための予約

3 実行時エラーチェックが全て有効。

そして、処理系のデフォルトは3。

この値を変更するときには、

(setq *interpreter-safety* 3)

とする。

大まかにいって、3はフルにエラーチェック、0はチェックなし。

デバッグの時には、3を利用し、一度正しくプログラムが走ることが確認できれば0にしてスピードを上げる、というような使い方ができる。

(でき得る限りのスピードを出すということになると型宣言+コンパイルということになる。この辺りは、5章で解説)

レベル1は、主にほぼ完全に動くコードをテストするのに使える。

エラーの内容は正確だけれど、実際にエラーを起こしている場所とエラーが起きるタイミングが異なることがある。

> (setq *interpreter-safety* 1)

> (/!! 3 0)	;; The error occurs here, but is not signaled...
#<FLOAT-Pvar 5-32 *DEFAULT-VP-SET* (32 16)>

> (+!! 2 3)	;; Still not reading a value from the CM...
#<FIELD-Pvar 11-3 *DEFAULT-VP-SET* (32 16)>

> (*sum 1)	;; Upon reading a value, the error is signaled:
>>Error: The result of a (two argument) float /!! overflowed
CMI::WAIT-UNTIL-FEBI-OUTPUT-FIFO-NOT-EMPTY:
:A  0: Abort to Lisp Top Level
->

のような場合、(*sum 1)で実際に値を読み込んだときにエラーが起きたりする。

ちなみに、シミュレーターの場合の動作では、どうやら実質3にしか設定されなさそうな様子。

次回、4.4から再開です。

2010-06-11

Getting Started in *LISP (26)

| 22:39 | Getting Started in *LISP (26) - わだばLisperになる を含むブックマーク はてなブックマーク - Getting Started in *LISP (26) - わだばLisperになる

今回は、4.2章 Error Messages です。

4.2 Error Messages

エラーについては、警告の場合と同じように様々ある

> (pront 'oops!)
>>Error: The function PRONT is undefined.
SYMBOL-FUNCTION:
   Required arg 0 (S): PRONT
:C  0: Try evaluating #'PRONT again
:A  1: Abort to Lisp Top Level
->

というようなタイプミスにより引き起こされたものから、

> (/!! 3 0)
>>Error: In interpreted /!!.
	The result of a (two argument) float /!! overflowed.
	There are 8192 selected processors,
	8192 processors have an error.
	A SINGLE-FLOAT temporary pvar stored at location 458752
	caused the error.
*LISP-I::/!!-2:
...
:A  : Abort to Lisp Top Level
->

不正な引数を与えて起きたエラー等々。

エラーメッセージがConnection Machineっぽくて良いですね。

4.2.1 Recovering from Errors

エラーから(デバッガから)の復帰は、Lucid CLならば、:a(abort)でOKとのこと。

When You Abort, Remember to (*warm-boot)

しかし、*Lispの場合、Connection Machineとフロントエンドのマシンの二つのマシンを使っているので、フロントエンド側が復帰していてもConnection Machineがうまく復帰していない場合がある。

こういう場合には、

(*warm-boot)

を使う。

(*warm-boot)はConnection Machineの内部状態をリセットし、その他の細々としたことを整えてくれるとのこと。

デバッガから抜けた際には、Connection Machine内が色々と混乱した状態になっている場合もあり、エラーにならない筈のコードもエラーになったりするかもしれない。

> (*sum 1)	;; NOTE: This example was run on an 8K CM
8192

> (*when (evenp!! (self-address!!)) (break))
>>Break: break
EVAL:
 Required arg 0 (EXPRESSION): (*WHEN (EVENP!! (SELF...
:C	0: Return from Break
:A	1: Abort to Lisp Top Level
-> :a
Abort to Lisp Top Level

> (*sum 1)
4096

こんなことになったりするらしい。

ちなみに、シミュレーターでも同じようなことになりました。

上記の例は、(evenp!! (self-address!!))で半分のプロセッサを除外している状態で、BREAK→Abortとしたため、プロセッサが半分しか選択されていない状態が残ってしまっているためらしい。

こういうときには、(*warm-boot)して復帰させる

(*warm-boot)

(*sum 1)
;⇒ 8192
For More Persistent Errors, Try (*cold-boot)

(*warm-boot)しても直らないようなときには、一歩進んで(*cold-boot)する。

(*cold-boot)は(*warm-boot)よりもやりなおし度合いが深い。

また、エラーが永続的なpvarに起因するのではないか、と思われるときは、

(*cold-boot :undefine-all t)

を実行してみると良いとのこと。

:undefine-all tは、すべてのVPセットと、pvarを初期化する。

この初期化に伴い作成したプログラムは再ロードする必要があるかもしれない。

上記の対処方法を試しても謎のエラーがしつこく出る場合は、システム管理者に相談しましょう、とのこと。

次回、4.3から再開です。

2010-06-05

Getting Started in *LISP (25)

| 11:27 | Getting Started in *LISP (25) - わだばLisperになる を含むブックマーク はてなブックマーク - Getting Started in *LISP (25) - わだばLisperになる

今回から4章です。

3章の最後の前振りによれば、4章は、エラーハンドリングとデバッガの使用方法についての説明とのことでした。

When Things Go Wrong

予期せぬエラーに対してデバッガが教えてくれる情報や、エラー/警告メッセージなどを手掛かりにどう対処してゆくかを解説するのがこの章の目的とのこと

この章のテキストでは、Sun Common Lispのメッセージ表示を使うが、処理系によって表示に違いがあるとのことですが、SunもCLの処理系を出してたんですね。(パッケージ名がlclなので、中身はLucid CLのようですが)

4.1 Warning Messages

警告について

警告メッセージにも色々ありますが、まずは、

;;; GC: 174988 words [699952 bytes] of dynamic storage in use.
;;; 644210 words [2576840 bytes] of free storage available.

のようなGCの警告メッセージから。

これはGCが稼動しているということで、処理系によっては、(setq sys::*gc-silence* t)等で黙らせることができることが解説されています。

今どきの処理系ではCMUCLがGCの稼働状況が激しく表示されますが、これも(setq *gc-verbose* nil)で静かにできるようです。

次に、

> (defun simple (x) (+!! x 2))
> (compile 'simple)
;;; Warning: *Lisp Compiler: While compiling function SIMPLE:
;;;          The expression (+!! X 2) is not compiled because
;;;          the compiler cannot find a declaration for X.

のようなもので、コンパイラがすべてをコンパイルするのには情報が足りなかったため部分的にコンパイルできなかったというようなメッセージ。

可能な限り効率的というわけではないけれど、関数はコンパイルできているというもので、こういった類のメッセージは、無視できる。

後の*Lispコンパイラの章で詳しく解説するとのこと。

次回、4.2のエラーメッセージの解説から再開です。

2010-05-30

Getting Started in *LISP (24)

| 13:38 | Getting Started in *LISP (24) - わだばLisperになる を含むブックマーク はてなブックマーク - Getting Started in *LISP (24) - わだばLisperになる

前回が2009年の4/26日だったので実に1年ぶりですが、*Lisp入門の24回目です。

このペースだと一体いつ終了するのか…。

VPセットの扱い方をなんかしていた気がしますが、すっかり忘却の彼方です。

3.7 Summary: *Lisp as a Language

3章の振り返りです。

  • *whenや、if!!のような選択したプロセッサを利用する方法。
  • *psetや、*newのようなプロセッサ間でのデータのやりとりの方法
  • *sumやarray-to-pvarのようなフロントエンドとConnection Machineとのデータのやりとりの方法
  • scan!!や、spread!!、sort!!のようなデータの変形の方法
  • *cold-boot、def-vp-set、with-vp-setのような、プロセッサグリッドの操作方法

これらが*Lispの並列プログラミングツールとして主なところ。

次章の4章からはエラーハンドリングとデバッガの使用方法について説明するとのこと

ということで、次回、4から再開ですが、上記の主な操作方法のことは、すっかり忘れています…。

2009-04-26

Getting Started in *LISP (23)

| 10:46 | Getting Started in *LISP (23) - わだばLisperになる を含むブックマーク はてなブックマーク - Getting Started in *LISP (23) - わだばLisperになる

LingrのCL部屋でスペシャル変数とマルチスレッド問題の話題のお蔭で、すっかり忘れていた*Lispのことを思い出しました。

3ヶ月ほど間が空いてしまいましたが、*Lisp入門の23回目です。

3.6.6 Two Important VP Set Variables

どのVPセットが現在選択されていて、どれがデフォルトのVPセットになっているかを確認したい、ということは良くあることなので、その為の大域変数が用意されているとのこと。

まず、*default-vp-set* は、*cold-bootした時に設定されたVPセットが束縛されている

(*cold-boot :initial-dimensions '(128 128))

*default-vp-set*
;=> #<VP-SET Name: *DEFAULT-VP-SET*, Dimensions (128 128), Geometry-id: 2>

*default-vp-set* は *cold-boot を実行する度に設定されるが、逆にそれ以外の方法では変化しない。

対して、 *current-vp-set* は現在選択されているVPセットの内容に束縛されている。

*current-vp-set*
;=> #<VP-SET Name: *DEFAULT-VP-SET*, Dimensions (128 128), Geometry-id: 2>

(def-vp-set big-square ' (256 256)
  :*defvars ' ((big-square-pvar 1)
               (another-square-pvar (random!! 20))))

;; VPセットをbig-squareに設定
(set-vp-set big-square)

*current-vp-set*
;=> #<VP-SET Name: BIG-SQUARE, Dimensions (256 256), Geometry-id: 3>

ということで上記を利用して現在のVPセットがデフォルトのVPセットかどうかを調べる関数が書ける

(defun default-p ()
  (eq *current-vp-set* *default-vp-set*))

試してみる

(set-vp-set big-square)
;=> #<VP-SET Name: BIG-SQUARE, Dimensions (256 256), Geometry-id: 3>
(default-p)
;=> NIL

(set-vp-set *default-vp-set*)
;=> #<VP-SET Name: *DEFAULT-VP-SET*, Dimensions (128 128), Geometry-id: 2>

(default-p)
;=> T

VPセットは*Lispのツールのうちでも高度なものなので、ここではこれ以上詳細に立ち入らず、後の6.4章で詳細に解説するとのこと。

次回、3.7から再開

2009-01-20

Getting Started in *LISP (22)

| 10:46 | Getting Started in *LISP (22) - わだばLisperになる を含むブックマーク はてなブックマーク - Getting Started in *LISP (22) - わだばLisperになる

のんびりと続けております、*LISP入門。今回は、3.6.4からです。

3.6.4 Default and Current VP Sets

前回定義したVP setsをどうやって使うかということになるのですが、実際のところこれまでもデフォルトのVP setsを使ってきたとのこと。

初期化時に*cold-bootでサイズを指定していましたが、デフォルトのVP setsのサイズを指定していたということになります。

3.6.5 Selecting VP sets

ということで自前で定義したVP setsを利用する方法ですが、with-系マクロの*with-vp-set等を利用します。

(in-package :*lisp)

;;; 128 x 128に設定
(*cold-boot :initial-dimensions '(128 128))

現在の状況(デフォルト)を表示

(list *current-cm-configuration*
      *number-of-processors-limit*)
((128 128) 16384)

VP sets big-squareと、another-square-pvarを定義

(def-vp-set big-square '(256 256)
  :*defvars '((big-square-pvar 1)
              (another-square-pvar (random!! 20))))

*with-vp-setでbig-squareを選択

(*with-vp-set big-square
  (list *current-cm-configuration*
        *number-of-processors-limit*))
;=> ((256 256) 65536)

(list *current-cm-configuration*
      *number-of-processors-limit*)
;=> ((128 128) 16384)

*with-vp-setの外では元の設定であることが分かる。

カレントのVP setsを変更してしまいたいときは、set-vp-setを利用

(set-vp-set big-square)
;=> #<VP-SET Name: BIG-SQUARE, Dimensions (256 256), Geometry-id: 3>

(list *current-cm-configuration*
      *number-of-processors-limit*)
;=> ((256 256) 65536)

変更されたことが分かる

次回、3.6.6から再開です。

2009-01-17

Getting Started in *LISP (21)

| 14:59 | Getting Started in *LISP (21) - わだばLisperになる を含むブックマーク はてなブックマーク - Getting Started in *LISP (21) - わだばLisperになる

淡々と続けております、*LISP入門。今回は、3.6.2からです。

3.6.2 Where Did the Extra Processors Come From?

Connection Machineでは実プロセッサの数を越えてプロセッサを指定することができるとのことで、この場合は仮想プロセッサが使われるとのこと。

仮想プロセッサはVPと呼ばれます。

実と仮想との違いを意識することはなく透過的に使えるよう自動で設定されるようになっているとのこと。ただし、仮想なので速度は違ってきます。

3.6.3 Defining Custom Configurations - VP Sets

色々なサイズのデータを扱うようになると、pvarのサイズもまたそれに応じて設定する必要がでて来ますが、これまで見たようにpvarのサイズはプロセッサの数と同じなので、これを状況に応じて変えたいということになってきます。

この要求のためには、仮想プロセッサの仕組みを利用して対応させるとのことで、def-vp-set等を利用。

(in-package :*lisp)
(*cold-boot :initial-dimensions '(64 64))

(def-vp-set big-square '(256 256))

と定義した場合、big-squareは、仮想的な256x256の二次元グリッドになります

この作成したVP setsにも値を設定できます。

;; 初期値1で埋めたグリッド
(*defvar big-square-pvar 1 nil big-square)

;; *defvar書式
;; (*defvar variable &optional initial-value documentation (vp-set '*default-vp-set*))
;; 0-19の乱数で埋めたグリッド
(*defvar another-square-pvar (random!! 20) nil big-square)

また、default-vp-setでの宣言時にまとめることも可能です。

(def-vp-set big-square ' (256 256)
  :*defvars '((big-square-pvar 1)
              (another-square-pvar (random!! 20))))

次回、3.6.4から再開

2009-01-11

Getting Started in *LISP (20)

| 21:11 | Getting Started in *LISP (20) - わだばLisperになる を含むブックマーク はてなブックマーク - Getting Started in *LISP (20) - わだばLisperになる

3.6 Configuration Operators

これまでpvarの扱い方をみてきたが、今度は、pvar全体の規模や形を設定する方法を学ぶとのこと。

これには *cold-boot を使用する。

3.6.1 Defining the Initial Grid Configuration - *cold-boot

64x64x64プロセッサを使用する場合は、

(*cold-boot :initial-dimensions '(64 64 64))

;=> 1 ; チュートリアルでは8192になっているが…
;  (64 64 64)

とする。

現在の設定は*current-cm-configuration*や、*number-of-processors-limit*で確認できる

*current-cm-configuration*
;=> (64 64 64)

*number-of-processors-limit*
;=> 262144

なるほど、なるほど。

チュートリアルにはシミュレータの場合は、遅くなるので8x8x8位にしておきましょうという注意書きがあるのですが、当時から20年位経過しているということもありどの辺くらいまで行けそうなのか試してみました。

0-9の値をプロセッサにランダムに割り振った後で、全体をソートします。

(*cold-boot :initial-dimensions '(100 100 100))

(time (sort!! (random!! 10) '<=!!))
;>>
;(SORT!! (RANDOM!! 10) '<=!!) took 5,060,747 microseconds (5.060747 seconds) to run 
;                    with 2 available CPU cores.
;During that period, 4,920,000 microseconds (4.920000 seconds) were spent in user mode
;                    20,000 microseconds (0.020000 seconds) were spent in system mode
;1,122,322 microseconds (1.122322 seconds) was spent in GC.
; 32,000,336 bytes of memory allocated.
; 2,523 minor page faults, 0 major page faults, 0 swaps.
;#<PVAR SORT!!-RETURN :GENERAL  *DEFAULT-VP-SET* (100 100 100)>

以上、Clozure CLですが、100万プロセッサの設定でも壊れたりはしないようです。

2009-01-09

Getting Started in *LISP (19)

| 22:25 | Getting Started in *LISP (19) - わだばLisperになる を含むブックマーク はてなブックマーク - Getting Started in *LISP (19) - わだばLisperになる

3.5.3から再開です。

3.5.3 Sorting Pvar Values

前回に引き続き、データを変形するオペレータで有用なものには、sort!!あるとのこと。

これはpvarの範囲に作用するsortのようなもの。

(in-package :*lisp)
(*cold-boot :initial-dimensions '(8 8))
;; 8 x 8プロセッサを利用

;; グリッドを0-9の乱数で埋める
(*defvar random-numbers (random!! 10))

;; 確認してみる
(ppp random-numbers :end 20)
;>> 1 6 5 0 5 2 9 0 0 6 8 3 9 8 5 4 0 9 5 9
;=> NIL

プロセッサ番号が20より小さい範囲にsort!!を適用。述語は<=!!なので、<=で比較されるsortのようなもの。

(*when (<!! (self-address!!) 20)
  (ppp (sort!! random-numbers '<=!!) :end 20))
;>> 0 0 0 0 1 2 3 4 5 5 5 5 6 6 8 8 9 9 9 9 
;=> NIL

ソートのルーチンを自作したい場合のために、rank!!という関数も用意されている。

これは、pvarの数値的な順位を返す。

(*when (<!! (self-address!!) 20)
  (ppp (rank!! random-numbers '<=!!) :end 20))
;;; 1  6  5 0  5 2  9 0 0  6  8 3  9  8 5 4 0  9 5  9 pvarの値
;>> 4 13 11 3 10 5 19 2 1 12 15 6 18 14 9 7 0 17 8 16
;=> NIL

この例では、値が0の8番プロセッサが1番になっていることが確認できる。

次回、3.6から再開

2009-01-02

Getting Started in *LISP (18)

| 23:27 | Getting Started in *LISP (18) - わだばLisperになる を含むブックマーク はてなブックマーク - Getting Started in *LISP (18) - わだばLisperになる

今回は3.5.2から再開です。

3.5.2 Spreading Values across the Grid

スキャニングのオペレーションには他にスプレディッングがあるとのこと。

スプレディッングとは、指定した一点を列か行に押し広げることで、*Lispの場合は、2次元以上にも構成できるのでこの表現には語弊があるものの、方法論としては同じとのこと。

スプレディッングには、spread!!を利用する。

(in-package :*lisp)
;; 256 x 256プロセッサを利用
(*cold-boot :initial-dimensions '(8 8))

(ppp (self-address!!)
     :mode :grid
     :end '(8 3)
     :format "~3S ")
;>>
;       DIMENSION 0 (X)  ----->
;  
;  0   8   16  24  32  40  48  56  
;  1   9   17  25  33  41  49  57  
;  2   10  18  26  34  42  50  58  
;=>NIL

という構成のグリッドがあるとする。

この構成に(spread!! (self-address!!) 0 3)適用する。

0は0次元、3は列になり、0次元の3列目を行全体の値とすることを指示している。

(ppp (spread!! (self-address!!) 0 3) ;; Dimension 0, Coord. 3
     :mode :grid
     :end '(8 3)
     :format "~3S ")

;>>     DIMENSION 0 (X)  ----->
;  
;  24  24  24  24  24  24  24  24  
;  25  25  25  25  25  25  25  25  
;  26  26  26  26  26  26  26  26  
;=> NIL

次回、3.5.3から再開

2008-12-29

Getting Started in *LISP (17)

| 00:12 | Getting Started in *LISP (17) - わだばLisperになる を含むブックマーク はてなブックマーク - Getting Started in *LISP (17) - わだばLisperになる

今回は3.5から再開です。

3.5 Parallel Data Transformation in *Lisp

*Lispは大規模なデータの変形をサポートするオペレーションを提供しているとのことで、グリッド全体の総和を取ったり特定のグリッドに沿ってデータを累積したり色々できるとのこと。このセクションではその様なオペレーションの方法を解説。

データを変形するオペレーションは*Lispには

  1. 累積オペレーション
  2. ランキングとソート
  3. スキャン

等がある

3.5.1 Parallel Prefixing (Scanning)

上記のスキャンの方法には選択したグリッドのpvarを横断して作用するもので、scan!!が代表的。

scan!!は拡張性があり、値を掛け算したり、最大値や最小値を取ったり論理的and、or、xorが取れたり、グリッド間で値をコピーすることが可能。

全プロセッサーに2を設定し、+!!を作用させる例(pvarの表現として(!! 2)は2と書ける。)

(ppp (scan!! 2 '+!!) :end 20)
;>>> 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40
;=> NIL

scan!!は :include-self 引数が取れ、各自のプロセッサが自分の値を含めるかを指定できる

(ppp (scan!! 2 '+!! :include-self nil) :end 20)
NIL 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 NIL ; テキストだと先頭が0の筈なんだけれど…

:include-selfは一つシフトさせる用途にも使えることが分かる

scan!!特有の機能として、pvarをセグメントに分けてのオペレーションがある

これには、 :segment-pvar を使用する

;; セグメントの設定: 4つ置きにTを設定し他はnil
(*defvar segments (zerop!! (mod!! (self-address!!) 4)))

;; 確認
(ppp segments :end 16)
;>> T NIL NIL NIL T NIL NIL NIL T NIL NIL NIL T NIL NIL NIL 
;=> NIL

このセグメントにscan!!を作用させてみる

(ppp (scan!! 1 '+!! :segment-pvar segments) :end 16)
;>> 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4
;=> NIL

:segment-pvar を与えられたscan!!は、Tを開始地点と見做し作用することが分かる

次回 3.5.2から再開

2008-12-26

Getting Started in *LISP (16)

| 21:53 | Getting Started in *LISP (16) - わだばLisperになる を含むブックマーク はてなブックマーク - Getting Started in *LISP (16) - わだばLisperになる

3.4.2 Bulk Data Movement-Array/Pvar Conversions

前回の続きでフロントエンドとConnection Machineのデータ転送について

今回は、アレイとpvarとの変換用関数を使う方法を紹介。

そのままな名前の

  • array-to-pvar
  • pvar-to-array

があり、これで転送する。

;; フロントエンド側でアレイを定義
(defvar data-array #(1 2 3 4 5 6))

;; Connection Machine側で空pvarを定義
(*defvar data-pvar 0)

フロントエンド(アレイ)→Connection Machine

;; array-to-pvarでは:endによって終わりを示す
(array-to-pvar data-array data-pvar :end 6)

(ppp data-pvar :end 12)
;>>> 1 2 3 4 5 6 0 0 0 0 0 0
;=>  NIL

アレイが対応するpvarに設定されたことが分かる

Connection Machine→フロントエンド(アレイ)

;; :array-offsetは受け手のアレイの開始オフセット、:start、:endはpvar側
(pvar-to-array data-pvar data-array :array-offset 3
                                    :start 0 :end 3)

(let ((*print-array* t))
  (print data-array))
;=> #(1 2 3 1 2 3)

次回 3.5から再開

2008-12-25

Getting Started in *LISP (15)

| 19:30 | Getting Started in *LISP (15) - わだばLisperになる を含むブックマーク はてなブックマーク - Getting Started in *LISP (15) - わだばLisperになる

書いてる本人も*Lispはマニアック過ぎる気がしてみました。*Lispのシミュレータいじって遊んでる人って果して日本に何人いるんでしょうか。

Clozure CL、Allegro CL、CLISP等で動きますし、結構面白いので是非とも試してみて下さい!

ダウンロードは

からできます。

それはさておき続きです。

3.4 Front-End/CM Communication

フロントエンド(UNIXワークステーションやLispM)とConnection Machine(CM)のデータのやりとりについて

CMは単体で動作するものではなくフロントエンドに接続して利用する形態でした。この章はその方法について

方法は3種類で

  1. !!オペレータによるもの
  2. pvarの値を一つずつ読み出しては返すような方法
  3. アレイをpvarに変換する関数があるのでそれを利用

等があるとのこと

3.4.1 Funnels for Data-Global Communication Functions

まず3つのうちの一番最初の全プロセッサに一気に伝達する系統のものの解説

!!系のオペレータは全プロセッサに同時に作用します。

(in-package :*lisp)
;; 256 x 256プロセッサを利用
(*cold-boot :initial-dimensions '(256 256))

(*defvar numbers (random!! 10))

(*sum numbers)
;=> 295439

*whenやif!!を利用して該当するプロセッサを選択することも可能

;; 全プロセッサに1を設定して合計 => プロセッサの数
(*sum 1)
;=> 65536

;; プロセッサ番号が偶数のものだけに*sumが作用
(*when (evenp!! (self-address!!))
  (*sum 1))
;=> 32768

他に似たものとして *max、*minがあり

;; プロセッサ番号で最も大きい数
(*max (self-address!!))
;=> 65535

述語としては、*or、*andがあります

;; 全プロセッサT
(*or t!!)
;=> T

(*when nil!! (*or t!!))
;=> NIL

;; 全プロセッサに対する
;; (when nil (or t))

次回、3.4.2から再開

2008-12-09

Getting Started in *LISP (14)

| 20:55 | Getting Started in *LISP (14) - わだばLisperになる を含むブックマーク はてなブックマーク - Getting Started in *LISP (14) - わだばLisperになる

実に3ヶ月半ぶりなのですが、*Lispのチュートリアルです。

*Lispとは、65536個もCPUがあるConnection Machine用のLISPで、この日記では、それのシミュレータがあるので動かしてみています。\*LISPセクションがありますので興味がある方は是非一緒に遊んでみて下さい(*'-')

この3ヶ月半の間にAllegro CLとCLISP以外ではシミュレータが動かなかったのが型宣言をANSI CLでもコンパイルできるように書き直すことで動くようになりました。

type-system-deftypes.lisp の

(deftype pvar (&optional (element-type '*))
  ;; I have to return a satisfies type with a closure so that typep can work.
  ;; But, returning a closure will blow up both subtypep and the compiler on lucid.
  (let ((closure (*lisp-i::pvar-type-predicate 
                  (cadr (*lisp-i::canonical-pvar-type `(pvar ,element-type))))))
    `(satisfies ,closure)))

が、 satisfies に lambda 式を渡してしまっているのが原因でコンパイルできなかったので

(defvar *pvar-satisfy-tem* '*)

(defun pvar-satisfy-func (&rest args)
  (apply (*lisp-i::pvar-type-predicate 
          (cadr (*lisp-i::canonical-pvar-type `(pvar ,*pvar-satisfy-tem*))))
         args))

(deftype pvar (&optional (element-type '*))
  (let ((*pvar-satisfy-tem* element-type))
    `(satisfies pvar-satisfy-func)))

のように satisfies に渡す関数を大域で定義して大域変数を間に挟んで対処しました。

deftype の中で関数を作成しても良いとは思いますが、SBCLだと関数が複数生成されるようなのでこの方法にしました。この辺ちょっと謎です。

他にもっと良い方法があったら是非教えて下さい!

シミュレータの動作状況ですが、Clozure CLではいまのところ問題ないようですが、SBCLでは、pvarの値を上手くセットできなかったりでいまいちです。自分はSBCLをメインに使ってるのでどうにか対処したいところです。

3.3.5 An Example of Grid Communication

さて、いきなりですが、グリッドタイプのコミュニケーションの説明です。

どうやら前回きりが良くないところで終りにしたみたいで中途半端です。

内容としては、*newsを使ってグリッドの方を動かしてしまおうという内容です。

;; 8x8で初期化
(*cold-boot :initial-dimensions '(8 8))

;; 0で埋める
(*defvar data-pvar 0)

;; 値をセット
(*setf (pref data-pvar (grid 0 2)) 2)
(*setf (pref data-pvar (grid 0 3)) 3)
(*setf (pref data-pvar (grid 0 4)) 4)

;; 確認
(ppp data-pvar :mode :grid :end '(8 8))
;;      DIMENSION 0 (X)  ----->

;; 0 0 0 0 0 0 0 0 
;; 0 0 0 0 0 0 0 0 
;; 2 0 0 0 0 0 0 0 
;; 3 0 0 0 0 0 0 0 
;; 4 0 0 0 0 0 0 0 
;; 0 0 0 0 0 0 0 0 
;; 0 0 0 0 0 0 0 0 
;; 0 0 0 0 0 0 0 0 
;; NIL

ここで前回定義したzig-zag(Getting Started in *LISP (13) - わだばLisperになる - cadr group参照)

で地面をずらしてみます。(zig-zagは、東へ3歩、北へ1歩動かします)

8x8桝で、四方が繋っている(位置の数値が(mod 8)的)ので、こんな感じになります。

(zig-zag data-pvar)

(ppp data-pvar :mode :grid :end '(8 8))
;;      DIMENSION 0 (X)  ----->

;; 0 0 0 0 0 0 0 0 
;; 0 0 0 0 0 2 0 0 
;; 0 0 0 0 0 3 0 0 
;; 0 0 0 0 0 4 0 0 
;; 0 0 0 0 0 0 0 0 
;; 0 0 0 0 0 0 0 0 
;; 0 0 0 0 0 0 0 0 
;; 0 0 0 0 0 0 0 0 
;; NIL

次回 3.4から再開

2008-08-27

Getting Started in *LISP (13)

| 20:56 | Getting Started in *LISP (13) - わだばLisperになる を含むブックマーク はてなブックマーク - Getting Started in *LISP (13) - わだばLisperになる

投げ出さないように細かく進めて行くことにしたにも関わらず、夏バテのためか、また1ヶ月以上放置してしまっておりました*Lispのチュートリアル。

3.3.3 Grid Communication - Fast, but with Restrictions

前回のCPUの一対一の通信は、柔軟なんだけれどもスピードが遅いのが問題とのこと。

もう一つの方法であるグリッドは制限はあるものの速いとのこと。

3.3.4 The Grid Communication Operators of *Lisp

ということで、グリッドの操作方法について。なんとなく、*Lispっぽくなってまいりました。

グリッドの操作には、*newsや、news!!が使えます。

newsという名前は、グリッドの上下左右を東西南北に見立てたもの。グリッドは、2次元以上も組めるのですが、開発当初は、2次元までだったそうで、それの名残りとのこと。

まず、*newsから。

(*news ソースPVAR デスティネイションPVAR 東西 南北)

という感じのマクロです。

試してみる

(defun zig-zag (pvar)
  (*news pvar pvar 3 0)  ;;; three steps "east"
  (*news pvar pvar 0 -1) ;;; one step "north"
  (*news pvar pvar 2 0))

(*let ((g (self-address!!)))
  (print "before:")
  (ppp g :mode :grid :format "~3D ")
  (*news g g 0 -1)
  (print "after")
  (ppp g :mode :grid :format "~3D ")
  (zig-zag g))

;>>>
before

     DIMENSION 0 (X)  ----->

  0  16  32  48  64  80  96 112 128 144 160 176 192 208 224 240 
  1  17  33  49  65  81  97 113 129 145 161 177 193 209 225 241 
  2  18  34  50  66  82  98 114 130 146 162 178 194 210 226 242 
  3  19  35  51  67  83  99 115 131 147 163 179 195 211 227 243 
  4  20  36  52  68  84 100 116 132 148 164 180 196 212 228 244 
  5  21  37  53  69  85 101 117 133 149 165 181 197 213 229 245 
  6  22  38  54  70  86 102 118 134 150 166 182 198 214 230 246 
  7  23  39  55  71  87 103 119 135 151 167 183 199 215 231 247 
  8  24  40  56  72  88 104 120 136 152 168 184 200 216 232 248 
  9  25  41  57  73  89 105 121 137 153 169 185 201 217 233 249 
 10  26  42  58  74  90 106 122 138 154 170 186 202 218 234 250 
 11  27  43  59  75  91 107 123 139 155 171 187 203 219 235 251 
 12  28  44  60  76  92 108 124 140 156 172 188 204 220 236 252 
 13  29  45  61  77  93 109 125 141 157 173 189 205 221 237 253 
 14  30  46  62  78  94 110 126 142 158 174 190 206 222 238 254 
 15  31  47  63  79  95 111 127 143 159 175 191 207 223 239 255 

after

     DIMENSION 0 (X)  ----->

  1  17  33  49  65  81  97 113 129 145 161 177 193 209 225 241 
  2  18  34  50  66  82  98 114 130 146 162 178 194 210 226 242 
  3  19  35  51  67  83  99 115 131 147 163 179 195 211 227 243 
  4  20  36  52  68  84 100 116 132 148 164 180 196 212 228 244 
  5  21  37  53  69  85 101 117 133 149 165 181 197 213 229 245 
  6  22  38  54  70  86 102 118 134 150 166 182 198 214 230 246 
  7  23  39  55  71  87 103 119 135 151 167 183 199 215 231 247 
  8  24  40  56  72  88 104 120 136 152 168 184 200 216 232 248 
  9  25  41  57  73  89 105 121 137 153 169 185 201 217 233 249 
 10  26  42  58  74  90 106 122 138 154 170 186 202 218 234 250 
 11  27  43  59  75  91 107 123 139 155 171 187 203 219 235 251 
 12  28  44  60  76  92 108 124 140 156 172 188 204 220 236 252 
 13  29  45  61  77  93 109 125 141 157 173 189 205 221 237 253 
 14  30  46  62  78  94 110 126 142 158 174 190 206 222 238 254 
 15  31  47  63  79  95 111 127 143 159 175 191 207 223 239 255 
  0  16  32  48  64  80  96 112 128 144 160 176 192 208 224 240 
NIL

若干見難い気がしますが、定義したzig-zagという関数がグリッド上の値をごっそり移動しているのが分かると思います。

ということで、次回、3.3.5から再開。