Низкая производительность с Python Dask bag?

#python #performance #dask

#python #Производительность #dask

Вопрос:

Я пробую некоторые тесты dask.bag, чтобы подготовиться к большой работе по обработке текста над миллионами текстовых файлов. Прямо сейчас, на моих тестовых наборах из десятков или сотен тысяч текстовых файлов, я вижу, что dask работает примерно в 5-6 раз медленнее, чем обычная однопоточная функция обработки текста.

Может кто-нибудь объяснить, где я увижу преимущества скорости запуска dask над большим количеством текстовых файлов? Сколько файлов мне придется обработать, прежде чем он начнет ускоряться? 150 000 небольших текстовых файлов просто слишком мало? Какие параметры производительности я должен настроить, чтобы ускорить работу dask при обработке файлов? Чем может быть вызвано 5-кратное снижение производительности по сравнению с прямой однопоточной обработкой текста?

Вот пример кода, который я использую для тестирования dask. Это выполняется на основе тестового набора данных от Reuters, расположенного по адресу:

http://www.daviddlewis.com/resources/testcollections/reuters21578/

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

 import dask.bag as db
from collections import Counter
import string
import glob
import datetime

my_files = "./reuters/*.ascii"

def single_threaded_text_processor():
    c = Counter()
    for my_file in glob.glob(my_files):
        with open(my_file, "r") as f:
            d = f.read()
            c.update(d.split())
    return(c)

start = datetime.datetime.now()
print(single_threaded_text_processor().most_common(5))
print(str(datetime.datetime.now() - start))

start = datetime.datetime.now()
b = db.read_text(my_files)
wordcount = b.str.split().concat().frequencies().topk(5, lambda x: x[1])
print(str([w for w in wordcount]))
print(str(datetime.datetime.now() - start))
  

Вот мои результаты:

 [('the', 119848), ('of', 72357), ('to', 68642), ('and', 53439), ('in', 49990)]
0:00:02.958721
[(u'the', 119848), (u'of', 72357), (u'to', 68642), (u'and', 53439), (u'in', 49990)]
0:00:17.877077
  

Ответ №1:

Dask требует примерно 1 мс накладных расходов на задачу. По умолчанию dask.bag.read_text функция создает одну задачу для каждого имени файла. Я подозреваю, что вы просто перегружены накладными расходами.

Решение здесь, вероятно, заключается в обработке нескольких файлов в одной задаче. Функция read_text не дает вам никаких возможностей для этого, но вы можете переключиться на dask.delayed, который обеспечивает немного большую гибкость, а затем преобразовать в dask.bag позже, если это предпочтительнее.