for循环和算术运算中大型numpy数组的内存使用问题

2024-10-01 09:39:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我对python还很陌生。我对循环有一个隐式的时间积分,也就是说,下一步取决于上一步。基本上,我试图通过利用numpy阵列的广播特性而不利用更多的for循环来解决所有不同情况下的时间积分问题。因此,我有大数组

循环运行时间短(2.5秒),但在for循环中执行操作时,我的RAM(8 GB)几乎达到了它的容量。因此,我正在努力克服一个内存使用问题

ndata = 9624
u.shape = (3, 9624, 11, 3, 1000)
p.shape = (9624, 11, 1, 1000)
a1.shape = (11, 3, 1000)
a2.shape = (11, 3, 1000)
a3.shape = (11, 3, 1000)
p_star.shape = (11, 3, 1000)
delta_t.shape =(11, 1, 1)
k_star.shape =(11, 3, 1000)

for i in range(0,ndata-1):
    p_star = p[i+1] + a1 * u[0,i] + a2 * u[1,i] + a3 * u[2,i]
    u[0,i+1] = p_star / k_star
    u[1,i+1] = gama * (u[0,i+1]-u[0,i]) / (beta * delta_t) + u[1,i] * (1 - gama/beta) + delta_t * u[2,i] * (1 - gama/(2*beta))
    u[2,i+1] = (u[0,i+1]-u[0,i]) / (beta * (delta_t ** 2)) - u[1,i] / (beta * delta_t) - u[2,i] * ((1 / (2*beta)) - 1)

You can see memory usage in the loop here

在算术操作期间,将创建并分配数组的临时副本。我认为这里的主要问题是创建数组的副本。为了克服这个问题,应该进行算术运算

要执行这些操作,据我所知,应该定义numpy ufuncs的可选参数out=,或者应该使用+=-=*=/=。例如,numpy.sum(a1,a2, out=a1)

但为了以适当的方式执行上述操作,我必须定义许多辅助(或缓冲)变量。 我的问题是什么是减少内存使用的最佳方法。我相信,在python中,必须有一种优雅的方法来执行这些类型的算术运算

我也愿意接受其他建议

buff1 = np.zeros_like(u[0,0])
buff2 = np.zeros_like(u[0,0])
buff3 = np.zeros_like(u[0,0])
buff4 = np.zeros_like(u[0,0])
for i in range(0,ndata-1):
    # first line
    np.multiply(a1, u[0,i], out = buff1);
    np.multiply(a2, u[1,i], out = buff2);
    np.multiply(a3, u[2,i], out = buff3);
    buff1 += p[i+1];
    buff1 += buff2;
    buff1 += buff3;
    #second line
    np.divide(buff1, k_star, out = u[0,i+1])
    #third line
    np.subtract(u[0,i+1], u[0,i], out = buff1);
    buff1 *= gama
    buff1 /= beta
    buff1 /= delta_t
    np.divide(gama,beta, out = buff2)
    np.subtract(1, buff2, out=buff2)
    np.multiply(u[1,i], buff2, out=buff2)
    np.multiply(2, beta, out = buff3)
    np.divide(gama, buff3, out = buff3)
    np.subtract(1, buff3, out = buff3)
    np.multiply(u[2,i], buff3, out = buff3)
    np.multiply(delta_t, buff3, out = buff3)
    np.add(buff1, buff2, out = u[1,i+1])
    np.add(buff3, u[1,i+1], out = u[1,i+1])
    #last line goes like that
    


Tags: a2fora1npoutmultiplybetalike
1条回答
网友
1楼 · 发布于 2024-10-01 09:39:18

问题实际上是数组p和u的大小。加起来,它们由大约10亿个浮点数组成,每个浮点数用64位表示。或者,总共8 GBs。如果您需要保留所有9264个时间步,恐怕您对此无能为力。当然,如果您只保留最后两个时间步,情况会发生变化

相关问题 更多 >