
- •Об авторе
- •О группе редакторов
- •Предисловие
- •Введение
- •Как использовать эту книгу
- •Загрузка исходного кода CPython
- •Что в исходном коде?
- •Настройка среды разработки
- •IDE или редактор?
- •Настройка Visual Studio
- •Настройка Visual Studio Code
- •Настройка Vim
- •Выводы
- •Компиляция CPython
- •Компиляция CPython на macOS
- •Компиляция CPython на Linux
- •Установка специализированной версии
- •Знакомство с Make
- •Make-цели CPython
- •Компиляция CPython на Windows
- •Профильная оптимизация
- •Выводы
- •Грамматика и язык Python
- •Спецификация языка Python
- •Генератор парсеров
- •Повторное генерирование грамматики
- •Выводы
- •Конфигурация и ввод
- •Конфигурация состояния
- •Структура данных конфигурации среды выполнения
- •Конфигурация сборки
- •Сборка модуля из входных данных
- •Выводы
- •Генерирование конкретного синтаксического дерева
- •Парсер/токенизатор CPython
- •Абстрактные синтаксические деревья
- •Важные термины
- •Пример: добавление оператора «почти равно»
- •Выводы
- •Компилятор
- •Исходные файлы
- •Важные термины
- •Создание экземпляра компилятора
- •Флаги будущей функциональности и флаги компилятора
- •Таблицы символических имен
- •Основная компиляция
- •Ассемблер
- •Создание объекта кода
- •Использование Instaviz для вывода объекта кода
- •Пример: реализация оператора «почти равно»
- •Выводы
- •Цикл вычисления
- •Исходные файлы
- •Важные термины
- •Построение состояния потока
- •Построение объектов кадров
- •Выполнение кадра
- •Стек значений
- •Пример: добавление элемента в список
- •Выводы
- •Управление памятью
- •Выделение памяти в C
- •Проектирование системы управления памятью Python
- •Аллокаторы памяти CPython
- •Область выделения объектной памяти и PyMem
- •Область выделения сырой памяти
- •Нестандартные области выделения памяти
- •Санитайзеры выделенной памяти
- •Арена памяти PyArena
- •Подсчет ссылок
- •Сборка мусора
- •Выводы
- •Параллелизм и конкурентность
- •Модели параллелизма и конкурентности
- •Структура процесса
- •Многопроцессорный параллелизм
- •Многопоточность
- •Асинхронное программирование
- •Генераторы
- •Сопрограммы
- •Асинхронные генераторы
- •Субинтерпретаторы
- •Выводы
- •Объекты и типы
- •Примеры этой главы
- •Встроенные типы
- •Типы объектов
- •Тип type
- •Типы bool и long
- •Тип строки Юникода
- •Словари
- •Выводы
- •Стандартная библиотека
- •Модули Python
- •Модули Python и C
- •Набор тестов
- •Запуск набора тестов в Windows
- •Запуск набора тестов в Linux или macOS
- •Флаги тестирования
- •Запуск конкретных тестов
- •Модули тестирования
- •Вспомогательные средства тестирования
- •Выводы
- •Отладка
- •Обработчик сбоев
- •Компиляция поддержки отладки
- •LLDB для macOS
- •Отладчик Visual Studio
- •Отладчик CLion
- •Выводы
- •Бенчмаркинг, профилирование и трассировка
- •Использование timeit для микробенчмарка
- •Использование набора тестов производительности Python
- •Профилирование кода Python с использованием cProfile
- •Выводы
- •Что дальше?
- •Создание расширений C для CPython
- •Улучшение приложений Python
- •Участие в проекте CPython
- •Дальнейшее обучение
- •Препроцессор C
- •Базовый синтаксис C
- •Выводы
- •Благодарности
Параллелизм и конкурентность
Первые компьютеры проектировались с расчетом на то, что в определенный момент времени они будут делать что-то одно. Значительная часть их работы была связана с вычислительной математикой. Но с течением времени возникла необходимость в обработке ввода, получаемого из самых разнообразных источников — вплоть до дальних галактик.
Как следствие, компьютерным программам приходилось проводить много времени, простаивая в ожидании ответа — от шины, устройства ввода, ячейки памяти, вычислений, API или удаленного источника.
Достижением в области вычислений стал отход от однопользовательских терминалов к многозадачным операционным системам. Приложения должны были работать в фоновом режиме — прослушивать сетевые порты, реагировать на данные сети и обрабатывать ввод (например, от мыши).
Многозадачность стала востребованной задолго до появления современных многоядерных процессоров, так что операционные системы уже давно умеют разделять ресурсы между несколькими процессами.
В любой операционной системе центральное место занимает реестр запущенных процессов. У каждого процесса есть владелец, и он может запрашивать ресурсы, например память или процессорное время. В предыдущей главе рассматривалось выделение памяти.
Процессы запрашивают процессорное время в форме выполняемых операций. Операционная система управляет тем, какой процесс использует ЦП. Для этого она выделяет процессорное время и планирует процессы с учетом приоритетов:
Книги для программистов: https://t.me/booksforits

204 Параллелизм и конкурентность
A
B
|
|
|
Даже одному процессу может понадобиться выполнять несколько операций одновременно. Например, если вы работаете в текстовом редакторе, он должен проверять орфографию в процессе ввода. Современные приложения решают эту проблему одновременным выполнением сразу нескольких потоков и обработкой своих ресурсов.
Конкурентность — превосходное решение для реализации многозадачности, но возможности процессоров конечны. Некоторые высокопроизводительные компьютеры оснащаются несколькими процессорами или ядрами для распределения задач. Операционные системы предоставляют механизм планирования процессов по нескольким ЦП:
A 0
A 1
|
|
|
Книги для программистов: https://t.me/booksforits

Структура процесса 205
Итак, компьютеры используют параллелизм и конкурентность для решения проблемы многозадачного выполнения:
zz Параллелизм требует нескольких вычислительных устройств. Вычислительными устройствами могут быть процессоры или ядра.
zz Конкурентность требует механизма планирования задач, чтобы простаивающие задачи не блокировали ресурсы.
Многие компоненты архитектуры CPython абстрагируют сложность операционных систем, чтобы предоставить простой API для разработчиков. Подход CPython к параллелизму и конкурентности не является исключением.
МОДЕЛИ ПАРАЛЛЕЛИЗМА И КОНКУРЕНТНОСТИ
CPython предлагает множество подходов к параллелизму и конкурентности. Выбор зависит от ряда факторов. Также в CPython встречаются варианты использования, когда модели пересекаются.
Может оказаться, что для конкретной задачи можно выбирать между разными реализациями конкурентного выполнения, каждая из которых обладает своими достоинствами и недостатками.
В поставку CPython включены четыре модели в соответствующих модулях:
МОДУЛЬ |
КОНКУРЕНТНОСТЬ |
ПАРАЛЛЕЛИЗМ |
threading |
Да |
Нет |
multiprocessing |
Да |
Да |
asyncio |
Да |
Нет |
subinterpreters |
Да |
Да |
СТРУКТУРА ПРОЦЕССА
Одной из задач операционной системы, такой как Windows, macOS или Linux, является управление запущенными процессами. Такими процессами
Книги для программистов: https://t.me/booksforits

206 Параллелизм и конкурентность
могут быть UI-приложения вроде браузеров или IDE. Это также могут быть фоновые процессы — сетевые службы, службы операционной системы и т. д.
Для управления этими процессами ОС предоставляет API для запуска нового процесса. При создании процесс регистрируется операционной системой, чтобы она знала, какие процессы работают. Каждому процессу назначается уникальный идентификатор (PID). В зависимости от ОС процессы могут обладать другими свойствами.
POSIX-процессы обладают минимальным набором свойств, которые регистрируются в ОС:
zz Управляющий терминал. zz Текущий рабочий каталог.
zz Действующий идентификатор группы и действующий идентификатор пользователя.
zz Дескрипторы файлов и маска режимов создания файла.
zz Идентификатор группы процессов и идентификатор процесса.
zz Реальный идентификатор группы и реальный идентификатор пользователя.
zz Корневой каталог.
Чтобы просмотреть эти атрибуты для работающих процессов в macOS или Linux, выполните команду ps.
СМ. ТАКЖЕ
Стандарт IEEE POSIX(1003.1-2017) определяет интерфейс и стандартное поведение процессов и потоков.
Windows содержит похожий набор свойств, но устанавливает собственный стандарт. Файловые разрешения, структуры каталогов и реестр процессов в Windows сильно отличаются от POSIX.
Книги для программистов: https://t.me/booksforits

Структура процесса 207
Для получения информации о процессах Windows, представленных структурой Win32_Process, можно обратиться с запросом к среде WMI (Windows Management Instrumentation) или воспользоваться Диспетчером задач.
При запуске процесса в операционной системе ему предоставляется:
zz Стек в памяти для вызова подпрограмм.
zz Куча (см. «Динамическое выделение памяти в C»).
zz Доступ к файлам, блокировкам и сокетам операционной системы.
При выполнении процесса ЦП вашего компьютера также хранит дополнительные данные:
zz Регистр с текущей выполняемой инструкцией или любыми другими данными, необходимыми процессу для этой инструкции.
zz Указатель на инструкцию, или программный счетчик, указывающий, какая инструкция выполняется в настоящее время.
Процесс CPython включает скомпилированный интерпретатор Python
искомпилированные модули. Модули загружаются во время выполнения
ипреобразуются в инструкции циклом вычисления CPython:
|
|
|
|
|
|
• •• |
|
• • |
|||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
• •• CPython |
|
|
|
|
||||
|
|
|
|
|
|
|
|
• • • |
|||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Python |
|
|
|
|
|
|
• • •• |
|
|
|
|
|
||
|
|
|
|
|
|
|
|
||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
• |
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Регистр программы и программный счетчик указывают на одну инструкцию в процессе. Это означает, что в определенный момент времени выполняется
Книги для программистов: https://t.me/booksforits