【发布时间】:2020-05-20 19:40:09
【问题描述】:
以下代码在使用纯 Python 时运行时间为 45 秒。
for iteration in range(maxiter):
for node in range(n):
for dest in adjacency_list[node]:
rs[iteration + 1][dest] += beta * rs[iteration][node] / len(adjacency_list[node])
但是,通过简单地将 rs 初始化为 numpy ndarray 而不是 python 列表,代码在 145 秒内运行。我真的不知道为什么 numpy 在这个数组索引上花费 3 倍的时间。
我的想法是尽可能多地矢量化,但只设法矢量化了 beta/len(adjacency_list[node]) 的乘法。此代码在 77 秒内运行。
beta_over_out_degree = np.array([beta / len(al) for al in adjacency_list])
for iteration in range(1, maxiter + 1):
r_next = np.full(shape=n, fill_value=(1 - beta) / n)
f = beta_over_out_degree * r
for i in range(n):
r_next[adjacency_list[i]] += f[i]
r = np.copy(r_next)
rs[iteration] = np.copy(r)
问题在于adjacency_list 是具有不同列大小的列表的列表,具有 100 000 行和 1-15 列。
具有邻接矩阵的更标准方法(至少作为正常的 ndarray)不是一种选择,因为对于 n=100 000,它的 (n,n) 形状太大而无法分配给内存。
有没有办法使用它的索引来向量化 numpy 高级索引(也许把它变成一个 numpy ndarray)?
我也非常感谢任何其他速度提示。 提前致谢!
编辑:感谢@stevemo,我设法创建了具有csr_matrix 功能的adjacency_matrix,并将其用于迭代乘法。程序现在只需 2 秒即可运行!
for iteration in range(1, 101):
rs[iteration] += rs[iteration - 1] * adjacency_matrix
【问题讨论】:
-
你能分享数组的尺寸吗?也许创建一个虚拟示例?
-
您需要所有迭代中的值,还是只需要最后一个?
-
如果你指的是adjacency_list的值,因为它用在最内层循环中,所以我在所有迭代中都需要它们。
-
n=100000 时,形状为:r->(1,n),rs(100,n),adjacency_list->(n,介于 1 和 15 之间)
-
索引数组的单个元素比较慢。