Подтвердить что ты не робот

Производительность языков С++ vs Virtual Machine в высокочастотном финансировании

Я подумал, что вопрос производительности C/С++ vs С#/Java был хорошо преодолен, а это означает, что я бы прочитал достаточно доказательств, чтобы предположить, что языки VM не обязательно медленнее, чем языки "близкого к кремнию". В основном потому, что компилятор JIT может выполнять оптимизацию, которую не могут статически скомпилированные языки.

Однако недавно я получил резюме от парня, который утверждает, что высокочастотная торговля на Java всегда избивается С++ и что он был в ситуации, когда это было так.

Быстрый поиск на сайтах вакансий действительно показывает, что кандидатам HFT нужны знания С++, и посмотрите на Wilmott форум показывает всех практикующих говоря о С++.

Есть ли какая-то особая причина, почему это так? Я бы подумал, что при современном сложном финансовом бизнесе предпочтение будет отдаваться языку виртуальной машины с безопасностью типа, управляемой памятью и богатой библиотекой. Производительность выше. Кроме того, компиляторы JIT становятся все лучше и лучше. Они могут выполнять оптимизацию по мере запуска программы, поэтому вы можете подумать, что они используют эту информацию во время выполнения, чтобы побить производительность неуправляемой программы.

Возможно, эти ребята пишут критические биты на С++ и вызывают их из управляемой среды (P/Invoke и т.д.)? Возможно ли это?

Наконец, есть ли у кого-нибудь опыт с центральным вопросом в этом, поэтому в этом домене неуправляемый код, без сомнения, предпочитается над управляемым?

Насколько я могу судить, ребятам из HFT нужно как можно быстрее реагировать на поступающие рыночные данные, но это необязательно hard realtime требование. Вы хуже, если вы медленны, это точно, но вам не нужно гарантировать определенную скорость для каждого ответа, вам просто нужно быстрое среднее.

ИЗМЕНИТЬ

Правильно, пара хороших ответов до сих пор, но довольно общая (хорошо пробитая земля). Позвольте мне указать, какие программы будут работать с HFT-ребятами.

Основным критерием является отзывчивость. Когда заказ попадает на рынок, вы хотите быть первым, кто сможет реагировать на него. Если вы опаздываете, кто-то еще может взять его перед вами, но у каждой фирмы есть несколько другая стратегия, поэтому вы можете быть в порядке, если одна итерация немного медленная.

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

Эти фирмы, как правило, не имеют ограничений относительно того, насколько дорого стоит оборудование.

4b9b3361

Ответ 1

Во-первых, 1 мс - это вечность в HFT. Если вы считаете, что это не так, тогда было бы неплохо немного почитать о домене. (Это похоже на то, чтобы быть в 100 милях от биржи.) Пропускная способность и латентность глубоко переплетаются, как скажут вам формулы в любом учебнике по элементарной теории массового обслуживания. В тех же формулах будут отображаться значения дрожания (часто преобладает стандартное отклонение задержки очереди ЦП, если сетевая структура права, и у вас недостаточно сконфигурированных ядер).

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

Вам не нужны позиции, если ваша стратегия не предсказывает будущее (ОЧЕНЬ близкое время!!!) (и это, верьте или нет, сделано ОЧЕНЬ успешно). Если вы на расстоянии 1 мс от обмена, то значительная часть ваших заказов не будет выполнена, а то, что вы хотите, будет снято. Скорее всего те, кто выполнил одну ногу, в конечном итоге проиграют или, по крайней мере, не принесут прибыли.

Какова бы ни была ваша стратегия для аргументации, скажем, что она достигает 55%/45% коэффициента выигрыша/убытка. Даже небольшое изменение коэффициента выигрыша/убытка может иметь значительные изменения в прибыльности.

re: "запускать десятки (даже сотни)" кажется " порядком. Даже если смотреть на 20000 тиков в секунду, кажется мало, хотя это может быть среднее значение за весь день для набора инструментов на что он смотрит.

Существует высокая вариабельность ставок, наблюдаемых в любую секунду. Приведу пример. В некоторых из моих тестов я смотрю на 7 внебиржевых акций (CSCO, GOOG, MSFT, EBAY, AAPL, INTC, DELL) в середине дня ставки за секунду для этого потока могут варьироваться от 0 м/с (очень очень редко) до почти почти 2000 котировок и сделок за пик секунды. (см. почему я думаю, что 20000 выше, является низким.)

Я создаю инфраструктуру и программное обеспечение для измерения для этого домена, а номера, о которых мы говорим, составляют 100000 и миллионы в секунду. У меня есть библиотеки производителей/потребительских библиотек С++, которые могут подталкивать почти 5000000 (5 миллионов) сообщений/секунду между производителем и потребителем (32-битные, ядра 2,4 ГГц). Это 64-байтовые сообщения с новой, конструкцией, enqueue, synchronize, со стороны производителя и синхронизировать, деактивировать, касаться каждого байта, запускать виртуальный деструктор, на стороне потребителя, Теперь, по общему признанию, это простой бенчмарк без Socket IO (и сокет IO может быть уродливым), как это было бы в конечных точках контуров конечных точек. Это ВСЕ пользовательские классы синхронизации, которые только синхронизируются, когда пустые, пользовательские распределители, пользовательские блокировки свободных очередей и списки, случайные STL (с пользовательскими распределителями), но чаще всего настраиваемые навязчивые коллекции (из которых у меня есть значительная библиотека). Не раз я давал поставщику на этой арене четверную (и более) пропускную способность без увеличения дозирования на конечных точках сокета.

У меня есть книги OrderBook и OrderBook:: Universe, которые занимают менее 2% для новой, вставки, поиска, частичного заполнения, поиска, второго заполнения, стирания, удаления последовательности при усреднении по 22000 инструментам. Тест повторяется по всем 22000 инструментам последовательно между первым заполнением вставки и последним заполнением, поэтому в нем нет дешевых трюков для кэширования. Операции в одной книге разделены доступом из 22000 разных книг. Это НЕ Кэш-характеристики реальных данных. Реальные данные гораздо более локализованы во времени, и последовательные сделки часто попадают в одну и ту же книгу.

Вся эта работа предполагает тщательное рассмотрение констант и характеристик кеширования в любой из алгоритмических затрат используемых коллекций. (Иногда кажется, что K в KO (n) KO (n * log n) и т.д. И т.д. И т.д. Слишком слабо отклоняются)

Я работаю над инфраструктурной инфраструктурой Marketdata. Невозможно даже подумать об использовании java или управляемой среды для этой работы. И когда вы можете получить такой вид производительности на С++, и я думаю, что с управляемой средой довольно сложно получить миллионную/мп/с производительность). Я не могу представить ни одного из значительных инвестиционных банков или хедж-фондов (для которых зарплата в размере 250000 долларов США первоклассный С++-программист - ничто) не собирается с С++.

Кто-нибудь действительно получает 2000000 +/mps производительность из управляемой среды? Я знаю несколько человек на этой арене, и никто никогда не хвастался об этом мне. И я думаю, что 2 мм в управляемой среде будут иметь некоторые права бахвальства.

Я знаю одного крупного игрока, декодера порядка FIX, выполняющего 12000000 полевых декодов/сек. (CPU 3Ghz) Это С++, и парень, который написал это, бросил вызов кому-либо, чтобы придумать что-то в управляемой среде, которая составляет даже половину этой скорости.

Технологически это интересная область с множеством интересных проблем производительности. Рассмотрите рынок опционов, когда основные изменения безопасности - возможно, будут указаны 6 непогашенных ценовых точек с 3 или 4 разными датами истечения срока действия. Теперь для каждой торговли было, вероятно, 10-20 котировок. Эти котировки могут инициировать изменение цены в опциях. Таким образом, для каждой торговли может быть 100 или 200 изменений котировок опций. Это всего лишь тонна данных, а не большой объем данных, похожий на столкновение с большим адронным коллайдером, но все еще немного сложная задача. Это немного отличается от нажатия клавиш.

Даже споры о ПЛИС продолжаются. Многие люди считают, что хорошо закодированный парсер, работающий на 3GHZ-товаре HW, может побить ПЛИС на 500 МГц. Но даже если крошечный бит медленнее (не говоря о них), системы на базе FPGA могут иметь тенденцию к более жесткому распределению задержки. (Прочитайте "tend" - это не полный текст) Конечно, если у вас есть отличный синтаксический анализатор С++, который вы проталкиваете через Cfront, а затем проталкиваете его через генератор изображений FPGA... Но это еще одна дискуссия...

Ответ 2

Многие из них сводятся к простой разнице между фактом и теорией. Люди развили теории, чтобы объяснить, почему Java должна быть (или, по крайней мере, может быть) быстрее, чем С++. Большинство аргументов имеют мало общего с Java или С++ как таковым, а с динамической и статической компиляцией, причем Java и С++ действительно представляют собой нечто большее, чем примеры двух (хотя, конечно, возможно скомпилировать Java статически или С++ динамически). Большинство из этих людей имеют ориентиры, чтобы "доказать" свои претензии. Когда эти контрольные показатели подробно рассмотрены, быстро становится очевидным, что в довольно многих случаях они принимали весьма экстремальные меры для получения результатов, которые они (например, достаточно оптимизировать число при компиляции Java, но в частности отключить оптимизацию при компиляции С++).

Сравните это с Компьютерная игра Benchmarks Game, где практически любой может подать запись, поэтому весь код, как правило, оптимизирован в разумной степени (и, в некоторых случаях, даже необоснованно). Похоже, довольно ясно, что справедливое число людей относится к этому по существу как к конкуренции, а сторонники каждого языка делают все возможное, чтобы "доказать", что их предпочтительный язык лучше всего. Поскольку любой может представить реализацию любой проблемы, особенно плохое представление мало влияет на общие результаты. В этой ситуации C и С++ появляются как четкие лидеры.

Хуже того, если что-нибудь из этих результатов, вероятно, покажет Java в лучшем свете, чем полностью точно. В частности, кто-то, кто использует C или С++ и действительно заботится о производительности, может (и часто будет) использовать компилятор Intel вместо g++. Это, как правило, дает как минимум 20% -ное улучшение скорости по сравнению с g++.

Изменить (в ответ на пару очков, поднятых jalf, но на самом деле слишком долго, чтобы удобно вставлять комментарии):

  • указатели являются кошмаром писателей-оптимизаторов. Это действительно завышает вещи (совсем) немного. Указатели приводят к возможности сглаживания, что предотвращает определенные оптимизации при определенных обстоятельствах. Тем не менее, inlining предотвращает вредные эффекты большую часть времени (т.е. Компилятор может определить, существует ли сглаживание, а не всегда генерация кода в предположении, что может быть). Даже когда код действительно должен принимать псевдонимы, кеширование минимизирует удары по производительности при этом (т.е. Данные в кеше L1 только мельче, чем данные в регистре). Предотвращение псевдонимов поможет повысить производительность на С++, но не так сильно, как вы думаете.

  • Распределение происходит намного быстрее с сборщиком мусора. Это, безусловно, верно, что распределитель по умолчанию во многих реализациях С++ медленнее, чем обеспечивает большинство (текущих) сборщиков мусора, собираемых сборщиками. Это сбалансировано (по крайней мере, в степени) тем фактом, что распределения в С++, как правило, находятся в стеке, что также быстро, тогда как на языке GC почти все распределения обычно находятся в куче. Хуже того, на управляемом языке вы обычно выделяете пространство для каждого объекта индивидуально, тогда как в С++ вы обычно распределяете пространство для всех объектов в области вместе.

Также верно, что С++ напрямую поддерживает замену распределителей как в глобальном, так и в классовом порядке, поэтому, когда/если скорость распределения действительно является проблемой, ее обычно довольно легко исправить.

В конечном счете, jalf прав: обе эти точки, несомненно, способствуют "управляемым" реализациям. Степень этого улучшения должна быть сохранена в перспективе, хотя: их недостаточно, чтобы динамически скомпилированные реализации выполнялись быстрее по большому количеству кода - даже ориентиры, разработанные с самого начала, чтобы максимально облегчить их.

Edit2: Я вижу, что Джон Харроп попытался вставить свои две (миллиардные доли) центов. Для тех, кто его не знает, Джон был пресловутый тролль и спамер for годы, и, похоже, ищет новую почву для посева сорняков. Я бы попытался ответить на его комментарий подробно, но (как это типично для него) он состоит исключительно из неквалифицированных, неподдерживаемых обобщений, содержащих так мало фактического содержания, что значимый ответ невозможен. О том, что можно сделать, - дать зрителям справедливое предупреждение о том, что он стал известен тем, что был нечестным, корыстолюбивым и проигнорировал его.

Ответ 3

Компилятор JIT теоретически может выполнять множество оптимизаций, да, но как долго вы готовы ждать? Приложение С++ может отнимать часы для компилятора, потому что это происходит в автономном режиме, и пользователь не сидит там, постукивая пальцами и ожидая.

Компилятор JIT должен завершиться в течение нескольких миллисекунд. Итак, что, по вашему мнению, может уйти с самыми сложными оптимизациями?

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

И, конечно же, языки поддаются различным оптимизации. С++ позволяет писать очень сжатый код, практически без накладных расходов памяти, и где много операций высокого уровня в основном бесплатны (скажем, для построения класса).

В С#, с другой стороны, вы теряете хороший кусок памяти. И просто создание экземпляра класса несет хороший кусок служебных данных, так как базовый Object должен быть инициализирован, даже если ваш фактический класс пуст.

С++ позволяет компилятору агрессивно удалять неиспользуемый код. В С#, большая часть его должна быть там, чтобы ее можно было найти с отражением.

С другой стороны, у С# нет указателей, которые являются оптимизирующим кошмаром компилятора. И выделение памяти в управляемом языке намного дешевле, чем в С++.

Есть преимущества в любом случае, поэтому наивно ожидать, что вы сможете получить простой ответ "один или другой". В зависимости от точного исходного кода, компилятор, ОС, аппаратное обеспечение, на котором он работает, один или другой могут быть быстрее. И в зависимости от ваших потребностей необработанная производительность может не быть целью №1. Возможно, вас больше интересует отзывчивость, избегая непредсказуемых ларьков.

В общем, ваш типичный код на С++ будет работать аналогично эквивалентному С# -коду. Иногда быстрее, иногда медленнее, но, вероятно, не имеет большого значения в любом случае.

Но опять же, это зависит от конкретных обстоятельств. И это зависит от того, сколько времени вы готовы потратить на оптимизацию. если вы готовы потратить столько времени, сколько требуется, код на С++ обычно может обеспечить лучшую производительность, чем С#. Это просто требует много работы.

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

Ответ 4

Эти фирмы, как правило, не имеют ограничений относительно того, насколько дорого стоит оборудование.

Если им также все равно, насколько дорого стоит программное обеспечение, я бы подумал, что, конечно, С++ может быть быстрее: например, программист может использовать выделенную или предварительно выделенную память; и/или они могут запускать код в ядре (избегая циклических переходов) или в режиме реального времени O/S и/или тесно связать его с стекю сетевых протоколов.

Ответ 5

Есть причины использовать С++, кроме производительности. Существует ОГРОМНАЯ существующая библиотека кода C и С++. Переписывание всего этого на альтернативных языках было бы непрактичным. Для того, чтобы такие вещи, как P/Invoke, работали правильно, целевой код должен быть разработан для вызова из другого места. Если вам больше не понадобится писать какую-либо оболочку вокруг вещей, выставляющих полностью API C, потому что вы не можете P/Invoke на классы С++.

Наконец, P/Invoke - очень дорогостоящая операция.

JIT-компиляторы становятся все лучше и лучше. Они могут выполнять оптимизацию по мере запуска программы

Да, они могут это сделать. Но вы забываете, что любой компилятор С++ способен выполнять те же самые оптимизации. Конечно, время компиляции будет хуже, но сам факт, что такая оптимизация должна выполняться во время выполнения, - накладные расходы. Бывают случаи, когда управляемые языки могут бить С++ при определенных задачах, но это обычно происходит из-за их моделей памяти, а не из-за оптимизации времени выполнения. Строго говоря, вы могли бы, конечно, иметь такую ​​модель памяти в С++, EDIT: например, С# для обработки строк, /EDIT, но мало программистов на С++ тратят столько времени, чтобы оптимизировать свой код, как это делают парни JIT.

Существуют некоторые проблемы с производительностью, которые наследуют недостаток управляемых языков, а именно дисковый ввод-вывод. Это одноразовая стоимость, но в зависимости от приложения она может быть значительной. Даже с лучшими оптимизаторами вам все равно придется загружать 30 Мбайт + компилятора JIT с диска при запуске программы; в то время как для бинарного С++ для этого размера редко встречается.

Ответ 6

Простым фактом является то, что С++ предназначен для скорости. С#/Java нет.

Возьмите неисчислимые иерархии наследования, эндемичные для этих языков (например, IEnumerable), по сравнению с нулевыми накладными расходами std:: sort или std:: for_each, являющимися общими. С++ необработанная скорость выполнения не обязательно быстрее, но программист может разрабатывать быстрые или нулевые служебные системы. Даже такие вещи, как переполнение буфера - вы не можете отключить их обнаружение. В С++ у вас есть контроль. По сути, С++ - это быстрый язык - вы не платите за то, что не используете. Напротив, в С#, если вы используете, скажем, stackalloc, вы НЕ можете выполнять проверку переполнения буфера. Вы не можете выделять классы в стеке или смежно.

Кроме того, есть все время компиляции, где приложения на С++ могут занимать гораздо больше времени, как для компиляции, так и для разработки.

Ответ 7

Это может быть любопытно, но я смотрел видео пару недель назад, которое может показаться вам интересным: http://ocaml.janestreet.com/?q=node/61

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

Ответ 8

Большая часть нашего кода заканчивается необходимостью запускаться на сетке из 1000 машин.

Я думаю, что эта среда меняет аргумент. Если разница между скоростью выполнения С++ и С# равна 25%, то тогда в игру вступают другие факторы. Когда это выполняется в сетке, не может быть никакого различия в том, как он кодируется, поскольку весь процесс, разложенный на машинах, не может быть проблемой или решен путем распределения или покупки еще нескольких машин. Самая важная проблема и стоимость могут стать "временем выхода на рынок", где С# может оказаться победителем и более быстрым вариантом.

Что быстрее С++ или С#?

С# на шесть месяцев......

Ответ 9

Это не только вопрос языка программирования, аппаратного обеспечения и операционной системы. Лучшая общая производительность, которую вы получите с операционной системой реального времени, языком программирования в реальном времени и эффективным (!) Программированием.

Таким образом, у вас есть довольно много возможностей в выборе операционной системы, а некоторые - в выборе языка. Там C, Realtime Java, Realtime Fortran и несколько других.

Или, может быть, у вас будут лучшие результаты при программировании FPGA/Процессора для устранения стоимости операционной системы.

Самый большой выбор, который вы должны сделать, сколько возможных оптимизаций производительности вы проигнорируете в пользу выбора языка, который упрощает разработку и будет более стабильным, поскольку вы можете делать меньше ошибок, что приведет к более высокой доступности система. Это не следует упускать из виду. У вас нет выигрыша в разработке приложения, которое на 5% быстрее, чем любое другое приложение, которое разбивает каждую точку из-за небольшого количества труднодоступных ошибок.

Ответ 10

В HFT латентность представляет собой большую проблему, связанную с пропускной способностью. Учитывая присущий parallelism источник данных, вы всегда можете бросить больше ядер в проблему, но вы не можете компенсировать время ответа с большим количеством аппаратного обеспечения. Независимо от того, скомпилирован ли язык заранее или "Just-In-Time", сборка мусора может уничтожить вашу задержку. Существуют виртуальные JVM реального времени с гарантированной задержкой сбора мусора. Это довольно новая технология, боль для мелодии и смехотворно дорого, но если у вас есть ресурсы, это можно сделать. Вероятно, в ближайшие годы он станет намного более популярным, так как ранние усыновители финансируют R & D, которые происходят сейчас.

Ответ 11

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

Он не обязательно быстрее, чем Java/С#/..., но он согласован по ходу.

Как и в сети, иногда пропускная способность не так важна, как стабильная латентность.

Ответ 12

Огромная причина предпочесть С++ (или более низкий уровень) в этом случае, кроме того, что уже было сказано, заключается в том, что есть некоторые возможности адаптации для низкого уровня.

Если аппаратная технология изменяется, вы всегда можете зайти в блок __asm { } и использовать ее до того, как языки/компиляторы догонят

Например, по-прежнему нет поддержки SIMD в Java.

Ответ 13

Виртуальные операционные системы (JVM или CLR для .Net) не позволяют структурировать работу по времени, поскольку экземпляры процессов не могут работать на столько потоков, сколько может потребоваться.

Напротив, простой С++ позволяет выполнять параллельные алгоритмы и строить объекты вне критических для времени критических путей выполнения. Это почти все - простое и элегантное. Кроме того, с С++ вы платите только за то, что используете.

Ответ 14

Слон в комнате - это тот факт, что С++ быстрее, чем Java.

Мы все это знаем. Но мы также знаем, что если мы утверждаем это ясно, как я только что сделал, что мы не можем претендовать на участие в значимом дискуссии об этой теме не подлежит обсуждению. Насколько быстрее С++, чем Java для вашего приложения? То есть кольцо дискуссионной темы, но, увы, это всегда будет гипотетическим, если вы не реализуете приложения на обоих языках, в какой момент его там не будет местом для дискуссий.

Вернемся к вашей первой проектной встрече: жесткое требование для вашего проекта - высокая производительность. Все в комнате будут думать "С++" и несколько других скомпилированных языков. Парень в комнате, который предлагает Java или С#, должен будет обосновать его доказательствами (то есть прототипом), а не с гипотезами, а не с утверждениями поставщиков, а не с заявлениями на сайтах сплетен программистов и, конечно же, не с "привет" мировых ".

Как сейчас, вам нужно двигаться вперед с тем, что вы знаете, а не с тем, что гипотетически возможно.

Ответ 15

Nikie писал: "Не могли бы вы объяснить, что вы можете делать с потоками С++, а не с потоками .NET?"

Threading с .Net может выполнять практически все потоки С++, за исключением:

  • Эффективное выполнение COM-инкапсулированного двоичного кода. Например, чувствительные алгоритмы, которые могут быть скрыты от разработчиков приложений. (Может быть актуальным в HFT)
  • Создание нежирных потоков, которые не исчерпывают системные ресурсы узкими строительными блоками - обернутые интерфейсы ОС и синхронизацию и сигнализацию ОС-примитивов. (Крайне актуально для параллельных алгоритмов оптимизации времени работы в HFT)
  • Масштабирование пропускной способности приложения бизнес-процесса 10 или более раз на одном и том же аппаратном обеспечении и с той же задержкой. (Не относится к HFT)
  • Масштабирование на 100 и более раз количества одновременных взаимодействий пользователей на единицу аппаратного обеспечения. (Не относится к HFT)

Использование большего количества ядер процессора не может полностью компенсировать исчерпание системных ресурсов за счет строительных блоков .Net, поскольку больше ядер процессора является гарантией появления конкуренции памяти.