6

私はOCamlにいます。

通信ノードをシミュレートして、さまざまな通信スキームなどでメッセージがどのくらいの速さで伝播するかを調べています。

ノードは、1。固定メッセージを送信および2.受信できます。当然のことは、各ノードを個別のスレッドにすることだと思います。

どうやら、イベントモジュールとチャネルを使用してスレッドを相互にメッセージを渡すことができますが、この例は見つかりません。誰かが私を正しい方向に向けることができますか、それとも簡単な関連する例を教えてくれますか?

どうもありがとう。

4

3 に答える 3

7

はい、 OCamlのイベントモジュールを使用できます。その使用例は、オンラインのO'Reillyの本にあります。

于 2012-02-12T09:58:18.400 に答える
7

シミュレーションを試みる場合は、単にスレッドを使用するよりもはるかに多くのノードを制御する必要があります。少なくとも、大きな問題はありません。

このトピックに対する私の主観的なアプローチは、シミュレーションを完全に制御し続けるために、単純なシングルスレッドの仮想マシンを作成することです。OCamlでこれを行う最も簡単な方法は、モナドのような構造を使用することです(たとえば、Lwtで行われるように):

(* A thread is a piece of code that can be executed to perform some
   side-effects and fork zero, one or more threads before returning. 
   Some threads may block when waiting for an event to happen. *)
type thread = < run : thread list ; block : bool >

(* References can be used as communication channels out-of-the box (simply 
   read and write values ot them). To implement a blocking communication 
   pattern, use these two primitives: *)

let write r x next = object (self) 
  method block = !r <> None
  method run   = if self # block then [self]
                 else r := Some x ; [next ()]
end

let read r next = object (self) 
  method block = !r = None
  method run   = match r with 
                  | None -> [self]
                  | Some x -> r := None ; [next x]
end

チャネルに「送信に必要な時間」プロパティを追加するなど、ニーズに合ったより優れたプリミティブを作成できます。

次のステップは、シミュレーションエンジンを定義することです。

(* The simulation engine can be implemented as a simple queue. It starts 
   with a pre-defined set of threads and returns when no threads are left, 
   or when all threads are blocking. *)
let simulate threads = 
  let q = Queue.create () in 
  let () = List.iter (fun t -> Queue.push t q) threads in 
  let rec loop blocking = 
    if Queue.is_empty q then `AllThreadsTerminated else 
      if Queue.length q = blocking then `AllThreadsBlocked else 
        let thread = Queue.pop q in 
        if thread # block then ( 
          Queue.push thread q ; 
          loop (blocking + 1) 
        ) else ( 
          List.iter (fun t -> Queue.push t q) (thread # run) ; 
          loop 0
        ) 
  in
  loop 0 

ここでも、エンジンを調整して、どのノードがどのスレッドを実行しているかを追跡したり、ノードごとの優先順位を維持して、あるノードが他のノードよりも大幅に遅いまたは速いことをシミュレートしたり、すべてのステップで実行するスレッドをランダムに選択したりできます。すぐ。

最後のステップはシミュレーションの実行です。ここでは、2つのスレッドが乱数を送受信します。

let rec thread name input output = 
  write output (Random.int 1024) (fun () -> 
    read input (fun value ->
      Printf.printf "%s : %d" name value ; 
      print_newline () ;
      thread name input output
  ))

let a = ref None and b = ref None 
let _ = simulate [ thread "A -> B" a b ; thread "B -> A" b a ]        
于 2012-02-13T18:08:40.547 に答える
5

ジョン・レッピーのコンカレントMLを考えているようですね。ここにOCamlにも似たようなものがあるようです。

@Thomasが与えた答えも価値がありますが、このスタイルの並行プログラミングを使用したい場合は、非常に読みやすく、CMLの背後にある動機とそのいくつかの実質的な例を非常に明確に扱っているJohnReppyのPhD論文を読むことをお勧めします使用する。セマンティクスに興味がない場合は、その部分をスキップしてもドキュメントは引き続き読み取り可能です。

于 2012-02-12T01:00:23.713 に答える