Плазменный кэш, что это такое

Обновлено: 04.07.2024

Первоначально это сообщение было опубликовано в блоге Apache Arrow.

В этой записи блога рассказывается о Plasma, хранилище объектов в памяти, которое разрабатывается как часть Apache Arrow. Plasma хранит неизменяемые объекты в разделяемой памяти, чтобы многие клиенты могли эффективно обращаться к ним через границы процессов. В свете тенденции к увеличению размера многоядерных компьютеров Plasma обеспечивает критическую оптимизацию производительности в режиме больших данных.

Plasma изначально разрабатывалась как часть Ray, но недавно была перенесена в Apache Arrow в надежде, что она будет широко полезна.

Одна из целей Apache Arrow – служить общим уровнем данных, обеспечивающим обмен данными без копирования между несколькими платформами. Ключевым компонентом этого видения является использование управления памятью вне кучи (через Plasma) для хранения и совместного использования сериализованных объектов Arrow между приложениями.

Дорогая сериализация и десериализация, а также копирование данных являются частыми узкими местами производительности в распределенных вычислениях. Например, среда выполнения на основе Python, которая хочет распределить вычисления между несколькими «рабочими» процессами Python, а затем агрегировать результаты в одном «драйверном» процессе, может выбрать сериализацию данных с помощью встроенной библиотеки pickle. Если предположить, что на каждое ядро ​​приходится один процесс Python, каждый рабочий процесс должен будет копировать и десериализовать данные, что приводит к чрезмерному использованию памяти. Затем процессу драйвера придется десериализовать результаты каждого из рабочих процессов, что приведет к возникновению узкого места.

При использовании Plasma плюс Arrow обрабатываемые данные будут помещены в хранилище Plasma один раз, и все рабочие процессы будут считывать данные без их копирования или десериализации (рабочие процессы будут отображать соответствующую область памяти в свой собственный адрес). пространства). Затем рабочие помещали результаты своих вычислений обратно в хранилище Plasma, которое драйвер затем мог считывать и агрегировать без копирования или десериализации данных.

API Plasma:

Ниже мы иллюстрируем подмножество API. API C++ более подробно описан здесь, а API Python — здесь.

Идентификаторы объектов: каждый объект связан со строкой байтов.

Создание объекта. Объекты сохраняются в Plasma в два этапа. Во-первых, хранилище объектов создает объект, выделяя для него буфер. В этот момент клиент может записать в буфер и создать объект в выделенном буфере. Когда клиент завершает работу, клиент запечатывает буфер, делая объект неизменным и делая его доступным для других клиентов Plasma.

Получение объекта: после того, как объект был запечатан, любой клиент, знающий идентификатор объекта, может получить объект.

Если объект еще не запечатан, вызов client.get будет заблокирован до тех пор, пока объект не будет запечатан.

Приложение для сортировки

Чтобы проиллюстрировать преимущества Plasma, мы демонстрируем 11-кратное ускорение (на машине с 20 физическими ядрами) для сортировки большого кадра данных pandas (один миллиард записей). Базовым уровнем является встроенная функция сортировки pandas, которая сортирует DataFrame за 477 секунд. Чтобы использовать несколько ядер, мы реализуем следующую стандартную схему распределенной сортировки.

  • Мы предполагаем, что данные распределены по тысячам фреймов данных pandas и каждый из них уже находится в хранилище Plasma.
  • Мы делаем подвыборку данных, сортируем данные подвыборки и используем результат для определения L непересекающихся сегментов.
  • Для каждого из K разделов данных и каждого из L сегментов мы находим подмножество раздела данных, которое попадает в сегмент, и сортируем это подмножество.
  • Для каждого из L сегментов мы собираем все K отсортированных подмножеств, попадающих в этот сегмент.
  • Для каждого из L сегментов мы объединяем соответствующие K отсортированных подмножеств.
  • Мы превращаем каждое ведро в кадр данных pandas и помещаем его в хранилище Plasma.

Используя эту схему, мы можем отсортировать DataFrame (данные начинаются и заканчиваются в хранилище Plasma) за 44 секунды, что дает 11-кратное ускорение по сравнению с базовым уровнем.

Дизайн

Магазин Plasma работает как отдельный процесс. Он написан на C++ и разработан как однопоточный цикл событий на основе библиотеки циклов событий Redis. Клиентскую библиотеку плазмы можно связать с приложениями. Клиенты взаимодействуют с магазином Plasma с помощью сообщений, сериализованных с помощью Google Flatbuffers.

Призыв к участию

Plasma находится в стадии разработки, и API в настоящее время нестабилен. Сегодня Plasma в основном используется в Ray в качестве кэша в памяти для сериализованных объектов Arrow. Мы ищем более широкий набор вариантов использования, чтобы помочь улучшить API Plasma. Кроме того, мы ищем вклад в различных областях, включая повышение производительности и создание привязок к другим языкам. Сообщите нам, если вы заинтересованы в участии в проекте.

Ray: быстрая и простая платформа для распределенных приложений

  • Ray: быстрая и простая платформа для распределенных приложений

Ray — это быстрая и простая платформа для создания и запуска распределенных приложений.

На данный момент Plasma поддерживается только для Linux и macOS.

API Plasma¶

Запуск магазина Plasma¶

Вы можете запустить магазин Plasma, введя команду терминала, аналогичную следующей:

Флаг -m указывает размер хранилища в байтах, а флаг -s указывает сокет, который будет прослушиваться хранилищем. Таким образом, приведенная выше команда позволяет хранилищу Plasma использовать до 1 ГБ памяти и устанавливает сокет в /tmp/plasma .

Оставить текущее окно терминала открытым, пока магазин Plasma должен продолжать работать. Сообщения, касающиеся, например, отключения клиентов, могут время от времени выводиться на экран. Чтобы прекратить работу магазина Plasma, вы можете нажать Ctrl-C в терминале.

Создание клиента Plasma¶

Чтобы запустить клиент Plasma из Python, вызовите Plasma.connect, используя то же имя сокета:

Если при выполнении приведенного выше кода Python возникает следующая ошибка, это означает, что либо указан неверный сокет, либо хранилище ./plasma_store в данный момент не запущено. Проверьте, работает ли магазин Plasma.

Идентификаторы объектов¶

Каждый объект в магазине Plasma должен быть связан с уникальным идентификатором. Затем идентификатор объекта служит ключом, который любой клиент может использовать для извлечения этого объекта из хранилища Plasma. Вы можете сформировать объект ObjectID из строки байтов длиной 20.

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

Помещение и получение объектов Python¶

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

Вот как вы можете поместить и получить объект Python:

Это работает со всеми объектами Python, поддерживаемыми сериализацией объектов Arrow Python.

Вы также можете получить несколько объектов одновременно (что может быть более эффективным, поскольку позволяет избежать двусторонних обращений IPC):

Кроме того, можно задать тайм-аут для вызова get. Если объект недоступен в течение времени ожидания, будет возвращен специальный объект pyarrow.ObjectNotAvailable.

Создание буфера объектов¶

Объекты создаются в Plasma в два этапа. Во-первых, они создаются, что выделяет буфер для объекта. В этот момент клиент может записать в буфер и построить объект в выделенном буфере.

Чтобы создать объект для Plasma, необходимо создать идентификатор объекта, а также указать максимальный размер объекта в байтах.

По завершении работы клиент запечатывает буфер, делая объект неизменяемым и делая его доступным для других клиентов Plasma.

Получение буфера объектов¶

После того, как объект запечатан, любой клиент, знающий идентификатор объекта, может получить буфер объекта.

Если объект еще не запечатан, то вызов client.get_buffers будет заблокирован до тех пор, пока объект не будет запечатан клиентом, создающим объект. Используя аргумент timeout_ms для получения, вы можете указать для этого таймаут (в миллисекундах). По истечении тайм-аута интерпретатор возвращает управление.

Список объектов в магазине¶

Объекты в магазине могут быть перечислены следующим образом (обратите внимание, что эта функция в настоящее время является экспериментальной, и конкретное представление информации об объекте может измениться в будущем):

Использование Arrow и Pandas с Plasma¶

Сохранение объектов стрелки в плазме¶

Чтобы сохранить объект Arrow в Plasma, мы должны сначала создать объект, а затем запечатать его. Однако объекты Arrow, такие как тензоры, могут быть более сложными для записи, чем простые двоичные данные.

Чтобы создать объект в Plasma, вам по-прежнему нужен ObjectID и размер для передачи. Чтобы узнать размер вашего объекта Arrow, вы можете использовать API pyarrow, например pyarrow.ipc.get_tensor_size .

Чтобы записать объект Arrow Tensor в буфер, вы можете использовать Plasma для преобразования буфера memoryview в объект pyarrow.FixedSizeBufferWriter. Формат pyarrow.FixedSizeBufferWriter подходит для pyarrow.ipc.write_tensor Arrow:

Чтобы завершить сохранение объекта Arrow в Plasma, вызовите команду seal :

Получение объектов-стрелок из Plasma¶

Чтобы прочитать объект, сначала извлеките его как PlasmaBuffer, используя его идентификатор объекта.

Чтобы преобразовать PlasmaBuffer обратно в Arrow Tensor , сначала создайте из него объект pyarrow BufferReader. Затем вы можете передать BufferReader в pyarrow.ipc.read_tensor для восстановления объекта Arrow Tensor:

Наконец, вы можете использовать pyarrow.ipc.read_tensor для преобразования объекта Arrow обратно в пустые данные:

Хранение фреймов данных Pandas в Plasma¶

Сохранение фрейма данных Pandas по-прежнему следует процессу создания, а затем печати сохранения объекта в хранилище Plasma, однако нельзя напрямую записать фрейм данных в Plasma только с помощью Pandas. Plasma также должен знать размер DataFrame для выделения буфера.

Дополнительную информацию об использовании Arrow с Pandas см. в разделе Интеграция Pandas.

Вы можете создать эквивалент pyarrow для Pandas DataFrame, используя pyarrow.from_pandas для преобразования его в RecordBatch .

Для создания объекта Plasma требуется ObjectID и размер данных. Теперь, когда мы преобразовали Pandas DataFrame в PyArrow RecordBatch, используйте MockOutputStream для определения размера объекта Plasma.

Теперь DataFrame можно записать в буфер следующим образом.

Наконец, запечатайте готовый объект для использования всеми клиентами:

Получение кадров данных Pandas из Plasma¶

Поскольку мы храним Pandas DataFrame как объект PyArrow RecordBatch, чтобы вернуть объект из хранилища Plasma, мы выполняем шаги, аналогичные тем, которые указаны в разделе Получение объектов Arrow из Plasma.

Сначала нам нужно преобразовать PlasmaBuffer, возвращенный из client.get_buffers, в объект Arrow BufferReader.

Из BufferReader мы можем создать определенный RecordBatchStreamReader в Arrow для восстановления сохраненного объекта PyArrow RecordBatch.

Последний шаг — преобразовать объект PyArrow RecordBatch обратно в исходную структуру Pandas DataFrame.

Использование Plasma с огромными страницами¶

В Linux можно использовать магазин Plasma с огромными страницами для увеличения пропускной способности. Сначала вам нужно создать файловую систему и активировать огромные страницы с помощью

Обратите внимание, что корневой доступ нужен только для создания файловой системы, а не для запуска хранилища объектов. Затем вы можете запустить хранилище Plasma с флагом -d для точки монтирования файловой системы огромных страниц и флагом -h, указывающим, что активированы огромные страницы:

Читайте также: