Данная книга предлагает уникальные техники ускорения выполнения кода на Python с акцентом на большие данные. Вы узнаете, как оптимизировать работу со встроенными структурами данных за счет конкурентного выполнения, а также научитесь сокращать объем занимаемой данными памяти без ущерба для их точности. Ознакомившись с тщательно проработанными примерами, вы узнаете, как добиться большей производительности популярных библиотек, таких как NumPy и pandas, и как эффективно обрабатывать и хранить данные. В книге используется целостный подход к повышению эффективности решений, так что вы научитесь оптимизировать и масштабировать целые системы – начиная от кода и заканчивая архитектурой.
Издание предназначено для разработчиков Python, знакомых с основами языка и принципами конкурентных вычислений.
Author(s): Тиаго Антао
Edition: 1
Publisher: ДМК Пресс
Year: 2023
Language: Russian
Commentary: Publisher's PDF
Pages: 370
City: М.
Tags: Data Analysis; Data Structures; Python; Concurrency; Asynchronous Programming; Parallel Programming; MapReduce; Apache Parquet; Memory Management; Optimization; Profiling; High Performance; Laziness; NumPy; pandas; GPU Programming; Networking; Generators; Numba; Cython; High Performance Computing; Dask; Storage Management; Data Processing; Apache Arrow; Memory Hierarchy; Zarr; NumExpr; GuPy
Оглавление
Предисловие от издательства
Предисловие
Благодарности
О книге
Для кого эта книга
Организация книги
О сопроводительном коде
Программное и аппаратное обеспечение
Об авторе
О переводчике
Об изображении на обложке
Часть I. Фундаментальные подходы
1. Острая нехватка производительности при обработке данных
1.1. Насколько велик всемирный потоп данных?
1.2. Современные вычислительные архитектуры и высокопроизводительные вычисления
1.2.1. Изменения в архитектуре компьютеров
1.2.2. Изменения в архитектуре сети
1.2.3. Облако
1.3. Работа с ограничениями языка Python
1.3.1. Глобальная блокировка интерпретатора
1.4. Возможные решения
Заключение
2. Извлечение максимума возможного из встроенных средств Python
2.1. Профилирование приложений с операциями ввода-вывода и вычислениями
2.1.1. Загрузка данных и поиск минимальной температуры
2.1.2. Встроенный в Python модуль профилирования
2.1.3. Использование локального кеша для снижения сетевой нагрузки
2.2. Профилирование кода для обнаружения проблем с производительностью
2.2.1. Визуализация профилировочной информации
Знакомство с интерфейсом SnakeViz
2.2.2. Профилирование с детализацией до строк
2.2.3. Профилирование кода: выводы
Другие инструменты профилирования
2.3. Оптимизация работы базовых структур данных Python: списки, множества и словари
2.3.1. Быстродействие поиска в списке
2.3.2. Поиск с использованием множеств
2.3.3. Вычислительная сложность списков, множеств и словарей в Python
2.4. В поисках избыточного выделения памяти
2.4.1. По минному полю выделения памяти в Python
Кеширование и повторное использование объектов в Python
2.4.2. Выделение памяти для альтернативных представлений
Внутреннее представление строк и чисел
2.4.3. Использование массивов в качестве компактной альтернативы спискам
Выделение памяти для списков
2.4.4. Систематизирование новых знаний: оценка объема памяти, занимаемой объектом
2.4.5. Оценка занимаемой объектами памяти в Python: выводы
2.5. Использование ленивых вычислений и генераторов для работы с большими данными
2.5.1. Использование генераторов вместо обычных функций
Заключение
3. Конкурентность, параллелизм и асинхронная обработка
3.1. Написание шаблона асинхронного сервера
3.1.1. Разработка шаблона для взаимодействия с клиентами
3.1.2. Программирование с сопрограммами
3.1.3. Передача сложных данных от простого синхронного клиента
3.1.4. Альтернативные способы передачи данных между процессами
3.1.5. Асинхронное программирование: выводы
3.2. Реализация базового движка MapReduce
3.2.1. Описание фреймворка MapReduce
3.2.2. Разработка простейшего тестового сценария
3.2.3. Первая реализация фреймворка MapReduce
3.3. Реализация конкурентной версии фреймворка MapReduce
3.3.1. Использование модуля concurrent.futures для реализации многопоточного сервера
3.3.2. Асинхронное выполнение с использованием будущих объектов
3.3.3. Глобальная блокировка интерпретатора и многопоточность
PyPy
3.4. Реализация фреймворка MapReduce с использованием библиотеки multiprocessing
3.4.1. Решение на основе модуля concurrent.futures
Проблемы с передачей кода и данных при использовании модуля multiprocessing
3.4.2. Решение на основе модуля multiprocessing
CPU_count против sched_getaffinity при определении размера пула
3.4.3. Отслеживание прогресса при использовании модуля multiprocessing
Недостаточное и избыточное выделение ресурсов процессора
3.4.4. Передача данных порциями
Разделяемая память
3.5. Собираем все воедино: асинхронный многопоточный и многопроцессный сервер MapReduce
3.5.1. Архитектура высокопроизводительного решения
Блокировка и низкоуровневая синхронизация с многопоточностью и многопроцессностью
3.5.2. Создание надежной версии сервера
Управление ошибками и исключениями в многопоточном и многопроцессном коде
Заключение
4. Высокопроизводительный NumPy
4.1. Библиотека NumPy с точки зрения производительности
4.1.1. Копии и представления существующих массивов
4.1.2. Внутреннее устройство представлений NumPy
4.1.3. Эффективное использование представлений
4.2. Программирование на основе массивов
4.2.1. Отправная точка
4.2.2. Транслирование в NumPy
4.2.3. Применение приемов программирования на основе массивов
4.2.4. Векторизуем сознание
4.3. Оптимизация внутренней архитектуры NumPy
4.3.1. Обзор зависимостей в NumPy
4.3.2. Настройка NumPy в дистрибутиве Python
4.3.3. Потоки в NumPy
Заключение
Часть II. Аппаратное обеспечение
5. Реализация критически важного кода с помощью Cython
5.1. Обзор техник для эффективной реализации кода
5.2. Беглый обзор расширения Cython
5.2.1. Наивная реализация в Cython
Связка с кодом на Cython
Cython как компилируемый язык программирования
5.2.2. Использование аннотаций типов в Cython для повышения производительности
5.2.3. Как аннотации типов влияют на производительность
5.2.4. Типизация возвращаемых из функции значений
5.3. Профилирование кода на Cython
5.3.1. Использование встроенной инфраструктуры профилирования Python
5.3.2. Использование line_profiler
5.4. Оптимизация доступа к массивам в Cython с помощью memoryview
5.4.1. Использование представлений памяти
5.4.2. Избавление от всех взаимодействий с Python
5.5. Написание обобщенных универсальных функций NumPy на Cython
5.6. Продвинутая работа с массивами в Cython
5.6.1. Обход ограничений GIL по запуску нескольких потоков одновременно
5.6.2. Базовый анализ производительности
5.6.3. Космические войны в Quadlife
Значение вычислительной сложности алгоритмов
5.7. Параллелизм с Cython
Заключение
6. Иерархия памяти, хранение данных и работа с сетью
6.1. Как современная архитектура аппаратных средств влияет на эффективность кода Python
6.1.1. Неожиданное влияние современной архитектуры на производительность
6.1.2. Влияние кеша процессора на эффективность алгоритма
6.1.3. Современные устройства постоянного хранения
6.2. Эффективное хранение данных при помощи Blosc
6.2.1. Сжимаем данные, экономим время
6.2.2. Операции чтения (буферы памяти)
6.2.3. Влияние алгоритма сжатия на эффективность хранения
6.2.4. Использование сведений о представлении данных для повышения эффективности сжатия
6.3. Ускорение NumPy с помощью NumExpr
6.3.1. Быстрая обработка выражений
6.3.2. Влияние архитектуры аппаратных средств на результаты
6.3.3. Когда не стоит использовать библиотеку NumExpr
6.4. Производительность при использовании локальных сетей
6.4.1. Причины неэффективности вызовов REST
6.4.2. Наивный клиент на основе UDP и msgpack
6.4.3. Сервер на основе UDP
6.4.4. Безопасность на клиенте с помощью тайм-аутов
6.4.5. Прочие предпосылки для оптимизации сетевых вычислений
Заключение
Часть III. Приложения и библиотеки для современной обработки данных
7. Высокопроизводительный pandas и Apache Arrow
7.1. Оптимизация памяти и времени при загрузке данных
7.1.1. Сжатые и несжатые данные
7.1.2. Определение типов данных колонок
7.1.3. Эффект изменения точности типа данных
7.1.4. Кодирование и снижение объема данных
Кажущаяся безопасность инструкции inplace=True
7.2. Техники для повышения скорости анализа данных
7.2.1. Использование индексирования для ускорения доступа к данным
7.2.2. Техники перемещения по строкам
7.3. Взаимодействие pandas с NumPy, Cython и NumExpr
7.3.1. Явное использование NumPy
7.3.2. Pandas поверх NumExpr
7.3.3. Cython и pandas
7.4. Чтение данных в pandas с помощью Arrow
7.4.1. Взаимодействие между pandas и Apache Arrow
7.4.2. Чтение из файла CSV
7.4.3. Анализ данных в Arrow
7.5. Использование механизма взаимодействий в Arrow для делегирования задач более эффективным языкам и системам
7.5.1. Предпосылки архитектуры межъязыкового взаимодействия Arrow
7.5.2. Операции с нулевым копированием с использованием сервера Plasma от Arrow
Заключение
8. Хранение больших данных
8.1. Универсальный интерфейс для доступа к файлам: fsspec
8.1.1. Использование fsspec для поиска файлов в репозитории GitHub
Ограничения интерфейса fsspec
8.1.2. Использование fsspec для поиска zip-файлов
8.1.3. Доступ к файлам с использованием библиотеки fsspec
8.1.4. Использование цепочки URL для обращения к разным файловым системам
8.1.5. Замена реализации файловой системы
8.1.6. Взаимодействие с PyArrow
8.2. Parquet: эффективный формат хранения колоночных данных
8.2.1. Исследование метаданных Parquet
8.2.2. Кодирование колонок в Parquet
8.2.3. Секционирование наборов данных
8.3. Работа с наборами данных, не помещающимися в памяти, по-старому
8.3.1. Отображение в памяти с помощью NumPy
Копирование при записи в NumPy
8.3.2. Порционирование данных при чтении и записи в датафрейм
8.4. Использование Zarr для хранения больших массивов
8.4.1. Знакомство с внутренней структурой формата Zarr
8.4.2. Хранение массивов в Zarr
8.4.3. Создание нового массива
Основные правила по определению размера порции данных
8.4.4. Параллельное чтение и запись массивов в Zarr
Заключение
Часть IV. Продвинутые возможности
9. Анализ данных с использованием графического процессора
9.1. Предпосылки для использования вычислительных мощностей GPU
9.1.1. Преимущества использования графического процессора
9.1.2. Связь между центральным и графическим процессорами
Производители GPU и совместимость программного обеспечения
9.1.3. Внутренняя архитектура графического процессора
9.1.4. Архитектура программного обеспечения
9.2. Использование компилятора Numba для генерации кода под GPU
9.2.1. Программное обеспечение для работы с GPU в Python
9.2.2. Основы программирования для GPU с помощью Numba
9.2.3. Создание генератора Мандельброта с помощью графического процессора
9.2.4. Создание генератора Мандельброта с помощью NumPy
9.3. Анализ производительности кода для GPU: приложение с использованием CuPy
9.3.1. Библиотеки для анализа данных на базе GPU
9.3.2. Использование CuPy – версии библиотеки NumPy для GPU
9.3.3. Базовое взаимодействие с CuPy
9.3.4. Создание генератора Мандельброта с помощью Numba
9.3.5. Создание генератора Мандельброта с помощью CUDA C
9.3.6. Средства профилирования кода для GPU
Заключение
10. Анализ больших данных с использованием библиотеки Dask
10.1. Знакомство с моделью выполнения Dask
10.1.1. Шаблон pandas для сравнения
10.1.2. Решение на основе датафреймов Dask
10.2. Вычислительная стоимость операций Dask
10.2.1. Секционирование данных для обработки
10.2.2. Сохранение промежуточных вычислений
10.2.3. Реализации алгоритмов при работе с распределенными датафреймами
10.2.4. Рассекционирование данных
10.2.5. Хранение распределенных датафреймов
10.3. Использование распределенного планировщика Dask
10.3.1. Архитектура dask.distributed
10.3.2. Запуск кода с помощью dask.distributed
10.3.3. Работа с наборами данных, превышающими по объему доступную память
Заключение
Приложение А. Настройка окружения
А.1. Установка Anaconda Python
Обновление окружений conda
А.2. Установка дистрибутива Python
А.3. Использование Docker
А.4. Вопросы, касающиеся аппаратного обеспечения
Приложение Б. Использование Numba для создания эффективного низкоуровневого кода
Б.1. Создание оптимизированного кода с помощью Numba
Б.2. Написание параллельных функций в Numba
Б.3. Написание кода с использованием NumPy в Numba
Предметный указатель