Что быстрее - небезопасный код на C # или сырой C ++ - PullRequest
23 голосов
/ 11 ноября 2008

Я пишу программу обработки изображений для выполнения обработки видеокадров в реальном времени. Это в C # с использованием библиотеки Emgu.CV (C #), которая оборачивает библиотеку DLL OpenCV (неуправляемый C ++). Теперь я должен написать свой собственный специальный алгоритм, и он должен быть максимально быстрым.

Какая реализация алгоритма будет быстрее?

  1. Написание «небезопасной» функции на C #

  2. Добавление функции в библиотеку OpenCV и вызов ее через Emgu.CV

Я предполагаю, что C # unsafe медленнее, потому что он проходит через JIT-компилятор, но будет ли разница существенной?

Edit:

Скомпилировано для .NET 3.5 под VS2008

Ответы [ 10 ]

67 голосов
/ 11 ноября 2008

это должно быть как можно быстрее

Тогда вы задаете не тот вопрос.

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

Используйте в качестве руководства вывод хорошего компилятора C ++ с оптимизацией, потому что он, вероятно, знает некоторые хитрости, которых вы не знаете. Но вы, вероятно, сможете подумать о некоторых улучшениях, потому что C ++ не обязательно передает компилятору всю информацию, которая может быть полезна для оптимизации. Например, C ++ не имеет ограничения по ключевому слову C99. Хотя в этом конкретном случае многие компиляторы C ++ (включая MSVC) теперь поддерживают его, поэтому используйте его там, где это возможно.

Конечно, если вы имеете в виду: «Я хочу, чтобы это было быстро, но не настолько, чтобы выходить за пределы C # или C ++», тогда ответ будет другим; -)

Я бы ожидал, что во многих случаях C # приблизится к производительности похожего на C ++. Конечно, я предполагаю, что программа будет работать достаточно долго, поэтому время, затрачиваемое самой JIT, не имеет значения, но если вы обрабатываете много видео, это кажется вероятным. Но я также ожидаю, что будут некоторые вещи, которые, если вы сделаете их в небезопасном C #, будут намного медленнее, чем аналогичные вещи в C ++. Я не знаю, что это такое, потому что весь мой опыт работы с JIT связан с Java, а не с CLR. Также могут быть вещи, которые медленнее в C ++, например, если ваш алгоритм делает какие-либо вызовы обратно в код C #.

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

Обычно я бы советовал не думать, что это должно быть как можно быстрее. Требования должны быть достижимы, и по определению «как X, насколько это возможно» достижимы только границы. Требования также должны быть проверяемыми, и «насколько возможно, X» не проверяемо, если вы не знаете теоретический максимум. Более дружеское требование: «для этого требуется обрабатывать видеокадры с таким-то разрешением в реальном времени на такой-то быстродействующей ЦП», или «это должно быть быстрее, чем у нашего основного конкурента». Если версия C # делает это с небольшим запасом, чтобы учесть непредвиденные незначительные проблемы в настройке пользователя, то работа выполнена.

6 голосов
/ 11 ноября 2008

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

По моему опыту, использование фиксированной памяти очень помогает. В .NET 4.0 появился новый класс System.IO.UnmanagedMemoryAccessor , который может помочь в будущем.

6 голосов
/ 11 ноября 2008

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

JIT-компилятор может оптимизировать ваш код для платформы, на которой работает код, вместо среднего значения для всех платформ, на которых ваш код может работать, как это делает компилятор C ++. Это то, что в более новых версиях JIT-компилятора становится все лучше и в некоторых случаях может дать преимущество JIT-коду. Таким образом, ответ не так ясен, как вы могли ожидать. Например, новый компилятор горячей точки Java делает это очень хорошо.

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

Я не уверен, что небезопасный C # работает намного быстрее, чем обычный C #. Тебе тоже придется это попробовать.

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

5 голосов
/ 11 ноября 2008

Языки не имеют «скорость». Это зависит от компилятора и кода. Можно написать неэффективный код на любом языке, и умный компилятор сгенерирует почти оптимальный код независимо от языка источника.

Единственный действительно неизбежный фактор производительности между C # и C ++ - это то, что приложения C # должны делать больше при запуске (загружать среду .NET и, возможно, JIT-код), поэтому при прочих равных условиях они будут запускаться немного медленнее. После этого все зависит, и нет фундаментальной причины, по которой один язык всегда должен быть быстрее другого.

Я также не знаю ни одной причины, по которой небезопасный C # должен быть быстрее, чем безопасный. В общем, безопасный - это хорошо, потому что он позволяет компилятору делать более строгие предположения, и поэтому безопасный может быть быстрее. Но опять же, это зависит от кода, который вы компилируете, компилятора, который вы используете, и десятка других факторов.

Короче говоря, откажитесь от идеи, что вы можете измерить производительность языка. Ты не можешь Язык никогда не бывает «быстрым» или медленным ». У него нет скорости.

4 голосов
/ 11 ноября 2008

Если вы собираетесь реализовать свой алгоритм стандартным способом, я думаю, что он не имеет значения. Но у некоторых языков есть привязки к apis или библиотекам, которые могут дать вам нестандартный импульс.

  1. Подумайте, можете ли вы использовать обработку на GPU - nvidia и ati предоставляют платформы CUDA и CTM, и в настоящее время ведется работа по стандартизации от группы khronos (openGL). Предсказание также говорит мне, что amd добавит по крайней мере одно ядро ​​потокового процессора в свои будущие чипы. Поэтому я думаю, что в этой области есть многообещающее.

  2. Попытайтесь выяснить, можете ли вы использовать инструкции SSE, есть библиотеки, большинство из которых на C ++ или C, которые предоставляют удобный API-интерфейс, проверьте сайт Intel на предмет удобных оптимизированных библиотек, которые я помню «Intel Performance Primitives» и « Математическое ядро ​​".

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

3 голосов
/ 18 июля 2013

Это битва, которая будет бушевать вечно. C против C ++ против C # против чего угодно. В C # понятие небезопасно - разблокировать «опасные» операции. то есть использование указателей и возможность приводить к пустым указателям и т. д., как вы можете в C и C ++. Очень опасно и очень мощно! Но победить то, на чем был основан C #.

Вы обнаружите, что в настоящее время Microsoft сделала шаги в направлении повышения производительности, особенно после выпуска .NET, и следующая версия .NET фактически будет поддерживать встроенные методы, как вы можете с C ++. Это повысит производительность в очень специфических ситуациях. Ненавижу, что это будет не функция c #, а неприятный атрибут, который учитывает компилятор - но вы не можете получить все это.

Лично я пишу игру с C # и управляемым DirectX (почему не XNA за рамками этого поста). Я использую небезопасный код в графических ситуациях, что вызывает уклон в сторону того, что говорили другие.

Только из-за того, что доступ к пикселям с GDI ++ слишком медленный, я был вынужден искать альтернативы. Но в целом компилятор c # чертовски хорош, и для сравнения кода (вы можете найти статьи) вы обнаружите, что производительность очень сравнима с c ++. Это не значит, что нет лучшего способа написания кода.

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

Но для бизнеса и большинства вещей в наше время C # является реальным соперником, и пребывание в «безопасной» среде, безусловно, является бонусом.
Выйдя на улицу, вы можете сделать большинство вещей с помощью небезопасного кода, как у меня - и, боже, дошел ли я до крайности! Но стоило ли это того? Возможно нет. Лично я задаюсь вопросом, должен ли я больше думать о критичном по времени коде в C ++ и обо всех объектно-ориентированных безопасных вещах в C #. Но у меня производительность выше, чем я ожидал!

Пока вы осторожны с количеством вызовов, которые вы совершаете, вы можете получить лучшее из обоих миров. Я лично этого избегал, но не знаю, сколько это стоило.

Итак, подход, который я не пробовал, но хотел бы услышать о приключениях, связанных с использованием C ++. NET для разработки библиотеки, - будет ли это быстрее, чем c #, небезопасно для этих особых графических ситуаций? Как бы это сравнить с нативным C ++ скомпилированным кодом? Теперь есть вопрос!

Хм ..

2 голосов
/ 26 ноября 2008

Если вы знаете свою среду и используете хороший компилятор (для обработки видео в Windows Intel C ++ Compiler, вероятно, лучший выбор), C ++ превзойдет C # по нескольким причинам:

  • Среда выполнения C ++ не имеет встроенных проверок времени выполнения (недостатком является то, что у вас есть свободное правление, чтобы взорвать себя). В среде выполнения C # будет проводиться некоторая проверка работоспособности, по крайней мере, на начальном этапе.
  • Компиляторы C ++ созданы для оптимизации кода. Хотя теоретически возможно реализовать компилятор C # JIT, используя все оптимизирующие вудо, которые использует ICC (или GCC), сомнительно, что JIT от Microsoft будет надежно работать лучше. Даже если JIT-компилятор имеет статистику времени выполнения, он все равно не так хорош, как оптимизация на основе профилей в ICC или GCC.
  • Среда C ++ позволяет намного лучше контролировать модель памяти. Если ваше приложение доходит до перегрузки кэша данных или фрагментации кучи, вы действительно оцените дополнительный контроль над распределением. Черт возьми, если вы можете избежать динамического выделения ресурсов, то вам уже гораздо лучше ).

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

1 голос
/ 10 июня 2009

Честно говоря, на каком языке вы пишете, это не так важно, как то, какие алгоритмы вы используете (в любом случае, IMO). Может быть, перейдя к нативному коду, вы могли бы сделать ваше приложение быстрее, но это также может сделать его медленнее - это будет зависеть от компилятора, от того, как написаны программы, какого рода взаимодействие стоит incur, если вы используете смешанную среду и т. д. Вы не можете действительно сказать, не профилируя это. (и, если на то пошло, профилировали ли вы свое приложение? Вы действительно знаете, где оно проводит время? )

Лучший алгоритм полностью не зависит от выбранного вами языка.

1 голос
/ 28 ноября 2008

Я немного опаздываю с ответом, но могу дать вам некоторый анекдотический опыт. У нас были некоторые процедуры умножения матриц, которые изначально были закодированы в C # с использованием указателей и небезопасного кода. Это оказалось узким местом в нашем приложении, и затем мы использовали pinning + P / Invoke для вызова C ++ версии подпрограммы умножения Matrix и получили коэффициент улучшения в 2 раза. Это было некоторое время назад с .NET 1.1, так что теперь все может быть лучше. Как отмечают другие, это ничего не доказывает , но это было интересное упражнение.

Я также согласен с thAAAnos, если ваш алгоритм действительно должен «как можно быстрее» использовать IPL или, если необходимо, рассмотреть реализацию GPU.

0 голосов
/ 11 ноября 2008

Работа на процессоре всегда будет быстрее, чем на виртуальной машине на процессоре. Я не могу поверить, что люди пытаются спорить иначе.

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

Они были медленными, как ад. Мы переписали функциональность, которая была нам нужна в C ++.

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