与其他许多人一样,我的情况是我有一个类收集大量数据,并提供一种将数据作为numpy数组返回的方法。 (即使在返回数组后,其他数据也可以继续流入)。由于创建数组是一项昂贵的操作,我只想在必要时创建它,并尽可能高效地创建它(特别是在可能的情况下就地附加数据)。为此,我一直在阅读有关ndarray.resize()方法和refcheck参数的内容。我明白,只有当“你确定你没有与另一个Python对象共享这个数组的内存”时,refcheck应该被设置为False。ndarray.resize:为refcheck参数传递正确的值
事情是我不确定。有时候我有,有时候我没有。如果refcehck失败(我可以捕获它,然后创建一个新副本),但是我希望它只在存在“真实的”外部引用时才会失败,而忽略了我认为是安全的那些引用。
这里有一个简单的例证:
import numpy as np
def array_append(arr, values, refcheck = True):
added_len = len(values)
if added_len == 0:
return arr
old_len = len(arr)
new_len = old_len + added_len
arr.resize(new_len, refcheck = refcheck)
arr[old_len:] = values
return arr
class DataCollector(object):
def __init__(self):
self._new_data = []
self._arr = np.array([])
def add_data(self, data):
self._new_data.append(data)
def get_data_as_array(self):
self._flush()
return self._arr
def _flush(self):
if not self._new_data:
return
# self._arr = self._append1()
# self._arr = self._append2()
self._arr = self._append3()
self._new_data = []
def _append1(self):
# always raises an error, because there are at least 2 refs:
# self._arr and local variable 'arr' in array_append()
return array_append(self._arr, self._new_data, refcheck = True)
def _append2(self):
# Does not raise an error, but unsafe in case there are other
# references to self._arr
return array_append(self._arr, self._new_data, refcheck = False)
def _append3(self):
# "inline" version: works if there are no other references
# to self._arr, but raises an error if there are.
added_len = len(self._new_data)
old_len = len(self._arr)
self._arr.resize(old_len + added_len, refcheck = True)
self._arr[old_len:] = self._new_data
return self._arr
dc = DataCollector()
dc.add_data(0)
dc.add_data(1)
print dc.get_data_as_array()
dc.add_data(2)
print dc.get_data_as_array()
x = dc.get_data_as_array() # create an external reference
print x.shape
for i in xrange(5000):
dc.add_data(999)
print dc.get_data_as_array()
print x.shape
问题:
- 有没有做什么,我试图做的(逐步建立numpy的数组)更好的(快)的方式?
- 有没有告诉resize()方法的方法:“执行refcheck,但忽略那个我知道安全的引用(或n个引用)”? (这将解决_append1问题()总是失败)
这个解决方案的缺点是平均使用50%以上的内存,在我的情况下意味着几GB。但是,当然,在尺寸和速度之间有一个折衷,在我看来,速度可能更重要。我马上试一下。 – shx2 2013-03-07 07:08:51