Кэширование в Python: алгоритм LRU |
||||||||||||||||||||
МЕНЮ Искусственный интеллект Поиск Регистрация на сайте Помощь проекту ТЕМЫ Новости ИИ Искусственный интеллект Разработка ИИГолосовой помощник Городские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Нейронные сети начинающим Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Техническое зрение Чат-боты Авторизация |
2020-11-17 19:49 Эта публикация – незначительно сокращенный перевод статьи Сантьяго Валдаррама Caching in Python Using the LRU Cache Strategy. Переведенный текст также доступен в виде блокнота Jupyter. *** Кэширование – один из подходов, который при правильном использовании значительно ускоряет работу и снижает нагрузку на вычислительные ресурсы. В модуле стандартной библиотеки Python В этом руководстве мы рассмотрим:
Кэширование в Python: в чем польза Кэширование– это метод оптимизации хранения данных, при котором операции с данными производятся эффективнее, чем в их источнике. Представим, что мы создаем приложение для чтения новостей, которое агрегирует новости из различных источников. Пользователь перемещается по списку, приложение загружает статьи и отображает их на экране. Как поступит программа, если читатель решит сравнить пару статей и станет многократно между ними перемещаться? Без кэширования приложению придется каждый раз получать одно и то же содержимое. В этом случае неэффективно используется и система пользователя, и сервер со статьями, на котором создается дополнительная нагрузка. Лучшим подходом после получения статьи было бы хранить контент локально. Когда пользователь в следующий раз откроет статью, приложение сможет открыть контент из сохраненной копии, вместо того, чтобы заново загружать материал из источника. В информатике этот метод называетсякэшированием. Реализация кэширования в Python посредством словаря В Python можно реализовать кэширование, используя словарь. Вместо того, чтобы каждый раз обращаться к серверу, можно проверять, есть ли контент в кэше, и опрашивать сервер только если контента нет. В качестве ключа можно использовать URL статьи, а в качестве значения – ее содержимое: Примечание. Для запуска этого примера у вас должна быть установлена библиотека Хотя вызов Стратегии кэширования В этой простой реализации кэширования закралась очевидная проблема: содержимое словаря будет неограниченно расти: чем больше статей открыл пользователь, тем больше было использовано места в памяти. Чтобы обойти эту проблему, нам нужна стратегия, которая позволит программе решить, какие статьи пора удалить. Существует несколько различных стратегий, которые можно использовать для удаления элементов из кэша и предотвращения превышения его максимального размера. Пять самых популярных перечислены в таблице.
Погружаемся в идею LRU-кэширования Кэш, реализованный посредством стратегии LRU, упорядочивает элементы в порядке их использования. Каждый раз, когда мы обращаемся к записи, алгоритм LRU перемещает ее в верхнюю часть кэша. Таким образом, алгоритм может быстро определить запись, которая дольше всех не использовалась, проверив конец списка. На следующем рисунке показано представление кэша после того, как пользователь запросил статью из сети. Статья сохраняется в последнем слоте кэша перед тем, как будет передана пользователю. На следующем рисунке показано, что происходит, когда пользователь запрашивает следующую статью. Вторая статья занимает последний слот, перемещая первую статью вниз по списку. Стратегия LRU предполагает: чем позже использовался объект, тем больше вероятность, что он понадобится в будущем. Алгоритм сохраняет такой объект в кэше в течение максимально длительного времени. Заглядываем за кулисы кэша LRU Один из способов реализовать кэш LRU в Python – использовать комбинациюдвусвязного спискаихеш-таблицы. Головной элемент двусвязного списка указывает на последнюю запрошенную запись, а хвостовой – на наиболее давно использовавшуюся. На рисунке ниже показана возможная структура реализации кэша LRU. Используя хеш-таблицу, мы обеспечиваем доступ к каждому элементу в кэше, сопоставляя каждую запись с определенным местом в двусвязном списке. При этом доступ к недавно использовавшемуся элементу и обновление кэша – это операции, выполняемые за константное время (то есть свременной сложностьюалгоритма?(1). Примечание Примеры временной сложности различных функций Python рассматривались на proglib в статье «Сложность алгоритмов и операций на примере Python». Начиная с версии 3.2, для реализации стратегии LRU Python включает декоратор Использование @lru_cache для реализации кэша LRU в Python Декоратор Наглядное представление алгоритма: перепрыгиваем ступеньки Представим, что мы хотим определить число способов, которыми можем достичь определенной ступеньки на лестнице. Сколько есть способов, например, добраться до четвертой ступеньки, если мы можем переступить-перепрыгнуть 1, 2, 3 (но не более) ступеньки? На рисунке ниже представлены соответствующие комбинации. Под каждым из рисунков приведен путь с указанием числа ступенек, преодоленных за один прыжок. При этом количество способов достижения четвертой ступеньки равно общему числу способов, которыми можно добраться до третьей, второй и первой ступенек: Получается, что решение задачи можно разложить на более мелкие подзадачи. Чтобы определить различные пути к четвертой ступеньке, мы можем сложить четыре способа достижения третьей ступеньки, два способа достижения второй ступеньки и единственный способ для первой. То есть можно использовать рекурсивный подход. Опишем программно рекурсивное решение в точности, как мы его сейчас видим: Код работает для 4 ступенек. Давайте проверим, как он подсчитает число вариантов для лестницы из 30 ступенек. Получилось свыше 53 млн. комбинаций. Однако когда мы искали решение для тридцатой ступеньки, сценарий мог длиться довольно долго. Засекаем время выполнения программного кода Измерим, как долго длится выполнение кода. Примечание О различных вариантах работы со временем в Python вы можете прочитать в публикации «Назад в будущее: практическое руководство по путешествию во времени с Python». Эта публикация также адаптирована в виде блокнота Jupyter. Для этого мы можем использовать модуль Python Количество секунд зависит от характеристик используемого компьютера. В моей системе расчет занял 3 секунды, что довольно медленно для всего тридцати ступенек. Это решение можно значительно улучшить c помощьюмемоизации. Примечание Один из примеров мемоизации рассматривался в статье«Python и динамическое программирование на примере задачи о рюкзаке». Использование мемоизации для улучшения решения Наша рекурсивная реализация решает проблему, разбивая ее на более мелкие шаги, которые дополняют друг друга. На следующем рисунке показано дерево для семи ступенек, в котором каждый узел представляет определенный вызов Можно заметить, что алгоритму приходится вызывать Чтобы решить эту проблему, мы можем использовать мемоизацию: мы сохраняем в памяти результат, полученный для одних и тех же входных значений и затем возвращаем при следующем аналогичном запросе. Прекрасная возможность применить декоратор Примечание Если вы незнакомы с концепцией декораторов, но хотите глубже разобраться в вопросе, просто прочитайте материал«Всё, что нужно знать о декораторах Python» (она также адаптирована в форматеJupyterи Colab). Для наших задач достаточно знать, что это функции-обертки, которые позволяют модифицировать поведение функций и классов. Чтобы применить декоратор, достаточно объявить его перед определением функции. Импортируем декоратор из модуля Примечание В Python 3.8 и выше, если вы не указываете никаких параметров, можно использовать декоратор От единиц секунд к десяткам наносекунд – потрясающее улучшение, обязанное тем, что за кулисами декоратор Другие возможности @lru_cache Подключив декоратор У декоратора Применим Мы можем использовать информацию, возвращаемую
Добавление срока действия кэша Перейдем от учебного примера к более реалистичному. Представьте, что мы хотим отслеживать появление на ресурсе Real Python новых статей, содержащих в заголовке слово Real Python предоставляетпротокол Atom, так что мы можем использовать библиотеку Скрипт будет работать непрерывно, пока мы не остановим его, нажав Код загружает и анализирует xml-файл из RealPython. Далее цикл перебирает первые пять записей в списке. Если слово Каждый раз, когда сценарий загружает статью, в консоль выводится сообщение «Получение статьи с сервера...». Если мы позволим скрипту работать достаточно долго, мы увидим, что это сообщение появляется повторно даже при загрузке той же ссылки. Мы можем использовать декоратор Критерии исключения записей из кэша Мы можем реализовать описанную идею в новом декораторе, который расширяет Декоратор Код оборачивает функцию декоратором Перед доступом к записи в кэше декоратор проверяет, не наступила ли дата истечения срока действия. Если это так, декоратор очищает кэш и повторно вычисляет время жизни и срок действия. Время жизни распространяется на кэш в целом, а не на отдельные статьи. Кэширование статей с помощью нового декоратора Теперь мы можем использовать новый декоратор Обратите внимание, как код печатает сообщение «Получение статьи с сервера ...» при первом доступе к соответствующим статьям. После этого, в зависимости от скорости cети, сценарий будет извлекать статьи из кэша несколько раз, прежде чем снова обратится к серверу. В приведенном примере скрипт пытается получить доступ к статьям каждые 5 секунд, а срок действия кэша истекает раз в минуту. Заключение Кэширование – важный метод оптимизации, повышающий производительность любой программной системы. Понимание того, как работает кэширование, является фундаментальным шагом на пути к его эффективному включению в программный код. В этом уроке мы кратко рассмотрели:
Следующим шагом к реализации различных стратегий кэширования в ваших приложениях может стать библиотекаcachetools, предоставляющая особые типы данных и декораторы, охватывающие самые популярные стратегии кэширования. Источники Источник: proglib.io Комментарии: |
|||||||||||||||||||