Как говорит кто-то, удаление dosync, кажется, улучшает ситуацию в 10 раз, но это не вся история. Как только JVM имеет hotspotted ваш код, он получает еще один фактор на 10 быстрее. Вот почему вы должны использовать критериум или подобный, чтобы проверить реальную скорость ...
(def number (atom 0))
(defn tak [x y z]
(if (<= x y)
y
(do
(swap! number inc)
(tak (tak (dec x) y z)
(tak (dec y) z x)
(tak (dec z) x y)))))
(defn takeuchi_number [n]
(reset! number 0)
(tak n 0 (inc n))
@number)
;=> (time (takeuchi_number 10))
; "Elapsed time: 450.028 msecs"
; 1029803
;=> (time (takeuchi_number 10))
; "Elapsed time: 42.008 msecs"
; 1029803
Оригинала с dosync был около 5 секунд на моей машине, поэтому мы два порядка основания 10 магнитуды уже! Это лучшее, что мы можем сделать? Давайте реорганизуем чистые функции и убежим от счетчика.
(defn tak [c x y z]
(if (<= x y)
[c y]
(let [[a- x-] (tak 0 (dec x) y z)
[b- y-] (tak 0 (dec y) z x)
[c- z-] (tak 0 (dec z) x y)]
(recur (+' 1 a- b- c- c) x- y- z-))))
(defn takeuchi_number [n]
(tak 0 n 0 (inc n)))
;=> (time (takeuchi_number 10))
; "Elapsed time: 330.741 msecs"
; [1029803 11]
;=> (time (takeuchi_number 10))
; "Elapsed time: 137.829 msecs"
; [1029803 11]
;=> (time (takeuchi_number 10))
; "Elapsed time: 136.866 msecs"
; [1029803 11]
Не так хорошо. Стоимость хранения состояния в векторе и его передачи, вероятно, является накладными расходами. Однако теперь мы переработали чистоту, давайте воспользуемся нашим хорошим поведением!
=> (def tak (memoize tak))
#'euler.tak/tak
=> (time (takeuchi_number 10))
"Elapsed time: 1.401 msecs"
[1029803 11]
Здоровые 3000 или около того раз быстрее. Работает на меня.
Вам это нужно как метрика для вызовов этой функции за всю ее жизнь или вы хотите, чтобы это число было результатом? для более позднего эта ошибка была бы неправильной (одновременные вызовы) и ее прохождение (например, как мета) было бы лучше. – cfrick
Отбрасывание 'dosync', которое вам не нужно для замены атомов, увеличивает время выполнения для меня в 5 раз. – Jens
Я имел в виду DEcreases ;-) – Jens