Может ли управляемый код выполнять вычисления так же быстро, как и без ошибок? - PullRequest
2 голосов
/ 02 июня 2011

В последнее время меня интересуют разные шахматные движки.Есть много открытых и закрытых источников проекта в этой области.Все они (большинство из них так или иначе) написаны на C / C ++.Это довольно очевидно: у вас сложная вычислительная задача, вы используете C / C ++, поэтому вы получаете мобильность и скорость.Это кажется не слишком умным.

Однако я хотел бы поставить под сомнение эту идею.Когда впервые появился .NET, многие говорили, что идея .NET не будет работать, потому что .NET-программы были обречены быть очень медленными.На самом деле этого не произошло.Кто-то хорошо поработал с ВМ, JIT и т. Д., И сейчас у нас приличная производительность для большинства задач.Но не все.Microsoft никогда не обещала, что .NET подойдет для всех задач, и допущена для некоторых задач, которые вам все равно понадобятся C / C ++.

Возвращаясь к вопросу о вычислительно сложной задаче - есть ли способ написать .NET?Программировать так, чтобы он не выполнял вычисления значительно хуже, чем неуправляемый код, использующий те же алгоритмы?Я был бы счастлив с "постоянной" потерей скорости, но что-то хуже, чем это, будет проблемой.

Что вы думаете?Можем ли мы быть близки по скорости к неуправляемому коду для вычислений в управляемом коде, или неуправляемый код является единственным жизнеспособным ответом?Если мы можем, как?Если мы не можем почему?

Обновление : много хороших отзывов здесь.Я собираюсь принять самый голосующий ответ.

Ответы [ 7 ]

6 голосов
/ 02 июня 2011

"Может" это?Да, конечно.Даже без небезопасного / непроверяемого кода хорошо оптимизированный код .NET может превзойти собственный код.Например, ответ доктора Джона Харропа на эту тему: F # производительность в научных вычислениях

Будет ли это?Обычно нет, если только вы не идете в сторону , чтобы избежать распределения.

2 голосов
/ 02 июня 2011

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

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

Еще одна вещь, которую следует учитывать, - это компилятор. Я имею в виду, что JIT имеет доступ к дополнительной информации о программе и целевом процессоре. Тем не менее, действительно должен каждый раз перекомпилироваться с нуля и делать это при гораздо больших временных ограничениях, чем компилятор C ++, что по своей сути ограничивает возможности. Семантика CLR, например, выделение кучи для каждого объекта каждый раз, также существенно ограничивает его производительность. Управляемое выделение GC достаточно быстрое, но не требует выделения стека и, что более важно, отмены выделения.

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

2 голосов
/ 02 июня 2011

Простой ответ - нет.Некоторым комментаторам ниже: в большинстве случаев это будет медленнее, не всегда.Приложения, требующие большого объема вычислений, где каждая миллисекунда рассчитывает, будут по-прежнему написаны на неуправляемых языках, таких как C, C ++.GC сильно тормозит при сборе.

Например, никто не пишет 3D движки на C # или XNA.Есть некоторые, но ничто не близко к CryEngine или Unreal.

1 голос
/ 02 июня 2011

Короткий ответ да, длинный ответ с достаточным количеством работы.

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

0 голосов
/ 02 июня 2011

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

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

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

Напишите что-нибудь и протестируйте это!

0 голосов
/ 02 июня 2011

Это кажется слишком широким вопросом.

Есть несколько бесплатных подсказок: да, вы можете использовать unsafe, unchecked, массивы Structs и, что наиболее важно, C ++ / CLI.

Никогда не будет совпадения для встраивания C ++, расширения шаблонов во время компиляции (и оптимизации оптимизации) и т. Д.

Но суть в следующем: это зависит от проблемы. Что такое computations в любом случае. У Mono есть отличные расширения для использования SIMD-инструкций, а на Win32 вам нужно будет использовать их как родные. Интероп обманывает.

По моему опыту, портирование игрушечных проектов (таких как парсеры и движок Chess) приведет к разнице в скорости по крайней мере на порядок, независимо от того, насколько вы оптимизируете сторону .NET. Я считаю, что это связано, главным образом, с управлением кучей и служебными процедурами (System.String, System.IO).

В .NET могут быть большие подводные камни (чрезмерное использование Linq, lambdas, случайное использование Enum.HasFlag для выполнения битовой операции ...) и т. Д.

0 голосов
/ 02 июня 2011

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

Давление сборки мусора может быть интересным, но есть и тактика вокруг этого (объединение объектов).

...