具有m列的压缩稀疏列矩阵(csc),定义为here。
它有三个数组:Data,Indices和Indptr。
具有n行的压缩稀疏行(csr)矩阵具有类似的definition。
问题:
Cpu适用于n个作业。第p个作业产生具有n行和m列的稀疏矩阵(csc或csr)的第q行的数据。 p和q不必相等,只要哪个作业对应于记录哪一行。
如何有效地从作业中收集数据并生成csc矩阵?
目前的解决方案:
方法A.
after acquiring lock
shared_data[counter_nz:(counter_nz + job_nz)] = job_data
shared_indices[counter_nz:(counter_nz + job_nz)] = job_indices
shared_indptr[count_row + 1] = shared_indptr[count_row] + job_nz
shared_ordering[counter_row] = job_id
counter_nz += job_nz
counter_row += 1
release lock.
通过包装共享数组创建一个csr矩阵对象(如scipy.sparse.csr_matrix((shared_data,shared_indices,shared_indptr))。
将csr转换为csc矩阵(目标是制作csc矩阵而不是csr矩阵......)
这种方法的问题是锁实际上会杀死性能。就像十几个人试图抓住相同的工具来处理项目的不同部分。
方法B
每个cpu都可以处理m个作业,并使用A中描述的方法构建csc矩阵。这种方式使用了更多的内存,但矩阵的生成速度更快。
方法C
一个cpu在m作业上工作并构建一个csc矩阵。这比12 cpu机器上的接近A大约多两倍的时间。
方法D(2016年6月5日更新)
有cpu核心。最终csc矩阵和shared_ordering数组的shared_data,shared_indptr和shared_indices数组由所有cpu内核共享。无需锁定。每个cpu核心运行一个子进程(而不是一直启动和停止子进程)每个cpu核心进程m个作业的1 / s和每个cpu使用A中描述的方法构造一个小的csc矩阵。在cpu完成所有作业之后,它将三个大小的数据广播到其他cpus的三个小csc矩阵阵列中。一旦cpu从所有其他cpu接收到此信息(有s-1信息从其他cpus接收),它将计算其小csc矩阵的三个数组在最终csc矩阵的三个数组中的位置。然后它将其小csc矩阵复制到共享csc矩阵。
之后,cpu向其他cpu发送信号。一旦cpu收到s-1信号,它就会开始下一个周期。 (可能不需要第二次同步。)
希望同步将比A中的锁更少浪费时间。并且这种方法从1个cpu核心线性扩展到12个cpu核心。如果有人有这方面的经验,请随时提出建议。
方法D的缺点是它使用的内存量是内存所需数量的两倍来保存最终的csc矩阵。内存的一半用于共享阵列。另一半被小csc矩阵的所有数组使用......这似乎没问题。在方法B中,每个cpu只有大约1 / s的整个内存可供使用。方法D更好。
可以将小型matrics的数组保留为缓冲区,因此不必浪费时间来重新创建numpy数组。
我正在尝试使用B并优化每个作业的每个CPU内核的内存使用量。但是如果方法A可以避免通过更智能的锁设计来杀死性能,我会使用A ......我想我会选择D. 相关问题: Efficiently populate SciPy sparse matrix from subset of dictionary
答案 0 :(得分:2)
听起来你已经创建了一个csr
矩阵,然后直接修改了3个属性数组。而这是通过附加到现有数组来实现的。虽然我操纵了csr的data
属性,但我没有直接改变其他属性的经验。似乎很难可靠地做,并且没有稀疏代码反对。
另一种方法是首先构造3个数组,然后构造csr
。而不是每行使用np.append
,而是附加到列表,并使用np.concatenate
加入它们。
如果您使用coo
输入样式,则可以按任意顺序追加行。一项工作不必知道前一行中有多少项目。
coo
样式输入对于有限元刚度矩阵特别好,其中元素的矩阵重叠。 coo
输入可以直接转到csc
。
我最近讨论过从块构建稀疏矩阵: https://stackoverflow.com/a/37040831/901925
和
tile operation to create a csr_matrix from one row of another csr_matrix
lil
适用于增量工作,因为属性是列表的两个对象数组 - 每行一个列表。因此更新只需要用新列表替换两个空列表 - 指针操作。但我认为lil
到csc
比coo
慢到csc
(但我还没有测试过它)。