Как я запускал блокнот 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.

Удачного кодирования!