Отклик с низкой задержкой при использовании Ray на большом (isch) наборе данных

TL;DR

Какой самый быстрый способ получить почти нулевое время загрузки для набора данных pandas, который у меня есть в памяти, с помощью ray?

Фон

Я делаю приложение, которое использует полу-большие наборы данных (фреймы данных pandas от 100 МБ до 700 МБ) и пытаюсь сократить время каждого запроса. Для многих моих запросов загрузка данных составляет большую часть времени ответа. Наборы данных - это оптимизированные паркетные файлы (категории вместо строк и т. Д.), Которые считывают только нужные столбцы.

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

Типичный запрос:

  • Прочтите и проанализируйте контракт (~ 50-100 мс)
  • Загрузите набор данных (10-20 столбцов) (400-1200 мс)
  • Выполнить операции pandas (~ 50-100 мс)
  • Сериализируйте результаты (50-100 мс)

Теперь я пытаюсь ускорить это (уменьшить или удалить шаг загрузки набора данных).

Вещи, которые я пробовал:

  1. Используйте новую фильтрацию на уровне строк в наборе данных Arrow, чтобы читать только те строки, которые мне нужны. Вероятно, это будет хороший способ в будущем, но на данный момент новый API-интерфейс Arrow Dataset, на который полагается, значительно медленнее, чем чтение полного файла с использованием устаревшего загрузчика.
  2. Оптимизируйте, черт возьми, наборы данных. Это хорошо работает до такой степени, что где вещи находятся в категориях, типы данных оптимизированы.
  3. Сохраните фрейм данных в Ray. Использование ray.put и ray.get. Однако на самом деле это не улучшает ситуацию, поскольку отнимающая много времени часть - десериализация фрейма данных.
  4. Поместите набор данных в ramfs. На самом деле это не улучшает ситуацию, поскольку отнимающая много времени часть - десериализация фрейма данных.
  5. Сохраните объект в другом хранилище Plasma (за пределами ray.put), но очевидно, что скорость такая же (хотя я мог бы получить некоторые другие преимущества)

Наборы данных представляют собой паркетные файлы, что уже довольно быстро для сериализации / десериализации. Обычно я выбираю около 10-20 столбцов (из 1000) и около 30-60% строк.

Есть хорошие идеи, как ускорить загрузку? Мне не удалось найти никаких операций с почти нулевым копированием для фреймов данных pandas (то есть без штрафа за сериализацию).

Вещи, о которых я думаю:

  1. Размещение набора данных в акторе и использование одного актера на поток. Это, вероятно, дало бы актеру прямой доступ к фрейму данных без какой-либо сериализации, но потребовало бы от меня много обработки:

    • Making sure I have an actor per thread
    • Распределить запросы по потокам
    • "Переработайте" актеров при обновлении набора данных.

С уважением, Никлас


person Niklas B    schedule 10.06.2020    source источник


Ответы (2)


Ray действительно выполняет десериализацию с нулевым копированием для фрейма данных pandas. Время десериализации в основном фиксировано. Вот несколько тестов

Performing a `ray.get(object_id)` that contains a dataframe

0.8Mb: 
474 µs ± 23.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

80Mb:
507 µs ± 5.16 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

480Mb:
520 µs ± 3.05 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Я с радостью отвечу на дополнительные вопросы в Slack сообщества Ray

person Simon Mo    schedule 10.06.2020

Поговорив с Саймоном о Slack, мы нашли виновника:

simon-mo: ага, да, объекты / строки не являются нулевой копией. категориальная или фиксированная длина строки работает. для фиксированной длины вы можете сначала попробовать преобразовать их в np.array

Эксперименты с этим (категориальные значения, строки фиксированной длины и т. Д.) Позволяют мне получить не совсем нулевую копию, но, по крайней мере, довольно низкую задержку (~ 300 мс или меньше) при использовании Ray Objects или Plasma store.

person Niklas B    schedule 17.06.2020