2013-10-30 81 views
4

我想創建一個從真正巨大的列表SciPy的陣列。但不幸的是,我偶然發現了一個問題。真的創造巨大SciPy的陣列

我有一個列表XS,字符串。每個字符串的長度爲。

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

如果我只轉換第一元素,一切仍然正常工作。

>>> 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 是最小尺寸造成問題的原因。 我這個小腳本判定:

#!/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' 
+0

對不起,不由自主,因爲無法複製。你能找出導致錯誤的最小'xs'子集大小嗎? – alko

+0

@alko:我添加信息質疑 – yapphdorlw

+0

由於2147483648 = 2 ** 31,我很舒爾這是內存分配/在SciPy的adressation限制,可能是由於簽署了INT32使用。我建議scipy [問題跟蹤]解決這個錯誤(http://www.scipy.org/scipylib/bug-report.html) – alko

回答

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') 


""" 
+0

有趣。我的筆記本內存不足可能是可能的,儘管我不認爲其他機器(在大學實驗室有內存音調)也有同樣的問題。 (下次將檢查,如果它具有相同'最小尺寸導致問題') – yapphdorlw

+0

對,這是有道理的。然後你可能可以使用memmap沒有問題。 – Paul

+0

我剛剛檢查過它。服務器具有相同的限制。不幸的是,對於我的具體應用,memmap比我的解決方法慢。 但很高興知道有存儲空間。也許我有一天會需要他們。 – yapphdorlw