Infiniband
В данной статье описывается настройка InfiniBand и RDMA на его основе для c7 и адаптеров ConnectX-3. Но основная последовательность действий в другой среде будет такой же, различия могут быть в именах пакетов и особенностях драйверов.
Список пакетов для установки
Важно понимать, что IB предоставляет возможность работы с железом преимущественно из юзерспейса, в обход ядра (переключения из пространства ядра в пространство пользователя слишком дорогое и неприемлемо на low-latency системах), так что драйвера в одном ядре мало.
Необходимы для работы:
ядро, собранной с поддержкой нужных IB устройств (в нашем случаеmlx4_core, mlx4_ib) libmlx4 — OFED компонента драйвера для Mellanox ConnectX HCA (юзерспейс) libibverbs librdmacm libibumad libibcm libibmad
Некоторые из указанных выше компонент могут не понадобится на узких задачах, но для облегчения настройки и отладки лучше поставить всё.
Это список утилит для работы с IB, отладки и тестирования, лучше поставить все:
libibverbs-utils librdmacm-utils perftest libopensm2 libinfiniband-diags infiniband-diags
Размер MTT таблицы
У драйвера IB адаптера есть один важный параметр: Memory Translation Table (MTT) — это таблица отображения страниц виртуальной памяти в реальную. Для работы RDMA размер MTT должен быть не меньше размера физической памяти системы, рекомендуется удвоенный размер для улучшенной обработки фрагментации и иных проблем), подробнее в руководстве open-mpi, документации melanox и ibm.
Конкретные ошибки могут возникать разные, но все они будут связаны с невозможностью работы RDMA или MPI. В документации выше описано решение, но оно верно для старых ядер, в сколь-либо современных (как минимум начиная с 3.x) параметры модуля mlx4_core ядра иные (log_num_mtt нет) и считать нужно немного иначе. Следует обратить внимание, что от слишком большого значения на машине с малым количеством памяти также вредно, т.к. уменьшит эффективность её использования.
По состоянию на ядро 4.14 у модуля mlx4_core есть один релевантный параметр log_mtts_per_seg, который задаётся в виде показателя экспоненты по основанию 2 и по-умолчанию равен 3. Эмпирическим путём было установлено, что достаточным является соотношение: full ram = 4GB * 2^log_mtts_per_seg, при этом максимально возможным значением, заложенным в драйвере является 7. Поэтому рекомендуется задавать log_mtts_per_seg = ⌈RAM/4GB⌉+1 для RAM <= 256 GB и log_mtts_per_seg = 7 для RAM >= 256 GB. (⌈x⌉ — округление вверх).
Итак, передаём нужный параметр модулю ядра при его загрузке:
# cat /etc/modprobe.d/ib.conf options mlx4_core log_mtts_per_seg=7
На других моделях карт или производителей могут быть похожие проблемы, поэтому следует уделять особое внимание размеру MTT при возникновении проблем с RDMA или MPI.
Загрузка модулей ядра
Необходимо загрузить следующие модули (и добавить в /etc/modules):
mlx4_ib — для карт Mellanox < ConnectX-5, для остальных производителей нужны свои ib_ipoib rdma_ucm ib_ucm ib_uverbs ib_umad rdma_cm ib_cm ib_mad iw_cm
Проверка на этом этапе, ibv должен видеть устройство:
# ibv_devices device node GUID ------ ---------------- mlx4_0 248a07030069dfa0
Менеджер подсети
Каждой сети Infiniband должен быть хотя бы один менеджер подсети (subnet manager). Часто его функции выполняет IB-свитч, но его может и не быть (например, соединение карта <-> карта) или он может быть ограничен по функциональности и нежелателен к использованию. Здесь рассматривается установка и настройка для простейшей топологии OpenSM.
На одном из узлов сети следует:
- Установить opensm2.
- Прописать в /etc/sysconfig/opensm:
OSM_HOSTS=hostname
где hostname — имя хоста, возвращаемое командой $ hostname
- Запустить opensm:
/etc/init.d/opensm start
- Проверить, что демон в автозагрузке:
chkconfig --list opensm
Следует отметить, что OpenSM способен обеспечивать топологию и маршрутизацию любой сложности, включая толстое дерево и многомерный tor, для каждой подсети такой топологии будет работать свой OpenSM. Подробности можно посмотреть в руководстве man opensm. При необходимости тонкой настройки рекомендуется создать полную конфигурацию opensm по-умолчанию с помощью opensm -c myopensmconf.conf.
Теперь можно проверить корректность инициализации IB сети:
#ibv_devinfo hca_id: mlx4_0 transport: InfiniBand (0) fw_ver: 2.42.5000 node_guid: 248a:0703:0069:dfa0 sys_image_guid: 248a:0703:0069:dfa3 vendor_id: 0x02c9 vendor_part_id: 4103 hw_ver: 0x0 board_id: MT_1090111019 phys_port_cnt: 2 port: 1 state: PORT_ACTIVE (4) max_mtu: 4096 (5) active_mtu: 4096 (5) sm_lid: 1 port_lid: 2 port_lmc: 0x00 link_layer: InfiniBand port: 2 state: PORT_DOWN (1) max_mtu: 4096 (5) active_mtu: 4096 (5) sm_lid: 0 port_lid: 0 port_lmc: 0x00 link_layer: InfiniBand
Следует обратить внимание на следующие параметры на подключенном порте:
state: PORT_ACTIVE (4) link_layer: InfiniBand
PORT_DOWN означает выключенный порт и/или отсутствие физического соединения.
PORT_INIT означает, что соединение есть, но находится в состоянии инициализации и ещё не готово к работе. Это часто бывает, если в сети нет subnet manager'а.
PORT_ACTIVE означает, что порт готов к работе.
Если link_layer: Ethernet или любой другой слой, кроме Infiniband, это означает, что поднят RDMA по другому протоколу, например, RDMA over Converged Ethernet (RoCE) и Infiniband не работает. Такое может быть на Mellanox картах с VPI интерфейсами (они могут работать как в режиме IB, так и в режиме CE).
IP over IB
Для приложений, работающих через lid/guid, в принципе, сделанной конфигурации достаточно. Но большинство приложений использует IP стек, поднятый поверх IB для инициализации соединений и получения части информации о конфигурации сети, поэтому
5. Создаём eth сеть поверх ib посредством ip-over-ib. Она нужна для
инициализации соединений и обмена данными между узлами. Сама пересылка
данных при этом идёт по IB.
На первом узле:
- ip addr add 192.168.20.1/24 dev ib0
На втором узле:
- ip addr add 192.168.20.2/24 dev ib0
IP/подсети можно на вкус выбирать, активное устройство может быть и не ib0, нужно проверить. Статус будет up после запуска subnet manager.
6. Проверка работы RDMA.
6.1. Простой IB RDMA ping:
На первом узле (192.168.20.1):
- ibv_rc_pingpong -g 0 -d mlx4_0 -i 1
На втором узле:
- ibv_rc_pingpong -g 0 -d mlx4_0 -i 1 192.168.20.1
где цифра после -i — номер активного порта, можно посмотреть в ibv_devinfo.
После запуска второй команды должна быть информация об обмене данными, вывод похож на обоих узлах:
local address: LID 0x0001, QPN 0x00004e, PSN 0xdfe7bc, GID fe80::248a:703:69:e001 remote address: LID 0x0002, QPN 0x00004f, PSN 0x212ee1, GID fe80::248a:703:69:dfa1
8192000 bytes in 0.01 seconds = 11638.43 Mbit/sec 1000 iters in 0.01 seconds = 5.63 usec/iter
6.2. Проверка отправки потока данных через RDMA:
На первой машине (сервер):
- rping -s -a 192.168.20.1 -v
на второй (клиент):
- rping -c -a 192.168.20.1 -v
Будет огромное число строк данных, убивается по ctrl-c.
Один и тот же ip выше — не ошибка, так и должно быть: для сервера — где слушать, для клиента — куда стучаться.
8. Если желают надёжной и быстрой работы IB, cpu frequency scaling, turbo boost и т.п. должны быть выключены. А мы имеем:
- cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_driver
intel_pstate
Это приводит к некорректной работе ряда тестов, впрочем, непосредственно к RDMA не относится. Причина в низких задержках IB и, как следствие, в высокой чувтсвительности к изменению частоты CPU.