大型矩阵第二列分箱求和的高效实现方案问询
大型矩阵第二列分箱求和的高效实现方案问询
大家好,我现在碰到一个大型矩阵处理的性能瓶颈问题,想请教各位有没有更高效的实现思路。
我的需求是这样的:手里有一个4000列 × 1亿行的超大矩阵,需要根据第二列的数值把这1亿行划分成1000个等距区间(分箱),然后对每个箱内的所有行按列求和,最终得到一个1000行 × 4000列的结果矩阵。
下面是我目前尝试过的几种方法,但速度都达不到预期:
方法一:基础循环实现
import numpy as np # 注:实际数据是1e8行,这里用1000万行做测试模拟 aa = np.random.rand(10000000, 4000) l, r = np.min(aa[:,1]), np.max(aa[:,1]) bins = np.linspace(l, r, 1001) results = [] for bn in range(1000): ll, rr = bins[bn], bins[bn+1] # 每次循环都做布尔索引筛选子集再求和 sum_bin = np.sum(aa[(aa[:,1] > ll) & (aa[:,1] < rr)], axis=0) results.append(sum_bin) binmap = np.array(results)
这个方法最直观,但问题也很突出——每次循环都要对1亿行数据做布尔筛选,重复1000次后整体速度慢得难以接受。
方法二:Numba并行加速尝试
from numba import njit, prange @njit(parallel=True) def sumgood(bins, dd): results = np.zeros((1000, 4000), dtype=np.float64) # 用prange开启并行循环 for bn in prange(1000): l, r = bins[bn], bins[bn+1] subset = dd[(dd[:,1] > l) & (dd[:,1] < r)] sum_subset = np.sum(subset, axis=0) results[bn] = sum_subset return results binmap = sumgood(bins, aa)
本来以为Numba的并行能显著提升速度,但实际运行下来还是没达到预期,推测是循环内的布尔索引和子集求和依然是性能瓶颈。
方法三:exec动态变量拼接(不推荐的尝试)
for bn in range(1000): l, r = bins[bn], bins[bn+1] exec(f'good{bn}=np.sum(aa[(aa[:,1]>l) &( aa[:,1]< r) ],axis=0)') # 拼接所有动态生成的变量 binmap = np.concatenate([globals()[f'good{bn}'] for bn in range(1000)]).reshape(1000, 4000)
这种写法本身就很不优雅,而且速度上也没有任何实质性提升,纯粹是病急乱投医的尝试。
想请教各位大佬,针对这种大规模矩阵的分箱求和需求,有没有更高效的优化方向?比如能不能避免反复做子集筛选?或者有没有numpy的原生函数、其他工具库能更好地处理这类问题?
备注:内容来源于stack exchange,提问作者questionhang
相关产品推荐
相关产品推荐

