【发布时间】:2017-02-22 15:56:20
【问题描述】:
这是 FEM/FVM 方程系统的典型用例,因此可能具有更广泛的兴趣。从三角形网格 à la
我想创建一个scipy.sparse.csr_matrix。矩阵行/列表示网格节点处的值。该矩阵在主对角线上以及两个节点通过边连接的任何位置都有条目。
这是一个 MWE,它首先建立一个节点->边->细胞关系,然后建立矩阵:
import numpy
import meshzoo
from scipy import sparse
nx = 1600
ny = 1000
verts, cells = meshzoo.rectangle(0.0, 1.61, 0.0, 1.0, nx, ny)
n = len(verts)
nds = cells.T
nodes_edge_cells = numpy.stack([nds[[1, 2]], nds[[2, 0]],nds[[0, 1]]], axis=1)
# assign values to each edge (per cell)
alpha = numpy.random.rand(3, len(cells))
vals = numpy.array([
[alpha**2, -alpha],
[-alpha, alpha**2],
])
# Build I, J, V entries for COO matrix
I = []
J = []
V = []
#
V.append(vals[0][0])
V.append(vals[0][1])
V.append(vals[1][0])
V.append(vals[1][1])
#
I.append(nodes_edge_cells[0])
I.append(nodes_edge_cells[0])
I.append(nodes_edge_cells[1])
I.append(nodes_edge_cells[1])
#
J.append(nodes_edge_cells[0])
J.append(nodes_edge_cells[1])
J.append(nodes_edge_cells[0])
J.append(nodes_edge_cells[1])
# Create suitable data for coo_matrix
I = numpy.concatenate(I).flat
J = numpy.concatenate(J).flat
V = numpy.concatenate(V).flat
matrix = sparse.coo_matrix((V, (I, J)), shape=(n, n))
matrix = matrix.tocsr()
与
python -m cProfile -o profile.prof main.py
snakeviz profile.prof
可以创建和查看上述个人资料:
tocsr() 方法在这里占据了运行时的最大份额,但在构建 alpha 更复杂时也是如此。因此,我正在寻找加快速度的方法。
我已经找到了什么:
-
由于数据的结构,矩阵对角线上的值可以提前求和,即
V.append(vals[0, 0, 0] + vals[1, 1, 2]) I.append(nodes_edge_cells[0, 0]) # == nodes_edge_cells[1, 2] J.append(nodes_edge_cells[0, 0]) # == nodes_edge_cells[1, 2]这使得
I、J、V更短,从而加快了tocsr。 现在,边缘是“每个单元格”的。我可以使用
numpy.unique识别彼此相等的边缘,有效节省了大约一半的I、J、V。但是,我发现这也需要一些时间。 (不足为奇。)
我的另一个想法是,如果有一个类似于csr_matrix 的数据结构,其中主对角线为分开存放。我知道这存在于其他一些软件包中,但在 scipy 中找不到。对吗?
也许有一种明智的方式来直接构建 CSR?
【问题讨论】:
-
我想看看不同步骤的一些时间安排。
tocsr使用编译后的代码。我认为事先对coo输入的任何按摩都需要同样长的时间。 -
您确定
tocsr需要很长时间吗?我对一个 10k x 10k 矩阵做了非常相似的事情,其中 I、J、V 的长度达到了数百万,而且不需要那么长时间。也许 5-10 秒。 -
感谢 cmets。我已在原始帖子中添加了个人资料。
-
有趣。我认为
sum_duplicates是编译后的csr构造的一部分,但您的配置文件显示它是coo.py中的Python 方法。它使用lexsort、np.nonzero和reduceat。所以做你自己的sum_duplicates是有希望的。如果你的coohas_canonical_formattocsr应该更快。 -
csr有自己的sum_duplicates方法。它使用编译后的sparse._sparsetools.csr_sum_duplicates。
标签: python numpy matrix scipy scientific-computing