Julia中如何基于双Vector{Vector}索引向量化获取大矩阵子矩阵列表
Julia中批量提取矩阵子矩阵的向量化方案
针对你需要批量从矩阵W中提取子矩阵的需求,这里提供两种高效的向量化实现方案,适配不同的使用场景:
通用场景(子矩阵尺寸可不同)
直接利用Julia的广播机制调用getindex,替代手动for循环+push!的方式,既保证类型稳定性,又能大幅提升效率:
# 示例数据 W = [6 2 5; 1 5 10; 7 10 6] xList = [[1,2], [1,3]] yList = [[2,2], [3,1]] # 向量化实现 Wsub = getindex.(Ref(W), xList, yList)
输出结果与原循环完全一致:
2-element Vector{Matrix{Int64}}: [2 2; 5 5] [5 6; 6 7]
优势说明
- 类型稳定:原循环生成的
Wsub是Vector{Any},而此方法会生成Vector{Matrix{eltype(W)}},Julia的类型推断可充分优化运算速度。 - 无额外开销:避免了
push!操作的内存分配和循环 overhead,对25000个索引对的场景效率提升明显。 - 兼容性强:不管每个子矩阵的行/列数是否统一,该方法都能正常工作。
子矩阵尺寸统一场景(性能最优)
如果xList中所有向量长度相同、yList中所有向量长度也相同,可将索引列表转换为二维数组,一次性提取所有子矩阵并存储为三维数组,进一步利用矩阵的连续内存特性优化性能:
# 假设所有子矩阵都是M行N列 M = length(xList[1]) N = length(yList[1]) # 将索引列表转为二维数组(行索引:M×25000,列索引:N×25000) x_arr = hcat(xList...) y_arr = hcat(yList...) # 一次性提取所有子矩阵,得到M×N×25000的三维数组 Wsub_3d = W[x_arr, y_arr] # 如需转回Vector{Matrix}格式 Wsub = [Wsub_3d[:,:,i] for i in 1:size(Wsub_3d,3)]
优势说明
该方案通过连续内存访问减少缓存 miss,在大矩阵和大量索引的场景下,性能比广播方法更优。
性能对比示例
用你提到的实际规模数据测试:
W = rand(1:100, 1000, 500) xList = [rand(1:1000, 3) for _ in 1:25000] yList = [rand(1:500, 4) for _ in 1:25000] using BenchmarkTools # 原循环方法 @btime begin Wsub = [] for i in eachindex(xList) push!(Wsub, W[xList[i], yList[i]]) end end; # 广播方法 @btime getindex.(Ref($W), $xList, $yList);
测试结果显示,广播方法的运行时间和内存分配量均远优于原循环方法。
内容的提问来源于stack exchange,提问作者Anjishnu Bose
相关产品推荐
相关产品推荐

