【发布时间】:2015-10-19 00:35:26
【问题描述】:
我已经开始使用 clojure core.async 库。我发现 CSP、channels、go 块的概念真的很容易使用。但是,我不确定我是否正确使用它们。我有以下代码-
(def x-ch (chan))
(def y-ch (chan))
(def w1-ch (chan))
(def w2-ch (chan))
; they all return matrices
(go (>! x-ch (Mat/* x (map #(/ 1.0 %) (max-fold x)))))
(go (>! y-ch (Mat/* y (map #(/ 1.0 %) (max-fold y)))))
(go (>! w1-ch (gen-matrix 200 300)))
(go (>! w2-ch (gen-matrix 300 100)))
(let [x1 (<!! (go (<! x-ch)))
y1 (<!! (go (<! y-ch)))
w1 (<!! (go (<! w1-ch)))
w2 (<!! (go (<! w2-ch)))]
;; do stuff w/ x1 y1 w1 w2
)
我在符号x 和y 中有预定义的(矩阵)向量。我需要在使用它们之前修改这两个向量。这些向量非常大。我还需要生成两个随机矩阵。由于go 宏以异步方式启动计算,因此我将所有四个计算任务拆分为单独的 go 块,并将结果放入通道中。然后我有一个 let 块,我从通道中获取值并将它们存储到符号中。他们都在使用阻塞 <!! 函数,因为它们在主线程上。
我要做的基本上是通过将程序片段拆分为异步进程来加快计算时间。这是正确的做法吗?
【问题讨论】:
-
为什么要在这里使用异步代码?当您必须阻塞和等待时,异步代码是有效的。否则它什么也不做。当您只需要进行数学运算时,您应该直接或并行计算它,例如将来。
-
谢谢。在我的代码中,我同时开始 4 个计算并阻止/等待这些值,直到它们返回一些东西。这与异步阻塞/等待有何不同?但是,就像尼古拉斯和你指出的那样,我将为此使用未来。我不能在 go 块中使用 core.reducers 吗?或者这是一个可怕的想法?
-
您不会同时启动它们。一切都是按顺序执行的,因为您在 go 块中没有有价值的阻塞操作。我定义了函数“素数?”测试数字 i 是否为素数。看这里:"(time (do (count (filter true? (map prime? (range 2 20000)))))" 给出 3 秒和 "(time (count (filter true? (map prime? (range 2 20000) )))))" 给出 3 秒。你只使用一个线程,这里的一切都是顺序的。测试一下!
-
谢谢。已经将我的代码切换为使用未来。
标签: performance concurrency clojure core.async