Производительность управляемого С++ по сравнению с неуправляемым/собственным C++

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

Неуправляемый C++ быстрее, чем управляемый C++? и почему?

Соглашения об Управляемом С++ с CLR вместо ОС и CLR заботятся об управлении памятью, которое упрощает код и вероятно также более эффективно, чем код, написанный "программистом" в неуправляемом C++? или существует некоторая другая причина? При использовании управляемый, как можно затем избежать динамического выделения памяти, которое вызывает хит производительности, если это все очевидно для программиста и обработанное CLR?

Так возвращаясь к моему вопросу, действительно ли управляемый С++ более эффективен с точки зрения скорости, чем неуправляемый C++ и почему?

9
задан bsobaid 10 June 2010 в 16:39
поделиться

5 ответов

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

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

Меня несколько беспокоит утверждение сотни событий каждую миллисекунду. Это ужасно много. Сможете ли вы выполнить ожидаемую обработку на любом языке?

Как разработчик C++ на высокопроизводительных системах, я склонен доверять своей способности профилировать и оптимизировать выдаваемый код. Тем не менее, есть очень высокопроизводительные приложения .NET, где автор приложил все усилия, чтобы не выполнять динамическое выделение памяти внутри критических циклов - в основном, используя выделенные пулы объектов, созданные заранее.

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

3
ответ дан 4 December 2019 в 15:11
поделиться

Здесь есть много хороших ответов, но одним из аспектов управляемого кода, который может дать ему преимущество в долгосрочной перспективе, является анализ времени выполнения. Поскольку код, сгенерированный управляемым компилятором, является промежуточным форматом, фактически выполняемый машинный код может быть оптимизирован на основе фактического использования. Если конкретный набор функций активно используется, JIT'er может локализовать машинный код на одной странице памяти, увеличивая локальность. Если конкретный подвызов повторяется из определенного метода, JIT'er может динамически встраивать его.

Это улучшение по сравнению с неуправляемым кодом, где встраивание необходимо «угадать» заранее, а чрезмерное встраивание вредно, потому что оно увеличивает размер кода и вызывает проблемы с локализацией, которые вызывают (очень затратные по времени) промахи кэша L2 / L1. Эта информация просто недоступна для статического анализа, поэтому это возможно только в среде JIT. Есть хорошая корзина возможных побед от анализа времени выполнения, такого как оптимизированная размотка цикла и т. Д.

Я не утверждаю, что .NET JIT'er настолько умен, насколько это возможно, но я знаю, что слышал о глобальном анализе функций, и я знаю, что Hewlett-Packard и другие компании провели много исследований по анализу времени выполнения.

0
ответ дан 4 December 2019 в 15:11
поделиться

Все зависит от ситуации.

Вещи, которые делают неуправляемый код более быстрым / управляемый код медленнее:

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

Вещи, которые делают управляемый код быстрее / неуправляемый код медленнее:

  • поскольку код преобразуется в машинный код непосредственно перед его использованием , управляемый код может быть оптимизирован для реального процессора (с неуправляемым кодом вы должны ориентироваться на процессор с «минимальной поддержкой»).

И, вероятно, причин гораздо больше.

2
ответ дан 4 December 2019 в 15:11
поделиться

Разве C ++ / CLI не является наполовину интерпретируемым языком, как Java?

Кроме того, разве вчера кто-то не опубликовал исследование, которое показало, что системы GC всегда медленнее, чем системы без GC?

-2
ответ дан 4 December 2019 в 15:11
поделиться

На этот вопрос нет единого ответа. Как общее правило, родной код обычно быстрее, но 1) это не всегда так, 2) иногда разница слишком мала, чтобы о ней заботиться, и 3) то, насколько хорошо написан код, обычно имеет большее значение, чем управляемый или неуправляемый.

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

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

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

При использовании сборщика мусора выделение памяти обычно очень дешево. В типичном (копирующем) сборщике стоимость освобождения памяти зависит в основном от количества объектов, которые были выделены и все еще (по крайней мере, потенциально) используются.

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

9
ответ дан 4 December 2019 в 15:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: