Большинство заданий на программирование с низкой задержкой / высокой частотой (на основе спецификаций заданий), по-видимому, реализуются на платформах Unix. Во многих спецификациях они делают особый запрос для людей с опытом работы с «низкой задержкой Linux».
Предполагая, что это не означает ОС Linux в реальном времени, могут ли люди помочь мне с тем, к чему это может относиться? Я знаю, что вы можете установить привязку процессора к потокам, но я предполагаю, что они просят гораздо большего.
Тюнинг ядра? (хотя я слышал, что производители, такие как solarflare, производят сетевые карты с обходом ядра)?
Как насчет DMA или, возможно, общей памяти между процессами? Если бы люди могли дать мне краткие идеи, я мог бы пойти и исследовать Google.
(Этот вопрос, вероятно, потребует кого-то знакомого с высокочастотной торговлей)
Ответы:
Я проделал большую работу по поддержке групп HFT в настройках IB и Hedge Fund. Я собираюсь ответить с точки зрения системного администратора, но кое-что из этого применимо и к программированию в таких средах.
Есть несколько вещей, которые обычно ищет работодатель, когда ссылаются на поддержку «Low Latency». Некоторые из них представляют собой вопросы «сырой скорости» (знаете, какой тип карты 10g купить и в какой слот ее вставлять?), Но большинство из них касаются того, чем среда высокочастотной торговли отличается от традиционной Unix среда. Несколько примеров:
Традиционно Unix настроен на поддержку запуска большого количества процессов, не требуя ни одного из них для ресурсов, но в среде HFT вы, вероятно, захотите запустить одно приложение с абсолютным минимумом накладных расходов для переключения контекста и так далее. В качестве небольшого классического примера включение гиперпоточности на процессоре Intel позволяет одновременно запускать больше процессов, но оказывает значительное влияние на производительность на скорость, с которой выполняется каждый отдельный процесс. Как программист, вам также придется посмотреть на стоимость абстракций, таких как многопоточность и RPC, и выяснить, где более монолитное решение - хотя и менее чистое - позволит избежать накладных расходов.
TCP / IP обычно настраивается для предотвращения разрыва соединения и эффективного использования доступной пропускной способности. Если ваша цель состоит в том, чтобы получить максимально возможную задержку в очень быстром канале - вместо того, чтобы получить максимально возможную полосу пропускания в более ограниченном канале - вам нужно будет настроить параметры сетевого стека. Со стороны программирования вы также захотите взглянуть на доступные опции сокетов и выяснить, какие из них имеют настройки по умолчанию, более настроенные на пропускную способность и надежность, чем на снижение задержки.
Как с сетью, так и с хранилищем - вы захотите узнать, как отличить проблему производительности хранилища от проблемы приложения, и узнать, какие шаблоны использования ввода-вывода с наименьшей вероятностью будут влиять на производительность вашей программы (например, Например, узнайте, где сложность использования асинхронного ввода-вывода может окупиться для вас, и каковы недостатки).
И, наконец, еще более болезненно: мы, администраторы Unix, хотим получить как можно больше информации о состоянии сред, которые мы отслеживаем, поэтому нам нравится запускать инструменты, такие как агенты SNMP, инструменты активного мониторинга, такие как Nagios, и инструменты сбора данных, такие как sar (1). В среде, где необходимо полностью свести к минимуму переключение контекста и жестко контролировать использование дискового и сетевого ввода-вывода, мы должны найти правильный компромисс между затратами на мониторинг и производительностью отслеживаемых блоков. Точно так же, какие методы вы используете, которые облегчают кодирование, но снижают производительность?
Наконец, есть другие вещи, которые просто приходят со временем; хитрости и детали, которые вы узнаете с опытом. Но они более специализированы (когда я использую epoll? Почему две модели серверов HP с теоретически идентичными контроллерами PCIe работают так по-разному?), Более привязаны к тому, что использует ваш конкретный магазин, и с большей вероятностью меняются от года к другому ,
источник
В дополнение к превосходному ответу по настройке оборудования / настройки от @jimwise, «linux linux с низкой задержкой» подразумевает:
Многие из этих методов частично совпадают с разработкой игр, что является одной из причин того, почему индустрия финансового программного обеспечения поглощает любых недавно избыточных программистов игр (по крайней мере, до тех пор, пока они не выплатят свои долги по аренде).
Основная потребность заключается в том, чтобы иметь возможность прослушивать очень рыночный поток рыночных данных, таких как цены ценных бумаг (акции, товары, форекс), а затем принимать очень быстрое решение купить / продать / ничего не делать, основываясь на безопасности, цене и текущие авуары.
Конечно, все это тоже может пойти не так .
Поэтому я подробно остановлюсь на точке битовых массивов . Допустим, у нас есть система высокочастотной торговли, которая работает с длинным списком ордеров (купить 5 тысяч IBM, продать 10 тысяч DELL и т. Д.). Допустим, нам нужно быстро определить, все ли заказы выполнены, чтобы мы могли перейти к следующему заданию. В традиционном ОО-программировании это будет выглядеть так:
алгоритмическая сложность этого кода будет O (N), поскольку это линейное сканирование. Давайте посмотрим на профиль производительности с точки зрения доступа к памяти: каждая итерация цикла внутри std :: any_of () будет вызывать o.isFilled (), который является встроенным, поэтому становится доступ к памяти _isFilled, 1 байт (или 4 в зависимости от вашей архитектуры, настроек компилятора и компилятора) в объекте, скажем, всего 128 байт. Таким образом, мы получаем доступ к 1 байту на каждые 128 байтов. Когда мы прочитаем 1 байт, предполагая наихудший случай, мы получим промах кэша данных ЦП. Это вызовет запрос на чтение в ОЗУ, который считывает всю строку из ОЗУ ( см. Здесь для получения дополнительной информации ) просто для считывания 8 бит. Таким образом, профиль доступа к памяти пропорционален N.
Сравните это с:
профиль доступа к памяти этого, при условии, опять же, наихудшего случая, представляет собой ELEMS, деленные на ширину линии ОЗУ (варьируется - может быть двухканальным или трехканальным и т. д.).
Итак, по сути, мы оптимизируем алгоритмы для шаблонов доступа к памяти. Никакой объем оперативной памяти не поможет - это обусловлено размером кэша данных ЦП.
Это помогает?
На YouTube есть отличный рассказ о программировании с малой задержкой (для HFT): https://www.youtube.com/watch?v=NH1Tta7purM
источник
Поскольку я выпустил не одно или два высокочастотных программного обеспечения в производство, я бы сказал самые важные вещи:
Единственный человек, который на самом деле заставляет систему заниматься высокочастотной торговлей, - это ученый, который собирает код на С ++.
Среди используемых знаний
А. Операции сравнения и обмена.
Талантливый ученый будет использовать больше. Он должен найти в недавних новых «шаблонах» тот, который появился в Java первым. Называется шаблон DISRUPTOR. Свертывание LMAX-обмена в Европе объяснило высокочастотному сообществу, что использование потоков в современных процессорах приведет к потере времени обработки при освобождении кэша памяти процессором, если очередь daya не соответствует размеру современного кэша процессора = 64
Поэтому для этого чтения они обнародовали код Java, который позволяет многопоточному процессу правильно использовать аппаратный кэш процессора без разрешения конфликтов. И хороший компьютерный ученый должен найти этот шаблон уже портированным на c ++ или сделать это сам.
Это умение выходить за рамки любой конфигурации администратора. Это в самом сердце высокой частоты сегодня.
И вы будете удивлены, обнаружив, что канал используется ТОЛЬКО ДЛЯ уведомления ядра о поступившем сообщении. Вы можете поместить туда 64-битный номер сообщения - но для контента вы идете в очередь без блокировки CAS. Вызывается асинхронным
select()
вызовом ядра .Как видите, высокая частота - это развивающееся поле. Вы не можете быть просто программистом C ++, чтобы преуспеть.
И когда я говорю «добиться успеха», я имею в виду, что хедж-фонд, на который вы будете работать, БУДЕТ признавать гастроли в виде годовой компенсации сверх того количества, о котором говорят люди и рекрутеры.
Времена простого конструктора / деструктора часто задаваемые вопросы прошли навсегда. И C ++ ... сам мигрировал с новыми компиляторами, чтобы избавить вас от управления памятью и обеспечить отсутствие наследования большой глубины в классах. Пустая трата времени. Код повторного использования парадигмы изменился. Дело не только в том, сколько классов вы создали в полиморфе. Речь идет о подтвержденном времени выполнения кода, который вы можете использовать повторно.
Таким образом, это ваш выбор - пойти на кривую обучения или нет. Он никогда не достигнет знака остановки.
источник