如何以NumPy视图形式构造含重复块的大型正方形矩阵?
问题
需要构造一个大小为N*M × N*M的大型正方形矩阵,用于numpy的matmul运算。该矩阵存在大量重复结构:每个M×M的方块会重复N×N次。例如当M=2、N=3时:
import numpy as np s = np.array([[1,2], [3,4]]) S = np.array([[1,2,1,2,1,2], [3,4,3,4,3,4], [1,2,1,2,1,2], [3,4,3,4,3,4], [1,2,1,2,1,2], [3,4,3,4,3,4],])
目标是将S构造为s的视图以节省内存。尝试结合broadcast_to和reshape实现,代码如下:
import numpy N = 10000 M = 10 w = numpy.random.rand(N*M, 1) s = numpy.random.rand(M, M) S4d = numpy.broadcast_to(s, shape=(N, N, M, M)) S = S4d.reshape(N*M, N*M)
运行后报错:
numpy.core._exceptions._ArrayMemoryError: Unable to allocate 74.5 GiB for an array with shape (10000, 10000, 10, 10) and data type float64
请问是否有方法按上述要求构造矩阵S?
一种临时方案是编写针对该场景的矩阵乘法函数,但考虑实际参数M≈1e3、N≈1e4时,w'*S*w的运算量达O(1e14),速度会很慢。
补充说明
发现w'*S*w可以拆解为w的切片与s的乘法,整个计算仅需1秒左右。但仍想知道是否能将S构造为s的视图。
解决方案
无法直接构造出N*M × N*M形状的s的视图,核心原因如下:
- numpy的视图要求数组元素在内存中按固定步长连续排列,而
S的二维重复块结构无法通过调整s的内存步长实现:同一行、同一列的M×M块都要重复N次,这种双向重复的布局无法映射到s的单一内存结构上。 - 你尝试的
broadcast_to生成的4D数组本身是视图,但后续的reshape操作会触发内存复制——因为(N,N,M,M)的内存布局无法直接重塑为(N*M, N*M)而不打乱元素顺序,numpy会被迫分配新内存存储完整矩阵,最终导致内存不足。
如果想近似实现“低内存占用的大型矩阵”效果,可以用稀疏矩阵存储S,利用其重复结构大幅压缩内存:
import numpy as np from scipy.sparse import kron N = 10000 M = 10 s = np.random.rand(M, M) # 构造重复块结构的稀疏矩阵 S_sparse = kron(np.ones((N, N)), s)
kron生成的稀疏矩阵不会存储所有重复块,仅记录块的重复规则,内存占用仅与N和M×M的大小相关,远小于完整稠密矩阵,后续矩阵乘法也会自动利用结构优化计算。
另外,你已经找到的w'*S*w拆解计算方案其实是最优解——直接通过数学简化避免构造大型矩阵,比任何视图或稀疏矩阵方案的效率都更高。
内容的提问来源于stack exchange,提问作者user443854
相关产品推荐
相关产品推荐

