Почему важно оптимизировать формат данных |
||||||||||||||||||||||||||||||||||
МЕНЮ Главная страница Поиск Регистрация на сайте Помощь проекту Архив новостей ТЕМЫ Новости ИИ Голосовой помощник Разработка ИИГородские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Искусственный интеллект Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Нейронные сети начинающим Психология ИИ Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Творчество ИИ Техническое зрение Чат-боты Авторизация |
2024-10-17 12:48 Если вам нужно повысить скорость вашей программы, то первым делом логично будет вспомнить курс по структурам данных и оптимизировать алгоритмическую сложность. Сравнение хранилищ данных AoS и SoA Современное оборудование, и, в частности CPU, спроектировано так, чтобы обрабатывать данные определённым образом. Расположение данных в памяти влияет на то, насколько эффективно программа сможет использовать кэш CPU, как часто она сталкивается с промахами кэша и насколько оптимально она сможет задействовать векторные команды (SIMD). Даже при использовании оптимальных алгоритмов выбор неподходящего формата данных может приводить к частым перезагрузкам кэша, простаивающим конвейерам и чрезвычайно большому объёму передач содержимого памяти; всё это снижает производительность. Чтобы понять, как разные форматы данных влияют на производительность, мы воспользуемся простой программой на C++ и проведём разные эксперименты. В процессе этих экспериментов мы проанализируем время исполнения программы с разными форматами данных, чтобы разобраться в преимуществах и недостатках каждого формата. Ниже показан код примера реализации AoS и SoA.
В формате AoS мы определяем struct для сотрудника, содержащую все необходимые поля: id, имя и зарплату. Затем мы создаём вектор (то есть массив с изменяемым размером) этой структуры, чтобы хранить данные множества сотрудников. В случае SoA мы разделяем каждое поле данных сотрудников на отдельные векторы. Это значит, что у нас будет один массив для id, второй для имён и третий для зарплат. ? Производительность обновления данных Давайте исследуем свойства этих типов хранения. Сначала нам нужно понять типичный объектно-ориентированный способ доступа к данным. Приложения обычно вставляют, обновляют и удаляют объекты. В нашем примере мы создаём сотрудников при их найме, обновляем зарплату в процессе их работы в компании и удаляем их при увольнении.
В этом примере мы затрагиваем большую часть записи каждого сотрудника, так как получаем доступ и к имени, и к зарплате. Благодаря тому, что оба поля находятся в одной линии кэша, для обновления данных каждого сотрудника нам достаточно выполнить доступ только к одной линии кэша. ? Производительность чтения данных После изучения обоих форматов данных на типичном процессе вставки/обновления/удаления мы хотим исследовать чтение и анализ свойств всей коллекции. Чтобы понять влияние на производительность этого процесса при использовании разных форматов данных, мы выполним агрегирование суммарных затрат на персонал.
Хотя код выглядит очень похожим, производительность сильно различается. На моей машине код с SoA приблизительно втрое быстрее, чем код с AoS.
Кроме того, код с SoA может существенно выигрывать от автоматической векторизации в компиляторе. При уровне оптимизации O3 g++ генерирует для этого формата данных SIMD-код. В случае кода с AoS компилятор выполняет в цикле обход данных в массиве сотрудников, что можно увидеть в godbolt. Эта автоматическая векторизация даёт нам дополнительное повышение производительности в 1,5 раза, то есть суммарно SoA в четыре с лишним раза быстрее, чем AoS.
? Сжатие При оптимизации размера данных используется две распространённые методики: слабое и сильное сжатие. Сильное сжатие (например, LZ77 и код Хаффмана) минимизирует размер данных, не принимая дополнительных допущений о данных, но часто оказывается медленным и активно нагружает CPU, то есть мы получаем снижение размера ценой скорости. Методики слабого сжатия, например, кодирование длин серий (RLE), frame-of-reference или дельта-кодирование позволяет быстрым и эффективным образом снизить потребление памяти, не жертвуя при этом скоростью доступа. В отличие от сильного сжатия, многие методики слабого кодирования можно напрямую использовать для обработки сжатых данных без дополнительного извлечения, что ещё больше повышает скорость перемещения данных. Однако эффективность этих слабых методик сильно зависит от способа организации данных. Схемы слабого сжатия проявляют себя в полную силу, когда они могут обнаруживать паттерны или повторяющиеся значения. Примером такого паттерна может быть упорядоченная последовательность значений. При помощи формата SoA мы можем эффективно хранить данные с использованием дельта-кодирования или кодирования frame-of-reference. В целом, SoA лучше подходит для слабого сжатия, потому что схожие значения хранятся рядом друг с другом. Кроме того, SoA обеспечивает повышенную повторяемость в пределах каждого поля, что максимизирует коэффициент сжатия при таких схемах, как RLE. И наоборот: перемещающиеся поля в AoS ограничивают эффективность слабого сжатия. Вернёмся к нашему примеру и протестируем слабое сжатие с использованием frame-of-reference для десятичных последовательных значений. Кодирование frame-of-reference находит минимум значений и минимизирует количество байтов, требуемое для хранения разности с минимальным значением.
Как видно в приведённой ниже таблице, сжатие существенно уменьшает размер данных и повышает производительность. Наш способ сжатия позволяет обрабатывать данные напрямую, при этом требуя меньше перемещений данных. В целом, оптимизация формата хранения повышает скорость в семь раз и снижает потребление памяти и накопителя на 33%. Учтите, что мы измерили эти результаты при помощи общей реализации, показанной в Приложении.
? Оптимизация Out-Of-Memory Поняв, что использование SoA может существенно повысить производительность благодаря применению методик слабого сжатия, рассмотрим вопрос масштабирования этих концепций при работе с большими датасетами. Когда датасет становится слишком большим, чтобы уместиться в памяти или когда требуется эффективный доступ только к части данных, в дело вступают разбитые на блоки структуры массивов (chunked structure of arrays): мы разделяем данные на блоки одного размера и сохраняем их на диск. Для ускорения обработки мы вначале сохраняем минимальное и максимальное значение каждого блока. Перед обработкой блока мы можем проверить минимальное и максимальное значения и пропускать блоки, которые нам не нужны; например, если нас интересуют блоки с именами, начинающимися на A-M, то не нужно обрабатывать блоки с именами на Z. Так как каждый блок сжимается по отдельности, мы можем масштабировать систему до более крупных датасетов, не беспокоясь о деградации производительности сжатия, особенно при использовании слабых форматов наподобие кодирования frame-of-reference. Влияние на системы управления базами данных Очевидно, что все эти наблюдения крайне важны для создания быстрой и масштабируемой системы управления базами данных. Специалисты по базам данных называют AoS способом хранения row-major, а SoA — способом хранения column-major. Для большинства традиционных систем управления базами данных наиболее важна обработка транзакций (то есть множества обновлений, вставок и удалений), поэтому в них реализуется AoS, а в современных аналитических системах управления базами данных (то есть со множеством операций чтения данных и обработки чисел) обычно предпочитают SoA. Первоисточником разбитых на блоки SoA стал формат Partition Attributes Across (PAX). Сегодня дополнительное сжатие данных внутри формата PAX используется для чтения с медленных накопителей, например, с облачных хранилищ объектов (AWS S3 и прочих). Источник: habr.com Комментарии: |
|||||||||||||||||||||||||||||||||