为了尝试理解core.async,我尝试实现了“天网100万微基准测试”没有成功,即:
Creates an actor (goroutine, whatever), which spawns 10 new actors, each of them spawns 10 more actors, etc. until one million actors are created on the final level. Then, each of them returns back its ordinal number (from 0 to 999999), which are summed on the previous level and sent back upstream, until reaching the root actor. (The answer should be 499999500000).
这里有多种语言的实现:
https://github.com/atemerev/skynet
这是我完全失败的尝试:
(defn skynet [chan num size div]
(if (= 1 size)
(>! chan num)
(>! chan (reduce + (let [rc (async/chan)
n (/ size div)]
(doall (for [i [0 div]]
(skynet rc (+ num (* i n)) n div))
(for [i [0 div]] (<! rc))))))))
我试图从 REPL 的 go 块中调用它:
(time (go (<!! (skynet (async/chan) 0 1000000 10))))
我可能对有关 core.async 的许多事情(以及惰性求值)感到非常困惑。
我应该如何解决这个问题,为什么?
最佳答案
有some limitations关于 core.async 能够做什么,所以你不能使用 map
或 for
职能。
您的实现非常接近正确的实现。几点:
go
== 一个进程,所以你只是在创建一个进程,而不是 1m <!!
用于 go 块之外 <!
将在 go 块内使用 doall
只接受一个参数 一个可能可以改进的工作实现:
(defn skynet [parent num size div]
(go ;; We create a new process each time skynet is called
(if (= 1 size)
(>! parent num)
(let [self (chan)
new-size (/ size div)]
(dotimes [i div] ;; dotimes is more explicit for side effects
(skynet self (+ num (* i new-size)) new-size div))
(loop [i div ;; Manual reduce
t 0]
(if (zero? i)
(>! parent t)
(recur (dec i)
(+ t (<! self)))))))))
并称之为:
(time
(do
(def result (chan))
(def x (skynet result 0 1000000 10))
(<!! result)))
关于clojure - 如何使用 core.async 实现天网 1m 微基准测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35400990/