假设我有一个以压缩方式存储numpy数组的类,但也支持索引:
class Compressed:
def __init__(self, numpy_array):
"... store numpy_array in a compressed way ..."
def __getitem__(self, index):
return "... the equivalent of numpy_array[index] ..."
是否有一种合理的(非hacky)方式可以让它与持久性很好地协同工作?我希望能够定义一个大的(但可压缩的)数组x,然后得到x.persist()的等价物,但内存数据全部包含在压缩实例中。奖金,如果它也可以与dask.persist()
一起使用。
答案 0 :(得分:0)
是的,你可以在你的dask.array的块上映射你的Compressed
类,坚持下去,然后跟进np.asarray
的调用。您的数据将以压缩格式保留。这有点非法,因为大多数numpy操作不适用于这些块。但是,如果您跟进对np.asarray
的懒惰调用,那么一切都应该是安全的。
在下面的示例中,我们使用bcolz.carray
类执行此操作,该类实现压缩数组。
import bcolz
import dask.array as da
import numpy as np
x = da.random.randint(0, 100, size=(1000, 1000, 1000), chunks=(100, 100, 100))
x = x.map_blocks(bcolz.carray).persist().map_blocks(np.asarray) # <<--- main point
import psutil;
>>> psutil.Process().memory_info().rss / x.nbytes # compression ratio
0.173897216
>>> x.sum().compute() # things still work
49499671807
但是,在访问之前,这会在每个块上调用np.asarray
,如果您的压缩方案支持随机访问,则可能效率最高。如果这对您至关重要,请告诉我,我会看看是否可以找到解决方法。
此外,值得指出的是,如果您使用的是分布式调度程序,并且每个节点都有本地磁盘,则Dask会以压缩格式将多余数据转储到磁盘。这显然比从内存中压缩数据中读取要慢,但仍然有用。