Unix / Linux з низькою затримкою


11

Більшість завдань програмування з низькою затримкою / високою частотою (засновані на специфікаціях завдань), схоже, реалізуються на платформах Unix. У багатьох специфікаціях вони роблять особливий запит для людей із типом досвіду "низької затримки Linux".

Якщо припустити, що це не означає Linux-операційну систему в режимі реального часу, чи могли б люди надати мені допомогу в тому, про що це може йти мова? Я знаю, що ви можете встановити спорідненість CPU до потоків, але я припускаю, що вони просять набагато більше, ніж це.

Налаштування ядра? (хоча я чув, як виробники, як solarflare, все одно виробляють мережеві карти обходу ядра)?

А як щодо DMA чи можливо спільної пам'яті між процесами? Якщо люди могли б дати мені короткі ідеї, я можу піти і зробити дослідження на Google.

(Це питання, ймовірно, потребує когось, знайомого з високочастотною торгівлею)


2
Налаштування ядра - це спосіб зробити операційну систему в режимі реального часу максимально реальною. Закріплення нитки також є обов'язковим. Більше про це можна прочитати в цій статті: coralblocks.com/index.php/2014/04/…
rdalmeida

Крім того, пов'язані з : stackoverflow.com/q/15702601/632951
Pacerier

Відповіді:


26

Я провів досить велику роботу, підтримуючи групи HFT в налаштуваннях IB та Hedge Fund. Я збираюся відповісти з точки зору sysadmin, але щось із цього стосується і програмування в таких середовищах.

Є кілька речей, які роботодавець зазвичай шукає, коли вони посилаються на підтримку "низької затримки". Деякі з них - це "швидкі" запитання (чи знаєте ви, який тип картки 10 г купити, і який слот її поставити?), Але більшість з них стосується способів, якими середовище торгівлі з високою частотою відрізняється від традиційного Середовище Unix. Деякі приклади:

  • Unix традиційно налаштована на підтримку запуску великої кількості процесів без голодування жодного з них за ресурси, але в середовищі HFT ви, ймовірно, захочете запустити одну програму з абсолютним мінімумом накладних витрат для переключення контексту тощо. Як класичний невеликий приклад, увімкнення гіпертетизації процесора Intel дозволяє запускати більше процесів одночасно - але має значний вплив на продуктивність на швидкість, з якою виконується кожен окремий процес. Як програміст, вам також доведеться дивитися на вартість абстракцій, таких як нарізання різьби та RPC, і з'ясувати, де більш монолітне рішення - хоча і менш чисте - уникне накладних витрат.

  • TCP / IP, як правило, налаштовується для запобігання перепадів з'єднання та ефективного використання пропускної здатності. Якщо ваша мета полягає в тому, щоб вивести найменшу можливу затримку з дуже швидкого зв'язку - замість того, щоб отримати максимально можливу пропускну здатність із більш обмеженого зв'язку - вам потрібно буде налаштувати настройку мережевого стеку. З боку програмування ви також хочете розглянути доступні параметри сокетів і визначити, які з них за замовчуванням більше налаштовані на пропускну здатність та надійність, ніж на зменшення затримки.

  • Як і в роботі з мережею, так і зі сховищем даних - ви хочете знати, як визначити проблему продуктивності пам’яті з проблеми програми та дізнатися, які шаблони використання вводу-виводу найменш за все можуть заважати роботі вашої програми (як наприклад, дізнайтеся, де складність використання асинхронного вводу-виводу може окупитися за вас і які недоліки).

  • Нарешті, і ще болісніше: ми, адміністратори Unix, хочемо якомога більше інформації про стан навколишнього середовища, за яким ми відстежуємо, тому ми любимо запускати такі інструменти, як агенти SNMP, активні засоби моніторингу, як Nagios, та засоби збору даних, як sar (1). В умовах, коли контекстні комутатори потрібно мінімізувати та використовувати жорсткий контроль дискового та мережевого вводу-виводу, однак, ми повинні знайти правильний компроміс між витратами на моніторинг та продуктивністю короб, що відслідковуються. Аналогічно, які методи ви використовуєте, які полегшують кодування, але коштують вам продуктивність?

Нарешті, є й інші речі, які просто приходять з часом; хитрощі та деталі, які ви дізнаєтесь із досвідом. Але вони більш спеціалізовані (коли я використовую epoll? Чому дві моделі сервера HP з теоретично однаковими контролерами PCIe працюють так по-різному?), Більш прив'язані до того, що використовується у вашому конкретному магазині, і більше шансів змінитись від року до іншого .


1
Дякую, хоча мене цікавила відповідь на програмування, це було дуже корисно та інформативно.
user997112

5
@ user997112 Це відповідь на програмування. Якщо це не здається таким, продовжуйте читати, поки це не стане :)
Tim Post

15

На додаток до чудової відповіді на налаштування обладнання та налаштування від @jimwise, "Linux з низькою затримкою" означає:

  • C ++ з міркувань детермінізму (несподівана затримка під час запуску GC), доступ до об'єктів низького рівня (введення / виведення, сигнали), мовна потужність (повне використання TMP та STL, тип безпеки).
  • віддайте перевагу швидкості над пам'яттю:> 512 Gb оперативної пам’яті є загальним; бази даних - це пам'ять, кешована наперед або екзотичні продукти NoSQL.
  • вибір алгоритму: якнайшвидший як можливо порівняно з розумним / зрозумілим / розширюваним, наприклад, без блокування, декілька бітових масивів замість властивостей масиву об’єктів-з-bool-властивостями.
  • повне використання засобів ОС, таких як Спільна пам'ять між процесами на різних ядрах.
  • захищений. Програмне забезпечення HFT зазвичай розташоване на фондовій біржі, тому можливості зловмисного програмного забезпечення неприйнятні.

Багато з цих методів перетинаються з розвитком ігор, що є однією з причин, чому галузь фінансового програмного забезпечення поглинає будь-яких нещодавно зайвих програмістів ігор (принаймні, поки вони не сплатять заборгованість за оренду).

Основна потреба полягає в тому, щоб мати можливість прослуховувати дуже високий пропускну здатність потоку ринкових даних, таких як цінність цінних паперів (акції, товари, валюта), а потім дуже швидко приймати рішення про покупку / продаж / не робити нічого, виходячи з цінних паперів, ціна та поточні фонди.

Звичайно, це теж може піти напрочуд неправильно .


Тож я детальніше розробив точку масивів бітів . Скажімо, у нас є високочастотна система торгівлі, яка працює за довгим списком замовлень (Купіть 5k IBM, продайте 10k DELL тощо). Скажімо, нам потрібно швидко визначити, чи всі замовлення заповнені, щоб ми могли перейти до наступного завдання. У традиційному програмуванні OO це буде виглядати так:

class Order {
  bool _isFilled;
  ...
public:
  inline bool isFilled() const { return _isFilled; }
};

std::vector<Order> orders;
bool needToFillMore = std::any_of(orders.begin(), orders.end(), 
  [](const Order & o) { return !o.isFilled(); } );

алгоритмічна складність цього коду буде O (N), оскільки це лінійне сканування. Давайте подивимось на профіль продуктивності з точки зору доступу до пам’яті: кожна ітерація циклу всередині std :: any_of () буде викликати o.isFilled (), який є вкладеним, тому стає доступ до пам'яті _isFilled, 1 байт (або 4 залежно від налаштувань вашої архітектури, компілятора та компілятора) в об'єкті, скажімо, загалом 128 байт. Отже, ми отримуємо доступ до 1 байта кожні 128 байт. Коли ми прочитаємо 1 байт, припускаючи найгірший випадок, отримаємо недолік кешу даних процесора. Це спричинить запит на читання в ОЗУ, який зчитує весь рядок з ОЗУ ( див. Тут для отримання додаткової інформації ) просто для зчитування 8 біт. Отже профіль доступу до пам'яті пропорційний Н.

Порівняйте це з:

const size_t ELEMS = MAX_ORDERS / sizeof (int);
unsigned int ordersFilled[ELEMS];

bool needToFillMore = std::any_of(ordersFilled, &ordersFilled[ELEMS+1],
   [](int packedFilledOrders) { return !(packedOrders == 0xFFFFFFFF); }

профіль доступу до пам’яті цього, припускаючи, в гіршому випадку, ELEMS, поділений на ширину лінії оперативної пам’яті (змінюється - може бути двоканальним або триканальним тощо).

Отже, по суті, ми оптимізуємо алгоритми для моделей доступу до пам'яті. Жодна кількість оперативної пам’яті не допоможе - ця потреба викликає розмір кешу даних процесора.

Чи допомагає це?


На YouTube ви можете чудово розповісти про програмування з низькою затримкою (для HFT): https://www.youtube.com/watch?v=NH1Tta7purM


"декілька бітових масивів замість масиву об'єктів-з-bool-властивостями", що ви маєте на увазі під цим?
користувач997112

1
Я детально розробив приклади та посилання.
JBRWilkinson

Перейшовши на крок далі - замість того, щоб використовувати цілий байт, щоб вказати, заповнено чи ні, - ви можете просто використовувати один біт. Отже, в одному кеш-ліні (64 байти) - ви могли представляти стан 256 порядків. Отже - менше промахів.
кіксвер

Крім того - якщо ви робите лінійне сканування пам'яті - апаратний префетер виконує велику роботу з завантаження даних. За умови, що ви отримуєте доступ до пам'яті послідовно чи швидко, або щось просто. Але якщо ви отримуєте доступ до пам’яті будь-яким непослідовним способом - попередній програвач CPU плутається. Наприклад, двійковий пошук. У цей момент програміст може допомогти процесорові підказками - _mm_prefetch.
квіксвер

-2

Оскільки я не ввів у виробництво не одне чи два високочастотні програми, я б сказав найважливіші речі:

  1. Конфігурація обладнання та системні адміністратори разом з інженерами мереж НЕ визначають хороший результат кількості замовлень, оброблених торговою системою, але вони можуть її знизити великим часом, якщо не знають основ, викладених вище.
  2. Єдина людина, яка насправді змушує систему займатися торгівлею на високих частотах, - це комп'ютер, який збирає код у c ++

    Серед використаних знань є

    A. Порівняйте та обміняйте операції.

    • як CAS використовується в процесорі і як комп'ютер підтримує його для використання в так званій обробці структури без блокування. Або обробка без блоку. Я не буду тут писати цілу книгу. Якщо коротко, компілятор GNU та компілятор Microsoft підтримують безпосереднє використання інструкцій CAS. Це дозволяє вашому коду мати "No.Wair", витягуючи елемент з черги або ставлячи новий у чергу.
  3. Талановитий вчений буде використовувати більше. Він повинен знайти нещодавно нові "візерунки", які з'явилися в Java першими. Називається ДИСРУПТОР-шаблон. Розгортання обміну LMAX в Європі пояснило високочастотному співтовариству, що використання потокових технологій у сучасних процесорах втратить час на обробку кешу пам'яті процесором, якщо черга деня не буде узгоджена з розміром сучасного кеш-пам'яті = 64

    Тож для цього читання вони оприлюднили код Java, який дозволяє багатопотоковому процесу правильно використовувати апаратний кеш процесора без вирішення конфліктів. І хороший комп'ютерний НАРОДНИК знайшов, що цей зразок вже перенесений на c ++ або робити перенос сам.

    Це досвід, що перевищує будь-яку конфігурацію адміністратора. Сьогодні це справжнє серце високої частоти.

  4. Хлопець з інформатики ПОЛУЧИЛИ писати багато C ++ коду не лише для того, щоб допомогти людям із забезпечення якості. Але також
    • валідація у торговців стикається з доведеною досягнутою швидкістю
    • засуджуйте використовувані різні старі технології та викривайте їх власним кодом, щоб показати, що вони не дають хороших результатів
    • писати власний багатокористувацький комунікаційний код c ++ на основі доведеної швидкості pupe / select ядра замість того, щоб знову використовувати старі технології. Наведу приклад u - сучасна бібліотека tcp - це ДВС. А люди, які це зробили, яскраві. Але їхні пріоритети були у сфері порівняння з багатьма мовами. Так. Ви можете краще в c ++. Тож шукайте найвищі показники продуктивності на основі ASYNCHRONOUS select-call. І не варто використовувати для багатьох споживачів кілька виробників - не для HF.
      І ви будете здивовані, дізнавшись, що труба використовується ТІЛЬКИ ДЛЯ повідомлення ядра про прибуте повідомлення. Ви можете поставити туди 64-розрядний номер повідомлення, але за змістом ви перейдете до не заблокованої черги CAS. Запускається асинхронним select()викликом ядра .
    • більше того. Дізнайтеся про присвоєння c ++ спорідненості з потоком, який виконує з'єднання / чергування ваших повідомлень. Ця нитка повинна мати спорідненість до ядра. Ніхто інший не повинен використовувати той самий номер основного процесора.
    • і так далі.

Як бачите - висока частота - це ПОЛІ РОЗВИТКУ. Ви не можете бути просто програмістом на C ++, щоб досягти успіху.

І коли я кажу, що досягти успіху, я маю на увазі, що хедж-фонд, на який ви працюєте, БУДЕ визнавати зусилля подорожей за щорічну компенсацію, що перевищує кількість, про яку говорять люди та рекрутери.

Часи простих FAQ про конструктор / деструктор зникли назавжди. І c ++ ... сама мігрувала з новими компіляторами, щоб позбавити вас від управління пам’яттю та застосувати без наслідування велику глибину в класах. Марна трата часу. Код повторного використання парадигми змінено. Йдеться не лише про те, скільки класів ви склали з поліморфу. Йдеться про прямо підтверджене час виконання коду, який ви можете повторно використовувати.

Тож ваш вибір вийти на криву навчання, чи ні. Він ніколи не потрапить на знак зупинки.


6
Ви можете докласти певних зусиль для написання орфографії та форматування. У своєму нинішньому вигляді цей пост ледве зрозумілий.
CodesInChaos

1
Ви описуєте ситуацію 10 років тому. На сьогодні апаратні рішення легко перевершують чистий C ++, незалежно від того, наскільки оптимізований ваш C ++.
Sjoerd

Для тих, хто хоче знати, що таке апаратні рішення - це здебільшого рішення FPGA, де код насправді спалюється у швидку пам'ять і не змінюється із відновленням так званої пам'яті ROM. Лише для читання
alex p

@alexp Ви точно не знаєте, про що говорите. FPGA - це щось інше, ніж "код, записаний у швидку пам'ять".
Sjoerd
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.