Как я запускал блокнот Jupyter первого урока FastAI (частично) локально на Macbook Pro M1 Max и почему в конце концов сдался.
Несмотря на мой обширный опыт в мире веб-разработки, я новичок в области машинного обучения. Я провел исследование и решил начать свое исследовательское путешествие с FastAI.
Это уникальный и всеобъемлющий курс, созданный абсолютными мастерами машинного обучения. Более того, и это лучшая часть, она с самого начала подталкивает вас к уровню кода.
Преподаватели и учебник неоднократно говорят, что вы должны использовать предоставляемые услуги для запуска примеров кода и обучения своих моделей FastAI. Тем не менее, вы знаете тот инженерный дух, который шепчет попробовать все на ваших руках, на вашей локальной машине. Это, вероятно, не имеет смысла, хотя я должен был попробовать.
Будет проще, если у меня есть ноутбук или настольный компьютер с графическим процессором, поддерживающим CUDA. Но это не мой случай! Я использую Macbook для своих повседневных задач, как и многие другие разработчики. Более того, у меня есть ноутбук с чипом Apple ARM.
Чипы ARM полтора года назад были головной болью при решении многих рутинных задач разработки. Я помню, насколько мучительным был процесс настройки правильных образов докеров для тестовых контейнеров. Тем не менее, большинство этих проблем остались в прошлом. Macbook на базе M1 — это фантастический инструмент для веб-программирования на сегодняшний день.
Вот ноутбук, который я использовал для этой статьи:
Чип: Apple M1 Max
Общее количество ядер: 10 (8 производительных и 2 эффективных)
Память: 64 ГБ
Меня не удивило, что это не относится к набору инструментов ML. Самые популярные фреймворки машинного обучения, Tensorflow и PyTorch, поддерживают М-чипы Apple. Я сосредоточусь на PyTorch, так как это фреймворк, который FastAI использует под капотом.
PyTorch уже давно поддерживает ускорение CUDA. Однако поддержка графического процессора Apple M1 была представлена в мае 2022 года, меньше года назад. Он все еще находится в бета-версии и имеет некоторые проблемы даже в последней сборке для разработчиков. Он доступен в MacOS 12.3+ и для библиотек версии 1.12+.
PyTorch интегрирует Шейдеры Apple Metal Performance Shaders (MPS). Подробности в документации по ссылке. Короче говоря, это позволяет PyTorch использовать ядра графического процессора процессора M1. Это запускает FatsAI с использованием графического процессора. Ю-ху! Мы должны получить производительность графического процессора для обучения нашей модели прямо на MacBook!
Прежде чем углубляться в подробности эксперимента, я хотел бы поделиться версиями библиотек, поскольку в современном мире машинного обучения все быстро меняется.
# # Name Version Build Channel ... fastai 2.7.10 pypi_0 pypi fastcore 1.5.28 pypi_0 pypi fastdownload 0.0.7 pypi_0 pypi fastprogress 1.0.3 pypi_0 pypi ffmpeg 4.2.2 h97e5cf8_0 pandas 1.5.3 pypi_0 pypi pip 22.3.1 py310hecd8cb5_0 python 3.10.9 h218abb5_0 pytorch 2.0.0.dev20230207 py3.10_0 pytorch-nightly scikit-learn 1.2.1 pypi_0 pypi scipy 1.10.0 pypi_0 pypi
Примечание. В итоге я использовал выпуск PyTorch-nightly , но все результаты одинаковы для последней стабильной версии — 1.13.1.
После начального чтения и исследования я начал с примеров кода Урока 1. Примечательно, что код запускается с нуля на чипе M1 без каких-либо модификаций. Единственная проблема заключается в том, что он использует ядра ЦП.
Mac использует все доступные ядра — эффективность и производительность.
Независимо от этого, временные показатели могут быть лучше, чем ожидалось. Первый запуск фрагмента кода, включающий обучение модели (vision_learner для набора данных изображений), занимает более 10 минут для эпохи.
Время заставить GPU немного попотеть.
Спасибо, FastAI API; он позволяет выполнять многие действия, в том числе работать с устройствами PyTorch. Тем не менее поиск функционального подхода в сети занял время. Самый популярный совет — просто установка устройства в модуль «факел» приводит к ошибке.
import torch torch.device("mps") #ERROR found at least two devices, mps:0 and cpu
Я предположил, что в данном случае у самой модели и обучаемого разные устройства. Таким образом, передача параметра устройства для запуска модели решает все проблемы:
dls = ImageDataLoaders.from_name_func( path, get_image_files(path), valid_pct=0.2, seed=42, label_func=is_cat, item_tfms=Resize(224), device=default_device(1))
Метод внутренней реализации default_device проверяет, используете ли вы устройство MPS или нет, и передает его в инициацию модели:
def default_device(use=-1): "Return or set default device; `use_cuda`: -1 - CUDA/mps if available; True - error if not available; False - CPU" if use == -1: use = defaults.use_cuda else: defaults.use_cuda=use if use is None: if torch.cuda.is_available(): use = True if use: if torch.cuda.is_available(): return torch.device(torch.cuda.current_device()) if _has_mps(): return torch.device('mps') return torch.device('cpu')
Вы можете проверить, поддерживает ли ваша сборка MPS:
#built with MPS activated. print(torch.backends.mps.is_built()) print(torch.backends.mps.is_available())
И весь код нарезан вместе:
#id first_training #caption Results from the first training # CLICK ME from fastai.vision.all import * import fastai import torch path = untar_data(URLs.PETS)/'images' print(torch.backends.mps.is_available()) def is_cat(x): return x[0].isupper() dls = ImageDataLoaders.from_name_func( path, get_image_files(path), valid_pct=0.2, seed=42, label_func=is_cat, item_tfms=Resize(224), device=default_device(1)) learn = vision_learner(dls, resnet34, metrics=error_rate) learn.fine_tune(1)
Результаты были невероятными!Увеличение производительности практически в 10 раз. Просто посмотрите на график мониторинга графического процессора!
ЦП отдыхает. При этом GPU справился примерно за минуту!
В тот момент я был очень доволен результатами. Время очень близко к тому, что показано в курсе, локально на моей машине!
Но мое настроение испортилось, как только я переключился на следующие фрагменты кода, обучающие разные модели. Честно говоря, большинство из них прошли хорошо, кроме пары.
Первый:
from fastai.text.all import * # default_device(torch.device("cpu")) dls = TextDataLoaders.from_folder(untar_data(URLs.IMDB), valid='test', bs=32, device=default_device(False)) learn = text_classifier_learner(dls, AWD_LSTM, drop_mult=0.5, metrics=accuracy) learn.fine_tune(4, 1e-2)
Этот код не выполнен из-за исключения
Операция neg_out_mps() не поддерживает тип ввода int64 в бэкенде MPS.
Я перешел к дальнейшим исследованиям. Бинго! Это именно та проблема, которую я нашел на GitHub — https://github.com/pytorch/pytorch/issues/86319
Ждать! Это решено и объединено! Время получить ночную сборку и начать заново.
Но нет! Это та же проблема и лог, но в другом месте.
У меня была только возможность применить это исправление в месте, где я обнаружил проблему (site-packages/fastai/text/models/core.py:118),перестроить PyTorch локально с исправлением и запустите все еще раз, надеясь, что это была последняя проблема.
Это исправление может занять гораздо больше времени. Похоже, слишком много, чтобы продолжать играть с настройкой M1.
Тем не менее, я запустил оставшиеся фрагменты кода, чтобы узнать, есть ли еще проблемы. И они были здесь. При следующем обучении ядро ноутбука Jupyter умирает при каждом запуске с небольшими подробностями.
Это была последняя капля для меня.
Я запускаю тот же код, используя ЦП, чтобы получить оценку времени для себя. Цифры плачевные. Больше часа на эпоху. Процессор просто не подходит для этой работы.
Вернемся к альтернативам. Paperspace, на мой взгляд, является лучшим вариантом для удаленного запуска примеров курса FastAI. Он дает вам больше информации об оборудовании и среде, а не, например, блокноты Google Colab, которые являются черными ящиками для пользователь. Бесплатных экземпляров Papaerspace нет в наличии. Тем не менее, вы можете платить 8 долларов в месяц и использовать бесплатные экземпляры более высокого уровня за дополнительную плату. Он также может быть не в состоянии. Но все же это хороший вариант.
Следующий экземпляр выполняет работу вдвое быстрее, чем мой Macbook Pro Max.
Следующий (платный экземпляр) дал 15 секунд (!), тогда как Macbook M1 Max с использованием графического процессора работает около 1 минуты.
Это действительно здорово, что PyTorch поддерживает чип M1. Также было интересно поэкспериментировать с курсом, технологиями и моим Macbook. Во всяком случае, наставник был абсолютно прав; это не стоит потраченного времени. Просто используйте развернутые удаленные решения, которые позволят вам сконцентрировать свои усилия на изучении курса, а не на бесконечном исправлении ошибок, связанных с ARM.
Удачного кодирования!