сумка dask не использует все ядра? альтернативы?
у меня есть скрипт python, который делает следующее: Я. который принимает входной файл данных (обычно вложенный формат JSON) ii. передает данные строка за строкой в другую функцию, которая управляет данными в желаемом формате iii. и, наконец, он записывает выходные данные в файл.
вот моя текущая простая строка python, которая делает это...
def manipulate(line):
# a pure python function which transforms the data
# ...
return manipulated_json
for line in f:
components.append(manipulate(ujson.loads(line)))
write_to_csv(components)`
это работает, но с python GIL, ограничивающим его одним ядром на сервере, это болезненно медленно, особенно с большими объем данных.
объем данных, с которыми я обычно имею дело, составляет около 4 гигабайт gzip, но иногда мне приходится обрабатывать данные, которые составляют сотни гигабайт gzip. Это не большие данные обязательно, но все еще не могут быть обработаны в памяти, и с GIL Python очень медленно обрабатывается.
при поиске решения для оптимизации обработки данных я наткнулся на dask. В то время как PySpark казался очевидным решением для меня в то время, обещания ДАСК и его простота покорили меня, и я решил попробовать.
после многих исследований в dask и как его использовать, я собрал очень маленький скрипт для репликации моего текущего процесса. Скрипт выглядит так:
import dask.bag as bag
import json
bag.from_filenames('input.json.gz').map(json.loads).map(lambda x:manipulate(x)).concat().to_dataframe().to_csv('output.csv.gz')`
это работает и дает те же результаты, что и мой оригинальный скрипт не-dask, но это по-прежнему использует только один CPU на сервере. Так что это не помогло. На самом деле, это медленнее.
что я делаю не так? Я чего-то не хватает? Я все еще довольно новичок в даске, поэтому дайте мне знать, если я что-то упустил или если я должен делать что-то совсем другое.
кроме того, есть ли альтернативы dask для использования полной емкости сервера (т. е. всех процессоров) для того, что мне нужно сделать?
спасибо,
T
3 ответов
проблема здесь в dask.dataframe.to_csv
, что заставляет вас работать в одноядерном режиме.
Я рекомендую использовать dask.bag
чтобы сделать ваше чтение и манипуляции, а затем сбросить вниз к куче CSV-файлов параллельно. Сброс во многие CSV-файлы намного проще для coordiante, чем сброс в один CSV-файл.
import dask.bag as bag
import json
b = bag.from_filenames('input.json.gz').map(json.loads).map(manipulate).concat()
b.map(lambda t: ','.join(map(str, t)).to_textfiles('out.*.csv').compute()
может также возникнуть проблема с попыткой прочитать один файл GZIP параллельно, но выше должно начать работу.
Кажется, что сумки параллельны только количеству разделов, которые у них есть.
для меня, работающей
mybag=bag.from_filenames(filename, chunkbytes=1e7)
mybag.npartitions
доходность
1746
что решило проблему и сделало обработку полностью распараллеливаемой.
Если вы предоставляете имя файла на основе glob, например MyFiles-*.csv
в ДАСК dataframe.to_csv()
вы должны иметь возможность выводить фрейм данных на диск.
Он создаст несколько файлов вместо 1 большого csv-файла. См. этот поток для mre https://groups.google.com/a/continuum.io/forum/#!searchin/blaze-dev/to_csv/blaze-dev/NCQfCoOWEcI/S7fwuCfeCgAJ
MyFiles-0001.csv
MyFiles-0002.csv
....