Чем больше потоков изменяет ссылку на Clojure, тем больше увеличивается число повторов на потоки? - PullRequest
4 голосов
/ 19 сентября 2010

Я немного беспокоюсь об этом.
Представьте себе самый простой способ управления версиями, когда программисты просто копируют весь каталог из главного репозитория, а после изменения файла делают обратное, если главный репозиторий остается прежним.Если это было изменено другим, они должны попробовать еще раз.

Когда число программистов увеличивается, естественно, что повторные попытки также увеличиваются, но это может быть не пропорционально количеству программистов.
Если десять программисты работают и работа занимаетчас на человека, чтобы выполнить всю работу десять часов необходимы как минимум.
Если они серьезны, то около 9 + 8 + 7 + ... 1 = 45 человеко-часов сводятся на нет.
В огромном количестве программистов, около 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)))

Процессор: 2,93 ГГц Четырехъядерный процессор 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

Я изменил задание на (Thread / sleep n) вместо (fib 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

В случае Thread / sleep я думаю, что повторные попытки могут увеличить больше, чем этот результат, потому чтоПроцессор доступен.
Почему бы не увеличить количество попыток?

Спасибо.

Ответы [ 2 ]

5 голосов
/ 19 сентября 2010

Потому что вы на самом деле не создаете 10, 100 или 1000 потоков!Создание future не всегда создает новую тему .Он использует пул потоков за кулисами , где он продолжает ставить в очередь задания (или Runnable s, чтобы быть техническим).Пул потоков - это кешированный пул потоков, который использует потоки для выполнения заданий.

Таким образом, в вашем случае вы на самом деле не создаете 1000 потоков.Если вы хотите увидеть повторы в действии, получите уровень ниже future - создайте свой собственный пул потоков и вставьте в него Runnable s.

1 голос
/ 20 сентября 2010

самоответ

Я изменил основную функцию, чтобы не использовать 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)))

fib

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
...