Как использовать один и тот же индекс среди нескольких массивов dask - PullRequest
0 голосов
/ 13 января 2019

Я пытаюсь создать приложение ipython на основе dask, которое содержит мета-класс, который состоит из нескольких под-dask-массивов (все они имеют форму (n_samples, dim_1, dim_2 ...)) и должны быть возможность разбивать под-dask-массивы с помощью оператора getitem .

В методе getitem я вызываю метод da.Array.compute (код все еще находится в очень раннем состоянии), поэтому я мог бы выполнять итерации пакетов подмассивов.

def MetaClass(object):
    ...    
    def __getitem__(self, inds):
        new_m = MetaClass()
        inds = inds.compute()
        for name,var in vars(self).items():
            if isinstance(var,da.Array):
                try:
                    setattr(new_m, name, var[inds])
                except Exception as e:
                    print(e)
            else:
                setattr(new_m, name, var)
        return new_m

# Here I construct the meta-class to work with some directory.
m = MetaClass('/my/data/...')
# m.type is one of the sub-dask-arrays
m2 = m[m.type==2]

Это работает, как и ожидалось, и я получаю нарезанные массивы, но в результате я получаю огромное потребление памяти, и я предполагаю, что в фоновом режиме механизм dask копирует индекс для каждого sub-dask-массива.

У меня вопрос: как мне добиться таких же результатов, не используя столько памяти?

(я пытался не «вычислять» «inds» в getitem , но затем я получал массивы в форме nan, которые не могут быть повторены, что является обязательным для приложения)

Я думал о трех возможных решениях, и я был бы рад узнать, какое из них является «правильным» для меня. (или чтобы найти другое решение, о котором я не думал):

  1. Чтобы использовать Dask DataFrame, в котором я не уверен, как вписать многомерные массивы dask (был бы очень признателен за помощь или даже ссылку, которая объясняет, как обращаться с многомерными массивами в dd).
  2. Чтобы забыть обо всем MetaClass и использовать один dask-массив с неприятным dtype (что-то вроде [("type", int, (1,)), ("images", np.uint8, (1000, 1000))]), опять же, я не знаком с этим и был бы очень признателен за помощь в этом (попытался гуглить это .. это немного сложно ..)
  3. Чтобы использовать индекс как глобальный внутри вызывающей функции ( getitem ) с свойством и его механизмом get-function-механизма (https://docs.python.org/2/library/functions.html#property). Но здесь есть большой недостаток в том, что я теряю типы массивов (большие для представления и всего, что нуждается в чем-либо, кроме самих данных).

Заранее спасибо !!!

1 Ответ

0 голосов
/ 21 января 2019

Можно использовать sub-arrays.map_blocks с общей функцией, которая хранит индексы в своей памяти.

Вот пример:

        def bool_mask(arr, block_info=None):
            from_ind,to_ind = block_info[0]["array-location"][0]
            return arr[inds[from_ind:to_ind]]

        def getitem(var):
            original_chunks = var.chunks[0]
            tmp_inds = np.cumsum([0]+list(original_chunks))
            from_inds = tmp_inds[:-1]
            to_inds = tmp_inds[1:]
            new_chunks_0 = np.array(list(map(lambda f,t:inds[f:t].sum(),from_inds,to_inds)))
            new_chunks = tuple([tuple(new_chunks_0.tolist())] + list(var.chunks[1:]))
            return var.map_blocks(bool_mask,dtype=var.dtype,chunks=new_chunks)
...