【发布时间】:2014-01-08 23:26:32
【问题描述】:
简短版:在 Clojure 中存储数百个数字的列表的正确方法是什么,其中每个数字都被递增数百万次(可能跨多个线程)?
长版:程序从一个空向量开始,其中每个值都初始化为0:
[0 0 0 0 0 0 0 0 0 ...]
然后它会逐行读取数百万行的文件。在对一行执行一些任意计算之后,程序会增加向量中的一些值。在第一行之后,向量可能如下所示:
[1 1 1 2 0 1 0 1 1 ...]
第二行之后:
[2 2 3 2 2 1 0 2 2 ...]
大约 5000 行之后,它可能看起来像:
[5000 4998 5008 5002 4225 5098 5002 5043 ...]
由于 Clojure 的数据结构是不可变的,因此仅使用 assoc 来增加向量中的值似乎非常浪费,因为每次递增都会复制整个向量。
在不花费所有 CPU 时间复制不可变数据结构的情况下进行这种并发数据聚合的正确方法是什么?我是否应该有一个向量,其中每个元素都类似于 ref 或 atom,所有线程都增加这些共享值?或者,是否有某种线程级的数据结构可以存储计数,然后最后一步是合并来自每个线程的计数?
这可能不会在单个线程上绑定 I/O,所以我猜我会将行处理拆分到多个线程中。向量的长度没有限制(可能有几千个元素长),但很可能是大约 100 个元素长。
【问题讨论】:
标签: multithreading performance data-structures concurrency clojure