我正在尝试在 numpy 中执行取决于多个参数的计算,并涉及创建许多中间数组。这些中间步骤涉及更多参数的积分。正因为如此,在我计算的部分过程中,我尝试创建一个数组,我意识到它的低端大小约为 30GB。我的系统无法处理这个。
作为我遇到的问题的一般示例,请考虑以下 Python 代码:
param1s = np.linspace(min1, max1, 100)
param2s = np.linspace(min2, max2, 100)
param3s = np.linspace(min3, max3, 100)
def main(param1, param2, param3):
dummy_param_as = np.linspace(0, 10, 100)
dummy_param_bs = np.linspace(-1, 1, 100)
huge_array = do_big_calculation(params1, params2, params3,
dummy_param_as, dummy_param_bs)
integral_over_dummy_b = np.trapz(huge_array, x=dummy_param_bs axis=-1)
return np.trapz(integral_over_dummy_b, x=dummy_param_as, axis=-1)
具体来说,do_big_calculation将所有参数沿单独的轴一起广播,创建一个 shape 数组(100, 100, 100, 100, 100)。然而,这个数组不需要存在很长时间,直到它可以集成到它的最后两个轴上。
对于这种情况,似乎有一个强烈推荐的解决方案:使用h5py或dask之类的东西将数据写入存储,并通过从存储的文件中加载块中的数据来执行计算。这种类型的解决方案似乎通常被称为核外方法。
但是,我发现了另一种似乎很少被讨论的途径:将结果流出来并迭代地构造结果,而无需触及存储。我发现的一个这样的解决方案是npstreams。
对于我的玩具示例,这种方法的工作方式是huge_array在内存中逐步构建梯形规则总和,以便huge_array根本不会加载到内存中。npstreams看起来像是一种实现方式。
我很好奇,考虑到我正在计算我的数据而不是加载存储的数据,这些方法的优缺点是什么?一个可能会更快吗?一个或两个都存在缩放问题?