4

我想从一个非常大的列表中创建一个 scipy 数组。但不幸的是,我偶然发现了一个问题。

我有一个字符串列表xs。每个字符串的长度为1

>>> type(xs)
<type 'list'>
>>> len(xs)
4001844816

如果我只转换前10 个元素,一切仍然按预期工作。

>>> s = xs[0:10]
>>> x = scipy.array(s)
>>> x
array(['A', 'B', 'C', 'D', 'E', 'F', 'O', 'O'],
      dtype='|S1‘)
>>> len(x)
10

对于整个列表,我得到以下结果:

>>> ary = scipy.array(xs)
>>> ary.size
1
>>> ary.shape
()
>>> ary[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: 0-d arrays can't be indexed
>>>ary[()]
...The long list

一种解决方法是:

test = scipy.zeros(len(xs), dtype=(str, 1))
for i in xrange(len(xs)):
    test[i] = xs[i]

不是内存不足的问题。到目前为止,我将使用解决方法(需要 15 分钟)。但我想了解这个问题。

谢谢

- 编辑:解决方法的备注test[:] = xs将不起作用。(也因0-d IndexError而失败)

在我的 macbook上, 2147483648是导致问题的最小尺寸。我用这个小脚本确定了它:

#!/usr/bin/python
import scipy as sp

startlen = 2147844816

xs = ["A"] * startlen
ary = sp.array(xs)
while ary.shape == ():
    print "bad", len(xs)
    xs.pop()
    ary = sp.array(xs)

print "good", len(xs)
print ary.shape, ary[0:10]
print "DONE."

这是输出

...
bad 2147483649
bad 2147483648
good 2147483647
(2147483647,) ['A' 'A' 'A' 'A' 'A' 'A' 'A' 'A' 'A' 'A']
DONE.

python版本是

>>> sys.version
'2.7.5 (default, Aug 25 2013, 00:04:04) \n[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)]'
>>> scipy.version.version
'0.11.0'
4

1 回答 1

1

假设您有 64 位 OS/Python/Numpy,您可能会遇到一些内存不足情况的表现——这有时可能是不寻常的。您的第一个列表是 4GB,然后您为 numpy 数组分配了额外的 4GB。即使对于 x64,这些也是大数组。你以前见过 memmap 数组吗?

我在下面所做的是创建了一系列 memmap 数组,显示(对于我的机器)断点在哪里(主要是磁盘 IO)。然而,体面的数组大小可以创建 300 亿个“S1”元素。此代码可能会帮助您查看 memmap 数组是否可以为您的问题提供一些好处。他们很容易使用。使用 memmap 数组可以加快 15 分钟的解决方法。

baseNumber = 3000000L
#dataType = 'float64'#
numBytes = 1
dataType = 'S1'
for powers in arange(1,7):
  l1 = baseNumber*10**powers
  print('working with %d elements'%(l1))
  print('number bytes required %f GB'%(l1*numBytes/1e9))
  try:
    fp = numpy.memmap('testa.map',dtype=dataType, mode='w+',shape=(1,l1))
    #works 
    print('works')
    del fp
  except Exception as e:
    print(repr(e))


"""
working with 30000000 elements
number bytes required 0.030000 GB
works
working with 300000000 elements
number bytes required 0.300000 GB
works
working with 3000000000 elements
number bytes required 3.000000 GB
works
working with 30000000000 elements
number bytes required 30.000000 GB
works
working with 300000000000 elements
number bytes required 300.000000 GB
IOError(28, 'No space left on device')
working with 3000000000000 elements
number bytes required 3000.000000 GB
IOError(28, 'No space left on device')


"""
于 2013-11-04T13:51:26.170 回答