Чем объясняется разница в производительности в Dask между DataFrame.assign (** kwargs) и dd [x] = y при добавлении нескольких столбцов? - PullRequest
0 голосов
/ 15 апреля 2020

При переносе некоторого кода из Pandas в Dask я обнаружил огромную разницу в производительности между изменением фрейма данных Dask путем вызова DataFrame.assign() с несколькими столбцами и изменением его с помощью нескольких вызовов DataFrame.__setitem__() (он же dataframe[x]=y).

С импортом

import pandas, dask, cProfile

Для кадра данных Dask, определенного как:

dd = dask.dataframe.from_pandas(pandas.DataFrame({'a':[1]}), npartitions=1)
cProfile.run('for i in range(100): dd["c"+str(i)]=dd["a"]+i')

, занимает 1,436 секунды

, а

cProfile.run('dd.assign(**{"c"+str(i):dd["a"]+i for i in range(100)})')

занимает всего 0,211 секунды. Разница в 6,8 раза.

Я уже пробовал смотреть на статистику с pyprof2calltree, но не смог ее понять.

Чем объясняется эта разница? И что еще более важно, есть ли способ получить производительность assign без необходимости рефакторинга кода, который многократно использует dd [x] = y?

Это может не иметь значения или произойти для больших наборов данных, у меня нет ' t проверено, но это относится к одной строке (почему меня беспокоит то, что Dask работает быстро для отдельных строк, это отдельная topi c).

Для контекста тоже есть разница в Pandas, но это намного меньше:

df = pandas.DataFrame({'a':[1]})
cProfile.run('for i in range (100): df["c"+str(i)]=df["a"]+i')

занимает 0,116 секунды.

cProfile.run('df.assign(**{"c"+str(i):df["a"]+i for i in range(100)})')

занимает 0,096 секунды. Просто 1.2X.

1 Ответ

0 голосов
/ 15 апреля 2020

Две основные причины:

  1. Формула для l oop создает больший граф задач (один новый слой на элемент в l oop) по сравнению с одной дополнительной задачей из assign.
  2. DataFrame.__setitem__ фактически реализовано в терминах присвоения: https://github.com/dask/dask/blob/366c7998398bc778c4aa5f4b6bb22c25b584fbc1/dask/dataframe/core.py#L3424 -L3432 , так что в итоге вы вызываете один и тот же код, просто много раз. Каждое назначение связано с копией в pandas.

Я уже пробовал просматривать статистику с помощью pyprof2calltree, но не смог разобраться в этом.

Подобные профилировщики (построенные на cProfile) плохо подходят для профилирования параллельного кода, такого как Dask.

...