非常大的数组处理与宇宙和numpy
问题描述:
由于某些原因,我需要使用天文转换comoving距离红移。基本上这涉及阅读,循环和写出列表或numpy数组......我的问题是,我的每个列表通常由〜9.5 x 10^6个元素组成。每当我尝试使用numpy.savetxt将输出保存到新的txt文件时,这会给我带来MemoryError。内存使用量快速增长,最终会减慢一点,但总是会提高128Gb的限制。非常大的数组处理与宇宙和numpy
如果有人知道我如何改进下面的脚本,我非常愿意倾听。谢谢!
import os
import sys
import glob
import math
import numpy
import astropy
import astropy.units as unit
from astropy.cosmology import *
cosmo = FlatLambdaCDM(H0=70, Om0=0.3)
inFile=sys.argv[1]
outFile=sys.argv[2]
comovingDistance = numpy.loadtxt(inFile, usecols=(2,))
Redshift = numpy.zeros(len(comovingDistance))
for i in range(len(comovingDistance)):
Redshift[i] = z_at_value(cosmo.comoving_distance, comovingDistance[i] * unit.kpc)
output = open(outFile,'w')
numpy.savetxt(output, Redshift, fmt='%1.8e')
output.close()
下面是错误日志文件:
Traceback (most recent call last):
File "comoving2redshift.py", line 21, in <module>
Redshift[i] = z_at_value(cosmo.comoving_distance, comovingDistance[i] * unit.kpc)
File "/afs/mpa/home/minh/.local/lib/python2.7/site-packages/astropy/cosmology/funcs.py", line 119, in z_at_value
fval_zmax = func(zmax)
File "/afs/mpa/home/minh/.local/lib/python2.7/site-packages/astropy/cosmology/core.py", line 1195, in comoving_distance
return self._comoving_distance_z1z2(0, z)
File "/afs/mpa/home/minh/.local/lib/python2.7/site-packages/astropy/cosmology/core.py", line 1219, in _comoving_distance_z1z2
return self._hubble_distance * vectorize_if_needed(f, z1, z2)
File "/afs/mpa/home/minh/.local/lib/python2.7/site-packages/astropy/units/quantity.py", line 924, in __mul__
return super(Quantity, self).__mul__(other)
File "/afs/mpa/home/minh/.local/lib/python2.7/site-packages/astropy/units/quantity.py", line 368, in __array_prepare__
from .quantity_helper import UNSUPPORTED_UFUNCS, UFUNC_HELPERS
MemoryError
答
我不知道内在的任何解决numpy的,但你可以立即书面每个解决方案文件保存一些内存分配,而不是后for循环。当numpy.savetxt()
将浮点格式设置为字符串时,这节省了Redshift
的内存分配以及在幕后完成的内存分配。
inFile=sys.argv[1]
outFile=sys.argv[2]
comovingDistance = numpy.loadtxt(inFile, usecols=(2,))
with open(outFile, 'w') as fp:
for distance in comovingDistance:
fp.write("{:1.8e}\n".format(
z_at_value(cosmo.comoving_distance, distance * unit.kpc)))
(注:未经测试)
答
作为一种替代我的其他建议的解决方案,可以拆分输入文件,迭代一套新的(临时)输入文件,并连接所有的输入文件在结束。 下面是一个bash包装器脚本,它在外面应该与问题中的Python脚本(一个输入文件参数,一个输出文件参数)完全相同。
#! /bin/bash
nlines=10000
input=$1
output=$2
# use a unique prefix!
prefix='tmpsplit'
split --lines=$nlines $input $prefix
outfiles=()
# Assume we only split to a maximum of 26^2 files
# This is the default for split anyway
for filename in ${prefix}??
do
outfile="${filename}-out"
./calcdist.py $filename $outfile
done
# This assumes the shells orders the glob expansion alphabetically
cat ${prefix}*out > $output
# Clean up
rm ${prefix}*
您可能需要使用一个临时目录,而不是依赖于一个独特的前缀。
你在哪一行得到'MemoryError'? – Divakar
@Divakar我在问题中添加了错误日志文件... –
[文档]中的注释(http://docs.astropy.org/en/stable/api/astropy.cosmology.z_at_value.html) z_at_value'似乎与你的案例有关,你可能想要尝试这种方法。另外,你有没有试图看看'z_at_value'是否是矢量化的?很可能你不需要迭代自己,也可以简单地执行'Redshift = z_at_value(cosmo.comoving_distance,comovingDistance * unit.kpc)'而无需分配'Redshift'数组。 – Jaime