分散計算
****

OpenXM
======

Asir は, 分散計算における通信プロトコルとして, Open XM (Open message eXchange protocol for Mathematics) を採用している. Open XM は, 主として数学オブジェクトをプロセス間でやりとりするための規約である. Open XM においては

 1. client が server に対して計算実行依頼のメッセージを送る.

 2. server が計算を実行する.

 3. client が server に結果送付依頼のメッセージを送る.

 4. server は結果を返し, client は結果を受け取る

という形で分散計算が行われる. server はスタックマシンである. すなわち, client から送られたデータオブジェクトは, 指定がない限り server のスタックに積まれ, コマンドが送られた時に, 必要なだけスタックからデータを取り出して, 関数呼び出しの引数とする.

Open XM において特徴的なことは, 計算結果は単に server のスタックに積まれるだけで, client からの依頼がない限り, 通信路にデータは流れないという点である.

プロトコルには, オブジェクトの共通フォーマットを規定する CMO (Common Mathematical Object format), プロセスに対する動作を指定する SM (Stack Machine command) が含まれる. これらは, スタックマシンにデータを送る際に, データの種類を指定するための OX expression としてラッピングされる.

Asir を client として Open XM による分散計算を行う場合には, まず, server を立ち上げて, 通信を成立させる必要がある. このために, ox_launch(), ox_launch_nox(), ox_launch_generic() などの関数が用意されている. さらに, 通信の成立した server に対して以下のような操作が関数として用意されている.

ox_push_cmo()

     データを server のスタックに積む

ox_pop_cmo()
     データを server のスタックから取り出す.

ox_cmo_rpc()

     server の関数を呼び出し, 結果をスタックに積む.

ox_execute_string()

     server 固有のユーザ言語 (Asir なら Asir 言語) で書かれた文字列を server が実行し, 結果をスタックに積む.

ox_push_cmd()

     SM コマンドの送信.

ox_get()

     既に通信路にあるデータの取り出し.

Mathcap
=======

server, client ともに, Open XM で規定されている全てのCMO フォーマット, SM コマンドを実装しているとは限らない. 相手の知らないデータ, コマンドを送った場合, 現状では結果は予想できない. このため, Open XM では, あらかじめ互いのサポートする CMO, SM のリストを交換しあって, 相手の知らないデータを送らないようにする仕組みを提唱している. このためのデータが Mathcap である. Mathcap は CMO としてはリストであり, その要素は 32 bit 整数または文字列である. 現在の規定では, Mathcap は長さが 3 のリストで,

[[version 番号, server 名],SMtaglist,[OXtaglist,CMOtaglist, CMOtaglist,...]]

という形をしている. OXtaglist の I 番目の要素は, その後に続く CMOtaglist の I 番目のものに対応していて, OXtag で示されるカテゴリのデータに対して, どのような CMO が使用可能かを示すものである. この指定を複数許すことにより, 例えば ox_asir のように, CMO データ以外に, Asir 固有のデータ形式により, CMOより多くの種類のデータ送受信を行えることを示せる.

データ送信の際に, 相手プロセスの Mathcap が既に登録されている場合, Mathcap によるチェックを行うか否かは, ctrl コマンドの "ox_check" スイッチにより決まる. このスイッチの初期値は 1 で, チェックを行うことを意味する. ctrl("ox_check",0) によりチェックを行わないようにできる.

スタックマシンコマンド
===========

スタックマシンコマンドは, スタックマシンである server に何らかの操作を行わせるために用意されている. いくつかのコマンドは, よく用いられる形で, 他のコマンド, データとともに, Asir の組み込み関数による送られるが, ユーザが明示的にあるコマンドを送る必要がしばしば生ずる. スタックマシンコマンドは 32 bit 以下の整数であり, ox_push_cmd() コマンドで送信できる. 以下で, 代表的なスタックマシンコマンドについて解説する. SM_xxx=yyy で, SM_xxx が mnemonic, yyy が値である.

以下で, スタックからデータを取り出すとは, スタックの一番上からデータを取り除くことを言う.

SM_popSerializedLocalObject=258

     server が ox_asir の場合に, 必ずしも CMO で定義されていないオブジェクトをスタックから取り出し, 通信路に流す.

SM_popCMO=262

     CMO オブジェクトをスタックから取り出し, 通信路に流す.

SM_popString=263

     スタックからデータを取り出し, 可読形式の文字列に変換して通信路に流す.

SM_mathcap=264

     server の mathcap をスタックに積む.

SM_pops=265

     スタックから取り出したデータを個数として, その個数分スタックからデータを取り除く.

SM_setName=266

     スタックからデータを変数名として取り出し, 次に取り出したデータをその変数に割り当てる. この割り当ては, server 固有の処理として行われる.

SM_evalName=267

     スタックから取り出したデータを変数名として, その値をスタックに載せる.

SM_executeStringByLocalParser=268

     スタックから取り出したデータを, server 固有の parser, evaluator で処理し, 結果をスタックに載せる.

SM_executeFunction=269

     スタックから, 関数名, 引数の個数, 個数分の引数を取り出し, 関数を呼び出し結果をスタックに載せる.

SM_beginBlock=270
     データブロックのはじまり.

SM_endBlock=271
     データブロックの終り.

SM_shutdown=272

     server との交信を切断し, server を終了させる.

SM_setMathcap=273

     スタックのデータを client の mathcap として, server に登録を要求する.

SM_getsp=275

     現在スタックに積まれているデータの数をスタックに載せる.

SM_dupErrors=276

     現在スタックに積まれているオブジェクトの内, エラーオブジェクトのみをリストにして, スタックに載せる.

SM_nop=300

     なにもしない.

デバッグ
====

分散計算においては, 一般にデバッグが困難となる. ox_asir においては, デバッグのためのいくつかの機能を提供している.

エラーオブジェクト
---------

Open XM server が実行中にエラーを起こした場合, 結果のかわりに CMO エラーオブジェクトをスタックに積む. エラーオブジェクトは, 対応する SM コマンドのシリアル番号と, エラーメッセージからなり, それによってどの SM コマンドがどのようなエラーを起こしたがある程度判明する.

     [340] ox_launch();
     0
     [341] ox_rpc(0,"fctr",1.2*x);
     0
     [342] ox_pop_cmo(0);
     error([8,fctrp : invalid argument])

ox_reset() は現在実行中の server をリセットして, コマンド受け付け状態に戻す. この機能は, 通常の Asir セッションにおけるキーボード割り込みとほぼ同様に, Open XM server をリセットできる. また, 何らかの原因で, 通信路のデータが載ったままの状態で ox_rpc() などを実行すると, ox_pop_cmo() など, スタックからの取り出しと, 実際に読まれるデータの対応が不正になる. そのような場合にも有効である.

リセット
----

デバッグ用ポップアップウィンドウ
----------------

server には, client におけるキーボードに相当する入力機能がないため, server 側で動作しているユーザ言語プログラムのデバッグが困難になる. このため, server 側でのユーザ言語プログラム実行中のエラーおよび, client からの ox_rpc(ID,"debug") 実行により, server にデバッグコマンドを入力するための小さなウィンドウがポップアップする. このウィンドウからの入力に対する出力は, log 用の xterm に表示される. このウィンドウを閉じるには, quit を入力すればよい.

分散計算に関する関数
==========

ox_launch, ox_launch_nox, ox_shutdown
-------------------------------------

ox_launch([HOST[,DIR],COMMAND])
ox_launch_nox([HOST[,DIR],COMMAND])
     :: 遠隔プロセスの起動および通信を開始する.

ox_shutdown(ID)
     :: 遠隔プロセスを終了させ, 通信を終了する.

return
     整数

host
     文字列または 0

dir, command
     文字列

id
     整数

  * ox_launch() は, ホスト HOST 上でコマンド COMMAND を起動し, このプロセスと通信を開始する. 引数が 3 つの場合, HOST 上で, DIR にある ox_launch というサーバ起動用プログラムを立ち上げる. ox_launch は COMMAND を起動する. HOST が 0 の時, Asir が動作しているマシン上でコマンドを起動する. 無引数の場合, HOST は 0, DIR は get_rootdir() で返されるディレクトリ, COMMAND は同じディレクトリの ox_asir を意味する.

  * HOST が 0, すなわちサーバを local に起動する場合には, DIR を省略できる. この場合, DIR は get_rootdir() で返されるディレクトリとなる.

  * COMMAND が / で始まる文字列の場合, 絶対パスと解釈される. それ以外の場合, DIR からの相対パスと解釈される.

  * UNIX 版においては, ox_launch() は, COMMAND の標準出力, 標準エラー出力を表示するための xterm を起動する. ox_launch_nox() は, X なしの環境の場合, あるいは xterm を起動せずにサーバを立ち上げる場合に用いる. この場合, COMMAND の出力は /dev/null に接続される. ox_launch() の場合でも, 環境変数 DISPLAY が設定されていない場合には, ox_launch_nox() と同じ動作をする.

  * 返される整数は通信のための識別子となる.

  * Asir と通信するプロセスは同一のマシン上で動作している必要はない. また, 通信におけるバイトオーダは server, client 間での最初の negotiation で決まるため, 相手先のマシンとバイトオーダが異なっていても構わない.

  * HOST にマシン名を指定する場合, 以下の準備が必要である. ここで, Asir の動いているホストを A, 通信相手のプロセスが起動されるホストを B とする.

      1. ホスト B の csh のサーチパスに起動されるプログラムのあるディレクトリをいれる. プログラムは rsh で起動される. したがって, ホスト B のサーチパスに そのプログラムが入っていない場合には起動できない. この場合絶対パスを与えるか, ~/.cshrc のサーチパスにそのプログラムのあるディレクトリを追加する必要がある. その際, 相手先ホストにおけるディレクトリであることを忘れないようにすること.

      2. ホスト B の ~/.rhosts に, ホスト A のホスト名を登録する.

      3. ox_plot など, X とのコネクションも用いられる場合, Xserver に対し, 必要なホストを authorize させる. xhost で必要なホスト名を追加すればよい.

      4. COMMAND によっては, スタックを大量に使用するものもあるため, .cshrc でスタックサイズを大きめ (16MB 程度) に指定しておくのが安全である. スタックサイズは limit stacksize 16m などと指定する.

  * COMMAND が, X 上にウインドウを開ける場合, DISPLAYが指定されればその文字列を, 省略時には環境変数 DISPLAY の値を用いる.

  * ox_shutdown() は識別子 ID に対応する遠隔プロセスを終了させる.

  * Asir が正常した場合には全ての入出力ストリームは自動的に閉じられ, 起動されているプロセスは全て終了するが, 異常終了した場合, 遠隔プロセスが終了しない場合もある. Asir が異常終了した場合, 遠隔プロセスを起動したマシン上で ps などを起動して, もし Asir から起動したプロセスが残っている場合, kill する必要がある.

  * log 表示用 xterm は -name ox_term オプションで起動される. よって, ox_term なるリソース名に対して xterm のリソース設定を行えば, log 用 xterm の挙動のみを変えることができる. 例えば,

          ox_xterm*iconic:on
          ox_xterm*scrollBar:on
          ox_xterm*saveLines:1000

     により, icon で起動, scrollbar つき, scrollbar で参照できる行数が最大 1000 行, という指定ができる.

     [219] ox_launch();
     0
     [220] ox_rpc(0,"fctr",x^10-y^10);
     0
     [221] ox_pop_local(0);
     [[1,1],[x^4+y*x^3+y^2*x^2+y^3*x+y^4,1],
     [x^4-y*x^3+y^2*x^2-y^3*x+y^4,1],[x-y,1],[x+y,1]]
     [222] ox_shutdown(0);
     0

参照
     ox_rpc, ox_pop_local, ifplot, conplot, plot

ox_launch_generic
-----------------

ox_launch_generic(HOST,LAUNCH,SERVER,USE_UNIX,USE_SSH,USE_X,CONN_TO_SERV)
     :: 遠隔プロセスの起動および通信を開始する.

return
     整数

host
     文字列または 0

launcher, server
     文字列

use_unix, use_ssh, use_x, conn_to_serv
     整数

  * ox_launch_generic() は, ホスト HOST 上で, コントロールプロセス LAUNCH およびサーバプロセス SERVER を起動する. その他の引数は, 使用する protocol の種類, X の使用/不使用, rsh/ssh によるプロセス起動, connect 方法の指定などを行うスイッチである.

  * HOST が 0 の場合, Asir が動作しているマシン上に, LAUNCH, SERVER を立ち上げる. この場合, USE_UNIX の値にかかわらず, UNIX internal protocol が用いられる.

  * USE_UNIX が 1 の場合, UNIX internal protocol を用いる. 0 の場合, Internet protocol を用いる.

  * USE_SSH が 1 の場合, ssh (Secure Shell) によりコントロール, サーバプロセスを立ち上げる. 必要に応じてパスワードを入力する必要がある. 相手先で sshd が動いていない場合, 自動的に rsh が用いられるが, パスワードが必要となる場合には, その場で起動に失敗する.

  * USE_X が 1 の場合, X 上での動作を仮定し, 設定されている DISPLAY変数を用いて, log 表示用 xterm のもとで SERVER が起動される. DISPLAY 変数がセットされていない場合には, 自動的に X なしの設定となる. DISPLAY が不適切にセットされている場合には, コントロール, サーバがハングするので要注意である.

  * CONN_TO_SERV が 1 の場合, Asir (client) が生成したポートに対し, client が bind,listen し, 起動されたプロセスが connect する. CONN_TO_SERV が 0 の場合, 起動されたプロセスが bind, listen し, client が connect する.

     [342] LIB=get_rootdir();
     /export/home/noro/ca/Kobe/build/OpenXM/lib/asir
     [343] ox_launch_generic(0,LIB+"/ox_launch",LIB+"/ox_asir",0,0,0,0);
     1
     [344] ox_launch_generic(0,LIB+"/ox_launch",LIB+"/ox_asir",1,0,0,0);
     2
     [345] ox_launch_generic(0,LIB+"/ox_launch",LIB+"/ox_asir",1,1,0,0);
     3
     [346] ox_launch_generic(0,LIB+"/ox_launch",LIB+"/ox_asir",1,1,1,0);
     4
     [347] ox_launch_generic(0,LIB+"/ox_launch",LIB+"/ox_asir",1,1,1,1);
     5
     [348] ox_launch_generic(0,LIB+"/ox_launch",LIB+"/ox_asir",1,1,0,1);
     6

参照
     ox_launch, ox_launch_generic

generate_port, try_bind_listen, try_connect, try_accept, register_server
------------------------------------------------------------------------

generate_port([USE_UNIX])
     :: port の生成
try_bind_listen(PORT)
     :: port に対して bind, listen
try_connect(HOST,PORT)
     :: port に対して connect
try_accept(SOCKET,PORT)
     :: connect 要求を accept
register_server(CONTROL_SOCKET,CONTROL_PORT,SERVER_SOCKET,SERVER_PORT)
     :: connection の成立した control socket, server socket の登録

return
     generate_port() のみ整数または文字列. その他は整数.

use_unix
     0 または 1

host
     文字列

port,control_port,server_port
     整数または文字列

socket,control_socket,server_socket
     整数

  * これらの関数は, 遠隔プロセスと通信を成立させるためのプリミティブである.

  * generate_port() は通信のための port を生成する. 無引数あるいは引数が 0 の場合, Internet domain の socket のための port 番号, それ以外の場合には, UNIX domain (host-internal protocol) のための, ファイル名を生成する. port 番号は random に生成されるが, その port が使用中でない保証はない.

  * try_bind_listen() は, 与えられた port に対し, その protocol に対応した socket を生成し, bind, listen する. 失敗した場合, -1 が返る.

  * try_connect() は, ホスト HOST の port PORT に対し connect を試みる. 失敗した場合 -1 が返る.

  * try_accept() は, SOCKET に対する connect 要求を accept し, 新たに生成された socket を返す. 失敗した場合 -1 が返る. いずれの場合にも, SOCKET は自動的に close される. 引数 PORT は, SOCKET の protocol を判別するために与える.

  * register_server() は, control, server それぞれの socket を一組にして, server list に登録し, ox_push_cmo() などで用いるプロセス識別子を返す.

  * 遠隔プロセスの起動は, shell() または手動で行う.

     [340] CPort=generate_port();
     39896
     [341] SPort=generate_port();
     37222
     [342] CSocket=try_bind_listen(CPort);
     3
     [343] SSocket=try_bind_listen(SPort);
     5

     /*
     ここで, ox_launch を起動 :
     %  ox_launch "127.1" 0 39716 37043 ox_asir "shio:0"
     */

     [344] CSocket=try_accept(CSocket,CPort);
     6
     [345] SSocket=try_accept(SSocket,SPort);
     3
     [346] register_server(CSocket,CPort,SSocket,SPort);
     0

参照
     ox_launch, ox_launch_generic, shell, ox_push_cmo

ox_asir
-------

この節の函数は, UNIX 上で 複数のマシン上で Asir を複数起動して分散計算を行うためのものである. 以下に述べる機能を用いるためには, あらかじめ各マシン上に ox_asir を ox_launch() により起動しておく必要がある.

     [5] ox_launch();
     0

     [5] ox_launch_nox("127.0.0.1","/usr/local/lib/asir","/usr/local/lib/asir/ox_asir");
     0

後者の場合および環境変数 DISPLAY が設定されていない場合, xtermは起動されず, ox_asir により起動される Asir の出力は /dev/null に接続される. デバッグが完了し, 子プロセスの表示するメッセージを見る必要がない場合には ox_launch_nox() を用いればよい.

     [7] RemoteLibDir = "/usr/local/lib/asir/"$
     [8] Machines = ["sumire","rokkaku","genkotsu","shinpuku"];
     [sumire,rokkaku,genkotsu,shinpuku]
     [9] Servers = map(ox_launch,Machines,RemoteLibDir,RemoteLibDir+"ox_asir");
     [0,1,2,3]

参照
     ox_launch, ox_launch_nox, ox_shutdown

ox_rpc, ox_cmo_rpc, ox_execute_string
-------------------------------------

ox_rpc(NUMBER,"FUNC",ARG0,...)
ox_cmo_rpc(NUMBER,"FUNC",ARG0,...)
ox_execute_string(NUMBER,"COMMAND",...)
     :: プロセスの函数呼び出し

return
     0

number
     数 (プロセス識別子)

func
     函数名

command
     文字列

arg0, arg1, ...
     任意 (引数)

  * 識別子 NUMBER のプロセスの函数を呼び出す.

  * 函数の計算終了を待たず, 直ちに 0 を返す.

  * ox_rpc() は, サーバが ox_asir の場合のみ用いることができる. それ以外の場合は, ox_cmo_rpc() を用いる.

  * 函数が返す値は ox_pop_local(), ox_pop_cmo() により取り出す.

  * サーバが ox_asir 以外のもの (例えば Kan サーバ ox_sm1など) の場合には, Open_XM プロトコルでサポートされているデータのみを送ることができる.

  * ox_execute_string は, 送った文字列 COMMAND をサーバが自らのユーザ言語パーザで解析し, 評価した結果をサーバのスタックに置くように指示する.

     [234] ox_cmo_rpc(0,"dp_ht",dp_ptod((x+y)^10,[x,y]));
     0
     [235] ox_pop_cmo(0);
     (1)*<<10,0>>
     [236] ox_execute_string(0,"12345 % 678;");
     0
     [237] ox_pop_cmo(0);
     141

参照
     ox_pop_local, ox_pop_cmo

ox_reset,register_handler
-------------------------

ox_reset(NUMBER)
     :: プロセスのリセット

register_handler(FUNC)
     :: プロセスのリセットのための関数登録

return
     1

number
     数 (プロセス識別子)

func
     関数子または 0

  * ox_reset() は, 識別子 NUMBER のプロセスをリセットし, コマンド受け付け状態にする.

  * そのプロセスが既に書き出した, あるいは現在書き出し中のデータがある場合, それを全部読み出し, 出力バッファを空にした時点で戻る.

  * 子プロセスが RUN 状態の場合でも, 割り込みにより強制的に計算を終了させる.

  * 分散計算を行う函数の先頭で, 使用するプロセスに対して実行する. あるいは計算途中での強制中断に用いる.

  * register_handler() は, C-c などによる割り込みの際に, u を指定することで, 無引数ユーザ定義関数 FUNC() が呼び出されるように設定する. この関数に, ox_reset() を呼び出させることで, 割り込みの際に自動的に Open XM server のリセットを行うことができる.

  * FUNC に 0 を指定することで, 設定を解除できる.

     [10] ox_launch();
     0
     [11] ox_rpc(0,"fctr",x^100-y^100);
     0
     [12] ox_reset(0); /* xterm のウィンドウには usr1 : return to toplevel by SIGUSR1 */
     1              /* が表示される.                                              */

     [340] Procs=[ox_launch(),ox_launch()];
     [0,1]
     [341] def reset() { extern Procs; map(ox_reset,Procs);}
     [342] map(ox_rpc,Procs,"fctr",x^100-y^100);
     [0,0]
     [343] register_handler(reset);
     1
     [344] interrupt ?(q/t/c/d/u/w/?) u
     Abort this computation? (y or n) y
     Calling the registered exception handler...done.
     return to toplevel

参照
     ox_rpc

ox_push_cmo, ox_push_local
--------------------------

ox_push_cmo(NUMBER,OBJ)
ox_push_local(NUMBER,OBJ)
     :: OBJ を識別子 NUMBER のプロセスに送信

return
     0

number
     数(プロセス識別子)

obj
     オブジェクト

  * 識別子 NUMBER のプロセスに OBJ を送信する.

  * ox_push_cmo は, Asir 以外の Open_XM サーバに送信する際に用いる.

  * ox_push_local は, ox_asir, ox_plot にデータを送る場合に用いることができる.

  * バッファがいっぱいにならない限り, ただちに復帰する.

参照
     ox_rpc, ox_cmo_rpc, ox_pop_cmo, ox_pop_local

ox_pop_cmo, ox_pop_local
------------------------

ox_pop_local(NUMBER)
     :: プロセス識別子 NUMBER からデータを受信する.

return
     受信データ

number
     数 (プロセス識別子)

  * プロセス識別子 NUMBER のプロセスからデータを受信する.

  * ox_pop_cmo は, Asir 以外の Open_XM サーバから受信する際に用いる.

  * ox_pop_local は, ox_asir, ox_plot からデータを受け取る場合に用いることができる.

  * サーバが計算中の場合ブロックする. これを避けるためには, ox_push_cmd で SM_popCMO (262) または SM_popSerializedLocalObject (258) を送っておき, ox_select でプロセスが ready になっていることを確かめてから ox_get すればよい.

     [3] ox_rpc(0,"fctr",x^100-y^100);
     0
     [4] ox_push_cmd(0,258);
     0
     [5] ox_select([0]);
     [0]
     [6] ox_get(0);
     [[1,1],[x^2+y^2,1],[x^4-y*x^3+y^2*x^2-y^3*x+y^4,1],...]

参照
     ox_rpc, ox_push_cmd, ox_select, ox_get

ox_push_cmd, ox_sync
--------------------

ox_push_cmd(NUMBER,COMMAND)
     :: プロセス識別子 NUMBER のプロセスにコマンド COMMAND を送信する.

ox_sync(NUMBER)
     :: プロセス識別子 NUMBER のプロセスに OX_SYNC_BALL を送信する.

return
     0

number
     数 (プロセス識別子)

command
     数 (コマンド識別子)

  * 識別子 NUMBER のプロセスにコマンドまたは OX_SYNC_BALL を送信する.

  * Open_XM において送受信データは OX_DATA, OX_COMMAND, OX_SYNC_BALLの 3 種類に分かれる. 通常, コマンドは何らかの操作に付随して暗黙のうちに送信されるが, これをユーザが個別に送りたい場合に用いられる.

  * OX_SYNC_BALL は ox_reset による計算中断, 復帰の際に送受信されるが, これを個別に送りたい場合に用いる. なお, 通常状態では OX_SYNC_BALL は無視される.

参照
     ox_rpc, ox_cmo_rpc, ox_reset

ox_get
------

ox_get(NUMBER)
     :: プロセス識別子 NUMBER のプロセスからデータを受信する.

return
     受信データ

number
     数(プロセス識別子)

  * プロセス識別子 NUMBER のプロセスからデータを受信する. 既にストリーム上にデータがあることを仮定している.

  * ox_push_cmd と組み合わせて用いる.

  * ox_pop_cmo, ox_pop_local は, ox_push_cmd と ox_get の組み合わせで実現されている.

     [11] ox_push_cmo(0,123);
     0
     [12] ox_push_cmd(0,262); /* 262=OX_popCMO */
     0
     [13] ox_get(0);
     123

参照
     ox_pop_cmo, ox_pop_local, ox_push_cmd

ox_pops
-------

ox_pops(NUMBER[,NITEM)
     :: プロセス識別子 NUMBER のプロセスのスタックからデータを取り除く.

return
     0

number
     数 (プロセス識別子)

nitem
     自然数

  * プロセス識別子 NUMBER のプロセスのスタックからデータを取り除く. NITEM が指定されている場合は NITEM 個, 指定のない場合は 1 個取り除く.

     [69] for(I=1;I<=10;I++)ox_push_cmo(0,I);
     [70] ox_pops(0,4);
     0
     [71] ox_pop_cmo(0);
     6

参照
     ox_pop_cmo, ox_pop_local

ox_select
---------

ox_select(NLIST[,TIMEOUT])
     :: 読み出し可能なプロセスの識別子を返す.

return
     リスト

nlist
     数 (子プロセス識別子) のリスト

timeout
     数

  * 識別子リスト NLIST のプロセスのうち既に出力を返しているプロセスの識別子リストを返す.

  * 全てのプロセスが RUN 状態のとき, いずれかのプロセスの終了を待つ. 但し, TIMEOUT が指定されている場合, TIMEOUT 秒だけ待つ.

  * ox_push_cmd() で SM_popCMO あるいは SM_popSerializedLocalObject を送っておき, ox_select() で ready 状態のプロセスを調べてox_get() することで, ox_pop_local(), ox_pop_cmo()で待ち状態に入るのを防ぐことができる.

     ox_launch();
     0
     [220] ox_launch();
     1
     [221] ox_launch();
     2
     [222] ox_rpc(2,"fctr",x^500-y^500);
     0
     [223] ox_rpc(1,"fctr",x^100-y^100);
     0
     [224] ox_rpc(0,"fctr",x^10-y^10);
     0
     [225] P=[0,1,2];
     [0,1,2]
     [226] map(ox_push_cmd,P,258);
     [0,0,0]
     [227] ox_select(P);
     [0]
     [228] ox_get(0);
     [[1,1],[x^4+y*x^3+y^2*x^2+y^3*x+y^4,1],
     [x^4-y*x^3+y^2*x^2-y^3*x+y^4,1],[x-y,1],[x+y,1]]

参照
     ox_pop_local, ox_pop_cmo, ox_push_cmd, ox_get

ox_flush
--------

ox_flush(ID)
     :: 送信バッファの強制 flush

return
     1

id
     子プロセス識別子

  * 通常はバッチモードは off であり, データ, コマンド送信ごとに送信バッファは flush される.

  * バッチモードは "ctrl" コマンドの "ox_batch" スイッチで on/off できる.

  * 細かいデータを多数送る場合に, ctrl("ox_batch",1) でバッチモードを on にすると, バッファがいっぱいになった場合にのみ flush されるため, overhead が小さくなる場合がある. ただしこの場合には, 最後に ox_flush(ID) を実行して, バッファを強制的に flush する必要がある.

  * ox_pop_cmo, ox_pop_local のように, コマンド送信後ただちにデータ待ちに入る関数がハングしないよう, これらの関数の内部では強制 flush が実行されている.

     [340] ox_launch_nox();
     0
     [341] cputime(1);
     0
     7e-05sec + gc : 4.8e-05sec(0.000119sec)
     [342] for(I=0;I<10000;I++)ox_push_cmo(0,I);
     0.232sec + gc : 0.006821sec(0.6878sec)
     [343] ctrl("ox_batch",1);
     1
     4.5e-05sec(3.302e-05sec)
     [344] for(I=0;I<10000;I++)ox_push_cmo(0,I); ox_flush(0);
     0.08063sec + gc : 0.06388sec(0.4408sec)
     [345] 1
     9.6e-05sec(0.01317sec)

参照
     ox_push_cmo, ox_push_local, ox_pop_cmo, ox_pop_local, ctrl

ox_get_serverinfo
-----------------

ox_get_serverinfo([ID])
     :: server の Mathcap, 動作中のプロセス識別子の取得

return
     リスト

id
     子プロセス識別子

  * 引数 ID があるとき, プロセス識別子 ID のプロセスの Mathcap をリストとして返す.

  * 引数なしのとき, 現在動作中のプロセス識別子およびその Mathcap からなるペアを, リストとして返す.

     [343] ox_get_serverinfo(0);
     [[199909080,Ox_system=ox_sm1.plain,Version=2.991118,HOSTTYPE=FreeBSD],
     [262,263,264,265,266,268,269,272,273,275,276],
     [[514],[2130706434,1,2,4,5,17,19,20,22,23,24,25,26,30,31,60,61,27,33,40,16,34]]]
     [344] ox_get_serverinfo();
     [[0,[[199909080,Ox_system=ox_sm1.plain,Version=2.991118,HOSTTYPE=FreeBSD],
     [262,263,264,265,266,268,269,272,273,275,276],
     [[514],[2130706434,1,2,4,5,17,19,20,22,23,24,25,26,30,31,60,61,27,33,40,16,34]]]],
     [1,[[199901160,ox_asir],
     [276,275,258,262,263,266,267,268,274,269,272,265,264,273,300,270,271],
     [[514,2144202544],
     [1,2,3,4,5,2130706433,2130706434,17,19,20,21,22,24,25,26,31,27,33,60],[0,1]]]]]

参照
     Mathcap.

ifplot, conplot, plot, plotover
-------------------------------

ifplot(FUNC [,GEOMETRY] [,XRANGE] [,YRANGE] [,ID] [,NAME])
     :: 2 変数関数の実数上での零点を表示する.

conplot(FUNC [,GEOMETRY] [,XRANGE] [,YRANGE] [,ZRANGE] [,ID] [,NAME])
     :: 2 変数関数の実数上での等高線を表示する.

plot(FUNC [,GEOMETRY] [,XRANGE] [,ID] [,NAME])
     :: 1 変数関数のグラフを表示する.

plotover(FUNC,ID,NUMBER)
     :: すでに存在しているウィンドウへ描画する.

return
     整数

func
     多項式

geometry, xrange, yrange, zrange
     リスト

id, number
     整数

name
     文字列

  * ifplot() は, 2 変数関数 FUNC の実数上での零点のグラフの表示を行う. conplot() は, 同様の引数に対し, 等高線の表示を行う. plot() は 1 変数関数のグラフの表示を行う. Windows 版は現状では未サポートである.

  * UNIX 版は, 遠隔プロセスにより実現されている. コマンドは ox_plot で, ox_launch() により起動しておく必要がある. ox_plot は, Asir の標準ライブラリディレクトリにある.

  * 引数の内, FUNC は必須である. その他の引数はオプションである. オプションの形式およびそのデフォルト値 (カッコ内) は次の通り.

     geometry
          ウィンドウのサイズをドット単位で [X,Y] で指定する. (UNIX 版では [300,300]. )

     xrange, yrange
          変数の範囲の指定で, [V,VMIN,VMAX] で指定する. (いずれの変数も [V,-2,2].) この指定がない場合, FUNC に含まれる変数の内変数順序の上の変数が x, 下の変数が y として扱われる. これを避けるためには XRANGE, YRANGE を指定する. また, FUNC が 1 変数の場合, これらの指定は必須となる.

     zrange
          conplot() の場合のみ指定できる. 形式は [V,VMIN,VMAX [,STEP ]] で, STEP が指定された場合には, 等高線の間隔が (VMAX-VMIN)/STEP となる. ([Z,-2,2,16].)

     id
          遠隔プロセスの番号, すなわち ox_launch() が返した番号を指定する. (一番最近に作られ, かつアクティブなプロセスに対応する番号.)

     name
          ウィンドウの名前. (Plot.) 生成されたウィンドウのタイトルは NAME:N/M となる. これは, プロセス番号 N のプロセスの, M 番のウィンドウを意味する. この番号は, plotover() で用いられる.

  * 一つのプロセス上で描画できるウィンドウの数は最大 128 個である.

  * plotover() は, 指定したウィンドウ上に, 引数である 2 変数多項式の零点を上書きする.

  * 描画終了後のウィンドウ上で, マウスの左ボタンを押しながらのドラッグで範囲を指定しボタンを離すと新たなウィンドウが生成され, 指定した範囲が拡大して表示される. ドラッグは左上から右下へと行う. ドラッグを始めた後キャンセルする場合は, マウスポインタを始点の上か左に持っていってボタンを離せばよい. 新しいウインドウの形は, 指定領域と相似で, 最大辺が, 元のウィンドウの最大辺と一致するように定められる. 以下で説明する precise が on の場合, 選択した領域が同一 window 上で書き直される.

  * ウィンドウ内で右ボタンを押すと, その点の座標がウィンドウの下部に表示される.

  * conplot() で生成したウィンドウにおいて, ウィンドウの右側のマーカを中ボタンでドラッグすると, 対応する等高線の色が変わり, 右上のウィンドウに対応するレベルが表示される.

  * UNIX 版ではいくつかのボタン, Mac 版ではプルダウンメニューによりいくつかの設定変更, 操作ができる. UNIX 版では次のボタンがある.

     quit
          window を破壊する. 計算を中断する場合, ox_reset() を用いる.

     wide (トグル)
          現在の表示部分を縦横各 10 倍した領域を表示する. 現在表示されている範囲はこの表示において中央部に長方形で示される. この表示で範囲指定を行うと, その範囲が新しいウィンドウに描画される.

     precise (トグル)
          選択領域を, 整数演算により, より正確に再描画する. これは, FUNC が有理数係数の 2 変数多項式の場合にのみ有効である. このモードでは Sturm 列と二分法により, 区間内の零点の個数を正確に求めていくもので, デフォルトの計算法よりも正確な描画が期待できる. ただし, 描画時間は余計にかかる場合が多い. この説明から明らかなように, この機能は有理数係数の多項式の描画に対してのみ有効である. ((x^2+y^2-1)^2 の描画で試してみよ.)

     formula
          対応する式を表示する.

     noaxis (トグル)
          座標軸を消す.

  * ox_plot が起動されるマシンによっては, スタックを大量に使用するものもあるため, .cshrc でスタックサイズを大きめ (16MB 程度) に指定しておくのが安全である. スタックサイズは limit stacksize 16m などと指定する.

  * X では、ウインドウの各部分について resource により色付けや、ボタンの形を変えることができる。 resource の指定の仕方は以下の通り。（デフォルトを示しておく） plot*form*shapeStyle は、rectangle, oval, ellipse, roundedRectangle が、指定できる。

          plot*background:white
          plot*form*shapeStyle:rectangle
          plot*form*background:white
          plot*form*quit*background:white
          plot*form*wide*background:white
          plot*form*precise*background:white
          plot*form*formula*background:white
          plot*form*noaxis*background:white
          plot*form*xcoord*background:white
          plot*form*ycoord*background:white
          plot*form*level*background:white
          plot*form*xdone*background:white
          plot*form*ydone*background:white

参照
     ox_launch, ox_shutdown, ox_reset