Окружение дата-аналитика на Mac OS 🍏 в 2021году

Stats&Data ninja
11 min readDec 16, 2021

--

Прошёл год с тех пор как Apple выпустила свои первые ноутбуки на процессорах M1 с архитектурой ARM. Многие популярные программы, особенно в области контента , довольно быстро добавили нативную поддержку данных ядер (vlc, многие приложение из Adobe Creative Cloud 🎥📽). Спецов по Data Engineering/Science также порадовали нативной поддержкой Visual Studio Code, Docker, Homebrew, Parallels Desktop 🤯. Однако существуют мнения, что для scientific computing данная архитектура не предназначена, и аналитик столкнется со множество проблем на M1.

Давай разберемся, как дата-аналитику настроить себе локальное окружение и точно ли будет больно при использовании ноутбуков на этой архитектуре??

0. Инструменты разработчика

Шаг №1 состоит в том, чтобы поставить себе dev-инструменты. Этот шаг не зависит от версии мака (ARM или Intel) и содержит в себе такие фундаментальные вещи как git и компилятор C++ кода, необходимый для сборки библиотек из исходников 🤓.

Первым делом ставим себе Apple’s Xcode Command Line Tools. Конечно, можно не пользоваться терминалом и поставить себе полноценный графический Xcode из AppStore. Однако он весит 12GB и вряд ли дата-аналитик будет пользоваться им в качестве IDE.

Пакетный менеджер

Нам необходим менеджер пакетов, чтобы устанавливать приложения (с поддержкой зависимостей) через команды, а не через скачивание архивов — так проще, быстрее и мне легче описывать 🥴. Для Mac OS основным является Homebrew 🏠. На оф-сайте показано как поставить:

# Понадобится sudo-доступ (например через sudo su)
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Далее установщик предложит добавить путь к программе в $PATH (переменная среды), чтобы можно было вызывать brew из командной строки. Делаем, как он говорит:

$ echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/${USER}/.zprofile$ eval "$(/opt/homebrew/bin/brew shellenv)"

В примере 👆вместо имени пользователя подставлен переменная среды, которая автоматически его вычислит. По сути PATH — указатель местоположения всех запускаемых бинарников, изначально берет инфу отсюда sudo nano /etc/paths.

Архитектура процессора

Для начала стоит чекнуть, правда ли у тебя M1 (первая строчка это команда, а вторая — вывод):

$ arch 
arm64

Ноутбуки на процессорах Inter выведут “i386” 💻.

До Homebrew 3.0 (на момент написания статьи уже доступна версия 3.3.8) не было отдельной версии под M1, и его можно было установить через:

$ arch -x86_64 /bin/bash -c “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"#добавляем псевдоним
$ alias brew=”arch -x86_64 brew”
# аналогично можно поставить все пакеты (но не надо так делать🤦‍♂):
# arch -x86_64 pip install numpy

Однако не рекомендую использовать arch -x86_64, т.к. это сводит на нет всю дальнейшую статью. Дело в том, что данные команды будут работать через Rosetta, о которой мы и поговорим в след. разделе.

1. Rosetta

Почти все приложения на M1 Mac можно запускать под Rosetta 2 (названо аналогично Rosetta, которую Apple использовала при замене процов PowerPC на Intel). Это транслятор, который переводит ISA (машинный код) c архитектуры x86_64 (AMD64) на ARM64 (AArch64, Apple Silicon). То есть программа будет запускаться как будто на процессоре от Intel.

$ /usr/sbin/softwareupdate --install-rosetta --agree-to-license

Выше код, ставящий Rosetta. Также, мак сам попросит ее поставить при запуске любой приложухи, не адаптированной под M1.

Картинка 1. Activity Monitor на Mac M1

Например, RStudio. Это видно в системном приложении под названием Activity Monitor (колонка Kind). Почти все вопросы на Stack Overflow, касающиеся установки пакетов для DS на Mac M1, получают в ответ предложение запускать терминал под Rosetta 2.

Можно скачать iTerm2 (или запустить brew install --cask iterm2) и сделать его отдельным терминалом под Rosetta. Далее пользоваться им как будто это терминал на компе с процессором Intel.

Минус такого подхода: обычно он на 20–30% медленнее 🐌, чем на нативный x86–64 (из блога Anaconda 🐍). Происходит это потому, что ARM (и следовательно Rosetta2) не поддерживает векторные операции (AVX). Некоторые программы автоматом выбирают вместо них другие, более простые (и менее производительные) инструкции. Также, возникает вторая проблема — некоторые библиотеки не используют альтернативу AVX, поэтому они не будут работать под Rosetta2. Например, TensorFlow.

2. Нативный M1

Конечно, лучше использовать нативные команды M1. Например, Apple представила свой форк для TensorFlow, и заявляет, что его запуск на M1 в 7 раз быстрее 🚀, чем на Intel. Давай разбираться, как настроить native- окружение.

2.1 Установка Python

Рассматриваю только 3й python. Для python 2 в начале прошлого года наступил EOL. Ставим через Homebrew, и можем проверить в Activity Monitor, что python будет работать под arm64.

$ brew install python 
# или лучше brew install python@3.9

Также, вместо brew можно воспользоваться pyenv для установки python в собственную виртуальную среду.

$ brew install openssl readline sqlite3 xz zlib
$ brew install pipenv
# или pip install --user pipenv
$ pyenv install 3.9.4# PYTHONPATH=/opt/homebrew/Caskroom/miniforge/base/pkgs/:$PYTHONPATH

Первая команда — установка зависимостей. Мануал для других версий питона 3 можно найти тут. Но! Тому же tensorflow на M1 нужна версия 3.9, а оф. сайт python заявляет, что полная поддержка ARM64 только с 3.9.1.

Смотрим, куда homebrew/pyenv положили питон:

$ type -a python3
python3 is /opt/homebrew/bin/python3
python3 is /usr/bin/python3

Далее, чекаем что наш Python нужной архитектуры:

$ file /opt/homebrew/bin/python3
opt/homebrew/bin/python3: Mach-O 64-bit executable arm64
# или проще:
$ file "$(which python3)"

2.2 Установка пакетов в python

Картинка 2. User-agent в Chrome для Mac M1

Стандартным способом ставить пакеты 📦 в python является pip, однако на M1 использовать его не стоит. Дам объяснение на пальцах (понимаю, что бывалые меня засмеют, но статья для аналитиков с небольших опытом👨🏻‍🏫). В индексе пакетов PyPI (куда ходит команда pip) для большинства пакетов существует заранее скомпилированные версии под конкретную ОС (т.н. wheels). При установке на Mac OS часть пакетов отдаст wheels, скомпилированные под процессоры Intel. Даже если такие пакеты установятся, при импорте они скорее всего упадут с ошибкой ☠️.

Правильный 🤌🏾 способ установить python-пакеты в Mac M1 — через miniforge. Это почти тоже самое, что и miniconda, но умеет определять архитектуру aarch64 и содержит бинарники пакетов под ARM.

$ brew install --cask miniforge

$ conda init zsh
# или conda init "$(basename "${SHELL}")"
$ conda activate

Можно не использовать терминал, а скачать правильный архив для aarch64 (Apple Silicon) на их Github.

Почему бы просто не поставить Anaconda? Есть несколько причин. Во-первых, полный дистрибутив весит 3GB и содержит 3к пакетов, что очевидно излишне. Во-вторых, 💰: многие собираются использовать данное окружение для выполнения своих рабочих задач, а я напомню, что использование Anaconda в коммерческих целях запрещено, а вот с mini-conda все сложнее. Как я понял из лицензии👩🏼‍✈️, она о репозитории, не о самой программе. В-третьих, только forge поддерживает aarch64.

2.3 Ставим основной стек

Если пакеты уже стоят, то скорее всего из wheels (обсудили выше), поэтому их изначально нужно удалить через pip3 uninstall …) ❗

Если ставить python без pyenv можно считать безгрешным способом, то ставить пакеты точно стоит в виртуальную среду. 1 Проект = 1 env — это культура 🥸, к которой стоит себя приучить. Многим это может показаться оверхэдом, но без этого будет очень больно 🤬🥵 в случае конфликта версий с системными библиотеками или другими приложениями.

$ conda create --name my_env python=3.9
(my_env)$ conda activate my_env
# чекаем
(my_env)$ file $(which python)
/opt/homebrew/Caskroom/miniforge/base/envs/my_env/bin/python: Mach-O 64-bit executable arm64

Большинство пакетов уже давно портировано, их статус можно проверить на этом сайте.

(my_env)$ conda install numpy
# можно через brew install numpy
(my_env)$ conda install pandas
(my_env)$ conda install matplotlib
(my_env)$ conda install plotly
(my_env)$ conda install statsmodels
(my_env)$ conda install scipy
# или brew install scipy
(my_env)$ conda install scikit-learn(my_env)$ conda install jupyter
(my_env)$ conda install jupyterlab

Можно посмотреть, куда conda ставит библиотеки:

(my_env)$ python3
>>import sys
>>print(sys.prefix, sys.path)
/opt/homebrew/Caskroom/miniforge/base/envs/my_env
(my_env)$ python3 -m site
# выведет также путь для установки флагом --user

О том, как использовать conda ты скорее всего знаешь, но если нет — лучше все же покурить мануал 🥱.

2.3 Библиотеки для ML

Начнем с бустинга, поскольку интерпретируемое и хорошо изученное семейство методов с небольшим порогом входа (на изучение), но в то же время очень мощное (даже один из победителей соревнования на Kaggle заявил, что его интерес состоит в том чтобы побить бустинг с помощью нейронок).

Установка LightGBM на m1

Все просто, поскольку LightGBM уже имеет нативный релиз ☺️для M1.

(my_env)$ conda install lightgbm
# или brew install lightgbm
(my_env)$ python3
>>import lightgbm as lgb

Установка XGBoost на m1

К сожалению, пока XGBoost не имеет нативного пакета, но может быть собран из исходников 🧠. Есть 2 варианта: воспользоваться доками и собрать пакет из репозитория на github ; или воспользоваться pip, который сделает то же самое (хотя работать будет несколько минут). Первый вариант сложнее, но надежнее. Второй выглядит так:

# обязательно ставить нативные numpy и scipy (см. блок 2.3)
# они являются зависимостями xgboost
(my_env)$
brew install cmake libomp
(my_env)$ pip3 install xgboost
(my_env)$ python3
>>from xgboost import XGBClassifier

К сожалению, оба варианта будут работать только на CPU без GPU-ускорения.

Установка CatBoost на m1

К сожалению, нативного пакета CatBoost пока нет в индексах, хотя в issue на github его команду постоянно пушат👊🏽, она обещала доделать в ближайшее время🤝. Тем не менее, можно собрать его из исходников, однако не будут использоваться перфоманс-фичи процессора.

Пакеты для Causal Inference

Пакеты от Microsoft прекрасно ставятся из miniforge.👯‍♂️

(my_env)$ conda install econml
(my_env)$ conda install dowhy
(my_env)$ python3
>>import econml
>>from econml.orf import DMLOrthoForest, DROrthoForest
>>from econml.dml import CausalForestDML
>>import dowhy
>>from dowhy import CausalModel
>>import dowhy.datasets

Если стоят старые версии библиотек, нужно переставить с помощью conda install -c conda-forge dowhy .

А вот поставить нативный CausalML не получится.

2.4 Deep learning

Apple особенно заботится 🫂 о том, чтобы на ее железе работали нейронки, потому как:

  1. Многие ДС выбирает макбуки в качестве рабочего компьютера
  2. Разработчиков контента 🎮📹 традиционно сидят на маках, используя фото/видео/аудио-редакторы 📷, а эти программы будут максимально использовать DL внутри себя.

Поэтому Apple разработала внутри себя т.н. Apple Neural Engine (ANE), состоящий из множества NPU. Это аналог GPU, только заточенный не под графику, а под нейронки. Ты мог видеть подобное в Google’s TPU. Все макбуки на M1 на текущий момент оснащены 16-ядерным ANE, что должно давать сильно ускорение по сравнению с обучением на CPU.

К сожалению, прямого доступа у разработчиков в ANE нет, только через CoreML, библиотеку от Apple. Так можно получить ускорение?

Установка TensorFlow на m1

Как я уже описывал выше, у Apple есть свой плагин TensorFlow, который работает на GPU M1. Давай его установим.

# удаляем старые версии пакетов, если они есть
(my_env)$ uninstall existing tensorflow-macos and tensorflow-metal
(my_env)$ conda install -c apple tensorflow-deps# если уже стояла прошлая версия
(my_env)$ conda install -c apple tensorflow-deps --force-reinstall
# ставим пакет
(my_env)$ python3 -m pip install tensorflow-macos
# ставим плагин
(my_env)$ python3 -m pip install tensorflow-metal
(my_env)$ python3
>>import tensorflow as tf
>>print(tf.__version__)

Большинство туториалов в сети рекомендуют создавать отдельную env для tensorflow, хотя большую часть зависимостей 🕸 мы уже установили раньше. Если по какой-то причине tf не установится/запустится, нужно еще раз сделать conda create и поставить туда уже готовый wheel:

(my_env)$ pip install --upgrade --force --no-dependencies https://github.com/apple/tensorflow_macos/releases/download/v0.1alpha2/tensorflow_addons_macos-0.1a2-cp38-cp38-macosx_11_0_arm64.whl https://github.com/apple/tensorflow_macos/releases/download/v0.1alpha2/tensorflow_macos-0.1a2-cp38-cp38-macosx_11_0_arm64.whl

Установка PyTorch на m1

Заработал совсем недавно. Проблема в том, что PyTorch все же заточен под GPU от NVIDIA (т.е. поддержка даже AMD появилась только в марте), что уже говорить про M1. Очевидно, работать он будет только на CPU и очень медленно.

(my_env)$ conda install -c pytorch pytorch torchvision(my_env)$ python3
>>import torch

Установка Keras на m1

А вот поставить Keras к сожалению не получится.

2.5 Другие версии python и библиотек

Если у тебя python≤3.8, и ты не хочешь обновлять numpy (с версии 1.21.0 он уже имеет универсальные wheels, работающие под обе архитектуры) и др. пакеты, для тебя сработает билд из исходников.

В первую очередь, нам потребуется pip.

# Для начала чекаем, что версия python и pip совпадает
$ pip3 --version && python3 --version
# если pip не стоит (хотя он идет вместе с python в homebrew)
# curl https://bootstrap.pypa.io/get-pip.py | python3
$ python3 -m pip install — upgrade pip setuptools wheel

Как я уже писал, хорошим тоном является создание своего env под проект, например через conda или pyenv. Туториал как этим пользоваться, можно найти тут. Можно также использовать модуль стандатной библиотеки — venv (до версии 3.3 это была отдельная либа virtualenv):

$ pip3 install — upgrade pip
$
pip3 install -U venv
$ python3 -m venv -p python3.8 new_venv
$ source new_venv/bin/activate
# выйти можно вот так:
$ deactivate

Далее собираем зависимости:

$ brew install cmake 
# dep для сборки пакетов из исходников
$ brew install openblas libomp gfortran
# dep для numpy
$ brew install libjpeg
# dep для Pillow -> matplotlib

$
pip3 install cython pybind11 pythran
# pythran нужен для scipy, ставить уже после numpy

Далее, ставим пакеты. Фишка в том, что бы зафорcить pip не использовать wheels, а собирать самому. Для этого, вначале объявляем переменные среды:

$ export OPENBLAS=$(/opt/homebrew/bin/brew --prefix openblas)
$ export CFLAGS="-falign-functions=8 ${CFLAGS}"

Ставим numpy

$ pip3 install --no-binary :all: --no-use-pep517 numpy

Ставим pandas

# можно попробовать так:
$ pip3 install --no-binary :all: --no-use-pep517pandas
$ pip3 install ib_insync
# второй вариант - прямой билд из репо без pip
$ git clone https://github.com/pandas-dev/pandas.git
$ cd pandas
$ python3 setup.py install

Ставим scipy

# опять вариант с pip
$
MACOSX_DEPLOYMENT_TARGET=11.1 pip3 install --no-binary :all: --no-use-pep517 scipy==1.7.0
# и опять вариант без pip
$ git clone https://github.com/scipy/scipy.git
$ cd scipy
$ git submodule update --init
$ pip3 install .
# можно попробовать поставить ночную сборку
$ pip3 install --pre --extra-index -i https://pypi.anaconda.org/scipy-wheels-nightly/simple scipy

Теперь sklearn

Как указано на оф. сайте, единственный способо установить пакет на M1 — через mini-forge. Тем не менее, указанный issue на доступность в PyPI закрыт 🤷‍♂. Поэтому думаю, что можно ставить через pip:

 $ pip3 install scikit-learn

3. Установка R

Год назад разработчики R написали блог-пост, в котором объяснили почему на тот момент не было нативного пакета для ARM. Проблема в том, что R требует Fortran, нативного компилятора которого все еще нет. Сейчас это проблема кажется удивительной, учитывая что Numpy, Scipy и другие питоновские пакеты также требуют Fortran, но при этом для них уже есть готовые сборки под M1.

Хорошие новости — есть экспериментальный компилятор фортрана под M1, который неплохо работает. Поэтому разработчики R сделали билды под ARM на этом компиляторе, вот отдельная страница проекта. Надо понимать, что это экспериментальная сборка, поэтому ошибки не исключены (почитайте в блок по ссылке выше про проблему с NA). На официальном зеркале cran (в России это зеркало МГУ 👨🏼‍🎓) уже есть эти бинарные сборки под arm64, которые будут исправно работать. Могут возникнуть проблемы с установкой пакетов, которые необходимо билдить из исходников. Тут более-менее описано, как это решить.

Также, можно скачать версию под mac для x86–64, которая “it is also known to work using Rosetta2 on M1-based Macs”, и не будет иметь проблем с библиотеками, но будет иметь проблемы с производительностью.

Надо понимать, что поставить Microsoft R Open (тот же R, но более производительный) на Macbook M1 не получится😿.

RStudio

В отличии от самого R, RStudio (основная среда разработки под него) до сих пор не нативна, а значит нельзя запустить в ней например tensorflow 🙉.

Тут я могу рекомендовать следующее — писать основной код в RStudio, а когда потребуются библиотеки под ARM — запускать их в R GUI (т.н. R Console).

Или, что еще лучше — использовать Visual Studio Code (например, чтобы использовать Copilot). Для R потребуется поставить расширения (раз, два) и настроить languageserver. Инструкцию можно найти тут.

Пока на этом все. Закономерный вопрос, зачем это нужно, ведь большая часть работы с python происходит на сервере с большим кол-вом ресурсов. Но стоит понимать, что серверное окружение может содержать старые версии библиотек, и к тому же требует постоянного интернета. Поэтому кажется, что в 2021 и следующем 2022 😷 для удаленной работы стоит настроить окружение локально.

Конечно, Python и R лишь часть того, что использует аналитик, поэтому у этой статьи точно будет продолжение.

P.S.: Если тебе понравилась стать, в качестве благодарности можешь купить мне кофе на https://www.donationalerts.com/r/stats_data_ninja или https://buymeacoffee.com/koch.

--

--

Stats&Data ninja
Stats&Data ninja

No responses yet