сумка 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 
....