我有一个地图矢量,如下所示,尽管每个数据集中可能有100个地图:
data({ a:a b:"2" c:t}{ a:b b:"0" c:t}{ a:c b:"-4" c:t}{ a:d b:"100" c:t}{ a:e b:"50" c:t})
Run Code Online (Sandbox Code Playgroud)
我需要产生以下总和:b
values(map :b data)
sum(reduce + (map read-string values)
Run Code Online (Sandbox Code Playgroud)
这给出了期望的结果,但计算时间长,约为每秒1/10.我正在为数十万个数据集执行此操作,因此需要花费大量处理时间来执行此操作.
任何人都可以建议一种更有效/更快的方法吗?
谢谢
在Clojure 1.2.1中,这是您在100/100秒内完成的总计100.000数据集场景的十分之一.它基本上是你的代码(这不是真正有效的clojure语法,但我们得到了要点),但不知何故运行10.000倍.
;generate 10.000 datasets of 100 maps having 10 fields each
(def scenario-data
(vec (repeatedly 10000
(fn [] (vec (repeatedly 100 (fn [] (zipmap
[:a :b :c :d :e :f :g :h :i :j]
(repeatedly (fn [] (str (- (rand-int 2000) 1000))))))))))))
;now map the datasets into the reduced sums of the parsed :b fields of each dataset
(time (doall (map (fn [dataset] (reduce (fn [acc mp] (+ acc (Integer/parseInt (:b mp)))) 0 dataset))
scenario-data)))
"Elapsed time: 120.43267 msecs"
=> (2248 -6383 7890 ...)
Run Code Online (Sandbox Code Playgroud)
由于这种情况是相当大的内存密集型(10.000数据集〜= 600MB,总计算使用~4GB),我无法在家用机器上运行100.000数据集方案.但是,如果我不将数据集保存在内存中,我可以运行它,但是可以映射到一个惰性序列,而不需要保持它的头部.
(time (doall (map (fn [dataset] (reduce (fn [acc mp] (+ acc (Integer/parseInt (:b mp)))) 0 dataset))
(repeatedly 100000
(fn [] (repeatedly 100 (fn [] (zipmap
[:a :b :c :d :e :f :g :h :i :j]
(repeatedly (fn [] (str (- (rand-int 2000) 1000))))))))))))
"Elapsed time: 30242.371308 msecs"
=> (-4975 -843 1560 ...)
Run Code Online (Sandbox Code Playgroud)
这是计算100.000数据集版本的30秒,包括生成数据所需的所有时间.使用pmap时间大约为一半(4个核心)的切割.
编辑:在具有足够内存的计算机上创建完全实现的100.000数据集需要135秒.在其上运行求和代码需要大约1500毫秒.使用pmap减少到约750毫秒.一个read-string版本是3.5倍〜慢.
TL/DR:如果有足够的内存,您发布的算法可以在1秒内在100.000数据集场景上运行.
请发布您的完整代码,包括您如何阅读并将数据集保存在内存中,并确保这次语法和观察结果都准确无误.由于没有从源头懒洋洋地读取数据集,这可能更多的是内存问题.