Dask and Numba - Как эффективно использовать разделы карты? - PullRequest
0 голосов
/ 10 января 2019

Я пытаюсь ускорить мой код и улучшить мое понимание Dask и Numba, я пытался использовать оба в некоторых примерах, но улучшений нет, и я не могу понять, почему.

Я должен сказать, что я на ноутбуке с четырьмя ядрами, поэтому улучшение может быть небольшим, но тем не менее оно должно быть.

Точнее, на ноутбуке с Windows 10, использующим Python 3.7 и имеющим Numba и Dask в среде conda.

Вот мой код:

import numpy as np
import pandas as pd
from numba import jit
import dask.dataframe as dd

data = np.random.randint(-10, 10, (10**8, 3))
df = pd.DataFrame(data=data, columns=["A", "B", "C"], index=None)
df["F"] = np.random.choice(["apple", "banana", "orange", 
                            "pear","grape","lime","citrus","peach"],10**8)

Как вы можете видеть, это довольно большой объем памяти для данных, поэтому я мог проверить, был ли Даск представлен на улучшении или нет. На меньших кадрах данных (<200 МБ) это, похоже, не имеет никакого значения. </p>

ddf = dd.from_pandas(df,npartitions=12)

@jit
def remove_special_char_with_numba(x):
    return x.replace('r','')

Это игрушечный пример, где я пытаюсь удалить строку из определенного столбца, Numba ускоряет код по сравнению с ванильными пандами, но не поддерживает строки, поэтому я не могу изменить replace или используйте режим nopython. Сейчас:

%%timeit
remove_special_char_with_numba(df["F"])

вывод:

58,9 с ± 9,51 с на цикл (среднее ± стандартное отклонение из 7 циклов, по 1 циклу каждый)

Далее, мое понимание следующего заключается в том, что Dask разделил мой фрейм данных на разные чанки / разделы и что он будет применять эту функцию к каждому отдельному чанку независимо. С четырьмя ядрами это должно ускорить процесс, насколько я понимаю.

%%timeit
ddf["F"].map_partitions(remove_special_char_with_numba).compute()

вывод:

45,9 с ± 10,5 с на цикл (среднее ± стандартное отклонение из 7 циклов, по 1 циклу каждый)

Теперь я не хочу быть жадным, но разве улучшение не должно быть больше этого? Я что-то не так делаю?

Спасибо

1 Ответ

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

Этот результат не должен вас сильно удивлять. Вы, очевидно, работаете с планировщиком потоков по умолчанию.

Это означает, что каждая строковая операция должна получить один питон GIL для того, чтобы это произошло, и это правда, независимо от того, находится ли она в рабочих потоках, контролируемых dask. Это остается верным для версии операции numba-jit, потому что вы не можете запустить эту функцию в режиме без Python. Если бы он был в режиме без Python, он выпустил бы GIL, и полная поддержка строк придет к numba.

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

...