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

Что быстрее - С# небезопасный код или необработанный С++

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

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

  • Написание "небезопасной" функции в С#

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

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

Edit:

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

4b9b3361

Ответ 1

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

Тогда вы задаете неправильный вопрос.

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

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

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

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

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

Обычно я бы посоветовал не начинать думать, "это должно быть как можно быстрее". Требования должны быть достижимыми и по определению "по мере возможности Х" достижимы только на границе. Требования также должны быть проверяемыми, а "как можно X" не поддаются проверке, если вы не знаете теоретический максимум. Более дружественным требованием является "для этого необходимо обработать видеофрагменты такого-то разрешения в реальном времени на таком-то и таком высокоскоростном процессоре", или "это должно быть быстрее, чем наш основной продукт конкурента". Если версия С# делает это, немного сэкономив для учета неожиданных незначительных проблем в настройке пользователя, выполните задание.

Ответ 2

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

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

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

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

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

Ответ 3

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

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

Ответ 4

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

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

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

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

Ответ 5

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

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

  • Попытайтесь выяснить, можете ли вы использовать SSE-инструкции, есть библиотеки почти на С++ или C, которые предоставляют удобную apis, проверяют сайт Intel на удобные оптимизированные библиотеки. Я действительно помню "Intel Performance Primitives" и "Math Kernel".

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

Ответ 6

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

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

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

Ответ 7

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

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

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

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

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

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

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

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

Хм..

Ответ 8

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

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

Ответ 9

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

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

Ответ 10

Запуск на CPU всегда будет быстрее, чем запуск на VM на CPU. Я не могу поверить, что люди пытаются спорить иначе.

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

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