【问题标题】:Clojure Refs in a game loop for state: why does it go slower and slower?游戏循环中的 Clojure Refs 状态:为什么它变得越来越慢?
【发布时间】:2013-03-19 23:07:11
【问题描述】:

我正在尝试根据上一步更新每个步骤的地图。我有一个 ref 是数字向量的向量,为了模糊我的世界地图,我向左、向右、向上和向下旋转,然后平均我的四个新世界地图。我将此更新作为主循环中的“更改”。它最初很快,但越来越慢。我是否没有以某种我不知道的方式放开我的脑袋?似乎它在每一步都进行了所有先前的计算。这是我的代码:

我定义地图:

      (def gradient-map
       (ref( vec (repeat columns (vec (repeat rows 0))))))

这是我的更新功能:

(defn rotate-grid-up [grid]
  (map #(concat (rest %) [(last %)]) grid))
(defn rotate-grid-down [grid]
  (map #(concat [(first %)] (drop-last %)) grid))
(defn rotate-grid-right [grid]
  (concat [(first grid)] (drop-last grid)))
(defn rotate-grid-left [grid]
  (concat (rest grid) [(last grid)]))

(defn blur [grid]
  (let [g1 (rotate-grid-up grid)
        g2 (rotate-grid-down grid)
        g3 (rotate-grid-left grid)
        g4 (rotate-grid-right grid)]
   (vec (map
     (fn [r1 r2 r3 r4 r5]
       (vec (map
        #(/ (+ %1 %2 %3 %4 %5) 5)
        r1 r2 r3 r4 r5)))
     g1 g2 g3 g4 grid))))

然后在我的绘图循环中,我模糊每个 tic

(dosync (alter gradient-map blur))

并且绘制循环慢到爬行。

【问题讨论】:

  • 所有的旋转函数都是惰性的(mapconcat 都是惰性的)。也许您应该尝试将所有旋转函数的主体包裹在 doall 中,看看是否有帮助。
  • 你确定这个doasync 是罪魁祸首吗?你在你的绘图循环中还做了什么?
  • 你为什么使用 refs?是否有多个线程?您是否以比完成工作更快的速度创作作品?

标签: clojure ref


【解决方案1】:

代码创建了太多向量,导致内存使用和 gc 增加。

您可以尝试不创建向量,懒惰地做所有事情,或者您可以最小化它们的创建。或者,您可以改用矩阵库(例如 core.matrix 或 Incanter)。

另外,无关的,你需要一个游戏状态的 ref 吗?如果没有与其他此类事物的依赖关系,那么一个原子就足够了?

【讨论】:

    【解决方案2】:

    在我相当新的计算机上,1000x1000 网格的模糊大约需要 2.7 秒。您的世界地图是否会随着时间的推移而增长?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-11
      • 2018-04-21
      • 2015-12-20
      • 1970-01-01
      • 1970-01-01
      • 2016-11-03
      • 2016-06-12
      • 1970-01-01
      相关资源
      最近更新 更多