4

これはちょっと気になります。
プログラマーがマスター リポジトリからすべてのディレクトリをコピーし、マスター リポジトリがまだ同じ場合はファイルを変更した後に逆の手順を実行する、最も単純なバージョン管理方法を想像してみてください。他のユーザーによって変更された場合は、再試行する必要があります。

プログラマーの数が増えるとリトライも増えるのは当然ですが、プログラマーの数に比例するとは限りません。10 人の
プログラマー が作業し、1 人あたり 1 時間かかるとすると、すべての作業を完了するには、少なくとも10 時間は必要です。 本気でやるなら、9+8+7+…1= 45工数がゼロになる。100人のプログラマーで は、約 99 + 98 + ... 1 = 4950工数が無駄になります。

リトライ回数を数えてみたところ、結果が得られました。

ソース

(defn fib [n] 
   (if  (or (zero? n) (= n 1)) 
       1 
      (+  (fib (dec n) )  (fib (- n 2))))) 

(defn calc! [r counter-A counter-B counter-C n]
  (dosync
   (swap! counter-A inc)
   ;;(Thread/sleep n)
   (fib n)
   (swap! counter-B inc)
   (alter r inc)
   (swap! counter-C inc)))

(defn main [thread-num n]
  (let [r (ref 0)
        counter-A (atom 0)
        counter-B (atom 0)
        counter-C (atom 0)]
    (doall (pmap deref
              (for [_ (take thread-num (repeat nil))]
                (future (calc! r counter-A counter-B counter-C n)))))
    (println thread-num " Thread. @ref:" @r)
    (println "A:" @counter-A ", B:" @counter-B ", C:" @counter-C)))

CPU: 2.93GHz クアッドコア Intel Core i7
結果

user> (time (main 10 25))
10  Thread. @ref: 10
A: 53 , B: 53 , C: 10
"Elapsed time: 94.412 msecs"
nil
user> (time (main 100 25))
100  Thread. @ref: 100
A: 545 , B: 545 , C: 100
"Elapsed time: 966.141 msecs"
nil
user> (time (main 1000 25))
1000  Thread. @ref: 1000
A: 5507 , B: 5507 , C: 1000
"Elapsed time: 9555.165 msecs"
nil

ジョブを (fib n) ではなく (Thread/sleep n) に変更したところ、同様の結果が得られました。

user> (time (main 10 20))
10  Thread. @ref: 10
A: 55 , B: 55 , C: 10
"Elapsed time: 220.616 msecs"
nil
user> (time (main 100 20))
100  Thread. @ref: 100
A: 689 , B: 689 , C: 117
"Elapsed time: 2013.729 msecs"
nil
user> (time (main 1000 20))
1000  Thread. @ref: 1000
A: 6911 , B: 6911 , C: 1127
"Elapsed time: 20243.214 msecs"
nil

スレッド/スリープの場合、CPU が使用可能であるため、リトライはこの結果よりも多くなる可能性があると思います。
リトライが増えないのはなぜですか?

ありがとう。

4

2 に答える 2

5

実際に 10、100、または 1000 のスレッドを生成しているわけではないためです。を作成しfuture ても、常に新しいスレッドが作成されるわけではありません。ジョブをキューに入れ続けるシーンの背後でスレッド プールを使用します (Runnable技術的には s)。スレッド プールは、ジョブを実行するためにスレッドを再利用するキャッシュされたスレッド プールです。

したがって、あなたの場合、実際には 1000 スレッドを生成していません。再試行の動作を確認したい場合は、1 つ下のレベルにfuture進みます。独自のスレッド プールを作成し、そこに s をプッシュRunnableします。

于 2010-09-19T19:15:46.667 に答える
1

自己回答

pmap を使用しないようにメイン関数を変更し、計算どおりに機能する結果を得ました。

(defn main [thread-num n]
  (let [r (ref 0)
        counter-A (atom 0)
        counter-B (atom 0)
        counter-C (atom 0)]
    (doall (map deref (doall (for [_ (take thread-num (repeat nil))]
                   (future (calc! r counter-A counter-B counter-C n))))))
    (println thread-num " Thread. @ref:" @r)
    (println "A:" @counter-A ", B:" @counter-B ", C:" @counter-C)))

フィブ

user=> (main 10 25)
10  Thread. @ref: 10
A: 55 , B: 55 , C: 10
nil
user=> (main 100 25)
100  Thread. @ref: 100
A: 1213 , B: 1213 , C: 100
nil
user=> (main 1000 25)
1000  Thread. @ref: 1000
A: 19992 , B: 19992 , C: 1001
nil

スレッド/スリープ

user=> (main 10 20)
10  Thread. @ref: 10
A: 55 , B: 55 , C: 10
nil
user=> (main 100 20)
100  Thread. @ref: 100
A: 4979 , B: 4979 , C: 102
nil
user=> (main 1000 20)
1000  Thread. @ref: 1000
A: 491223 , B: 491223 , C: 1008
nil
于 2010-09-20T19:46:56.137 に答える