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

Скорость .NET в численных вычислениях

По моему опыту,.NET в 2 - 3 раза медленнее, чем собственный. (Я реализовал L-BFGS для многомерной оптимизации).

Я отслеживал объявления в stackoverflow для http://www.centerspace.net/products/

скорость действительно потрясающая, скорость близка к собственному коду. Как они могут это сделать? Они сказали, что:

Q. Является ли NMath "чистым".NET?

а. Ответ зависит от вашего определения "pure.NET". NMath написан на С#, а также на небольшом управляемом С++ уровне. Однако для лучшей производительности основных операций с линейной алгеброй NMath полагается на встроенную библиотеку ядра Intel Math (входит в состав NMath). Но нет COM-компонентов, а не DLL - только сборки .NET. Кроме того, вся память, выделенная на уровне управляемого С++ и используемая собственным кодом, выделяется из управляемой кучи.

Может кто-нибудь объяснить мне больше?

4b9b3361

Ответ 1

Точка о С++/CLI правильная. Чтобы закончить картину, добавьте еще два интересных момента:

  • Управление памятью .NET(сборщик мусора), очевидно, не является проблемой здесь, поскольку NMath все еще зависит от него

  • Преимущество производительности фактически обеспечивается Intel MKL, которое предлагает реализации, чрезвычайно оптимизированные для многих процессоров. С моей точки зрения, это ключевой момент. Используя прямолинейный, наивный код на C/С++ не обязательно даст вам превосходную производительность по сравнению с С#/. NET, иногда это даже хуже. Однако С++/CLI позволяет использовать все "грязные" варианты оптимизации.

Ответ 2

Как они могут это сделать?

Как и большинство числовых библиотек для .NET, NMath - это нечто большее, чем оболочка из Intel MKL, встроенная в сборку .NET, возможно, путем связывания с С++/CLI для создания смешанная сборка. Вероятно, вы просто сравнили те биты, которые на самом деле не написаны в .NET.

Статьи журнала F #.NET Journal Численные библиотеки: специальные функции, интерполяция и случайные числа (16 марта 2008 г.) и Численные библиотеки: линейная алгебра и спектральные методы (16 апреля 2008 г.) протестировали довольно много функциональности, а NMath - фактически самая медленная из всех коммерческих библиотек. Их PRNG был медленнее всех остальных и на 50% медленнее, чем бесплатная библиотека Math.NET, некоторые базовые функции отсутствовали (например, способность вычислять Gamma(-0.5)) и другие базовые функции (связанные с Gamma функции, которые они действительно обеспечивали) были нарушены, И Extreme Optimization, и Bluebit beat NMath в тесте eigensolver. В то время NMath даже не обеспечивал преобразование Фурье.

Еще более удивительно, что расхождения в производительности иногда были огромными. Самая дорогая коммерческая цифровая библиотека, которую мы тестировали (IMSL), была на 500 × медленнее, чем свободная библиотека FFTW в тесте FFT, и ни одна из библиотек не использовала несколько ядер в то время.

На самом деле именно низкое качество этих библиотек побудило нас коммерциализировать нашу библиотеку F # for Numerics (которая на 100% чистый код F #).

Ответ 3

Я один из ведущих разработчиков ILNumerics. Поэтому я предвзятый, очевидно;) Но мы более раскрыты в отношении наших внутренних дел, поэтому я дам некоторое представление о наших секретах скорости.

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

  • Управляйте своей памятью соответствующим образом! Менеджмент памяти "Наивный" приведет к плохой производительности, поскольку он сильно ухудшает GC, вызывает фрагментацию памяти и ухудшает локальность памяти (следовательно, производительность кэша). В среде сбора мусора, такой как .NET, это сводится к предотвращению частого выделения памяти. В ILNumerics мы реализовали пул памяти с высокой производительностью, чтобы архивировать эту цель (и детерминированное удаление временных массивов, чтобы получить приятный, удобный синтаксис без неуклюжей семантики функций).

  • Используйте parallelism! Это касается как уровня потока parallelism, так и уровня данных parallelism. Несколько ядер используются путем потоковой обработки интенсивных вычислений. На процессорах X86/X64 SIMD/мультимедийные расширения, такие как SSE.XX и AVX, обеспечивают небольшую, но эффективную вектологию. Они не могут быть непосредственно адресованы текущими языками .NET. И это единственная причина, почему MKL может по-прежнему быстрее, чем "чистый".NET-код. (Но решения уже растут.)

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

Обратите внимание, что в этом порядке следует соблюдать эти меры предосторожности! Не имеет смысла заботиться о расширениях SSE или даже об увязке проверки, если узким местом является полоса памяти и процессор проводят большую часть времени, ожидая новых данных. Кроме того, для многих простых операций он даже не планирует вкладывать огромные усилия, чтобы архивировать самый последний крошечный масштаб до максимальной производительности! Рассмотрим общий пример функции LAPACK DAXPY. Он добавляет элементы вектора X к соответствующему элементу другого вектора Y. Если это делается в первый раз, вся память для X и Y должна быть извлечена из основной памяти. Вы ничего не можете с этим поделать. И память - это узкое место! Поэтому, несмотря на то, что добавление в конце выполняется наивным способом в С#

for (int i = 0; i < C.Length; i++) {
    C[i] = X[i] + Y[i]; 
}

или сделать с помощью стратегий векторизации - ему придется ждать памяти!

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

Если вам интересно, вы можете раскрыть свою реализацию L-BFGS? Я буду рад преобразовать его в ILNumerics и опубликовать результаты сравнения, и я уверен, что другие библиотеки, перечисленные здесь, хотели бы следовать. (?)

Ответ 4

Я опубликовал блог статью, посвященный этому вопросу.

Ответ 5

Ключ С++/CLI. Он позволяет скомпилировать код С++ в управляемую сборку .NET.

Ответ 6

Сегодня это отраслевой стандарт для создания смешанных .Net/родных библиотек, чтобы использовать преимущества обеих платформ для оптимизации производительности. Не только NMath, многие коммерческие и бесплатные библиотеки с интерфейсом .net работают так. Например: Math.NET Numerics, dnAnalytics, Extreme Optimization, FinMath и многие другие. Интеграция с MKL чрезвычайно популярна для числовых библиотек .net, и большинство из них просто используют сборку Managed С++ как промежуточный уровень. Но это решение имеет ряд недостатков:

  • Intel MKL является проприетарным программным обеспечением, и это немного дорого. Но некоторые библиотеки, такие как dnAnalytics, обеспечивают бесплатную замену функций MKL чистым кодом .net. Конечно, он намного медленнее, но он бесплатный и полностью функциональный.

  • Это снижает вашу совместимость, требующую наличия мощных управляемых DLL файлов С++ для 32-битного и 64-битного режимов.

  • Для работы с обычными вызовами необходимо выполнить маршалинг, который замедляет выполнение быстрых часто называемых операций, таких как Gamma или NormalCDF.

Последние две проблемы решены в библиотеке RTMath FinMath. Я действительно не знаю, как они это сделали, но они предоставляют единую чистую DLL.net, которая скомпилирована для любой платформы процессора и поддерживает 32-битную и 64-битную. Кроме того, я не видел снижения производительности в отношении MKL, когда мне нужно вызывать NormalCDF миллиарды раз.

Ответ 7

Поскольку (native) Intel MKL выполняет математику, вы на самом деле не выполняете математику в управляемом коде. Вы просто используете диспетчер памяти из .Net, поэтому результаты легко используются кодом .NET.

Ответ 8

Я узнал больше о форме @Darin Dimitrov комментировать его ответ и комментарий @Trevor Misfeldt к комментарию @Darin. Поэтому отправляйте его в качестве ответа для будущих читателей.

NMath использует P/Invoke или С++/CLI для вызова собственных функций библиотеки Intel Math Kernel Library, в которых выполняются наиболее интенсивные вычисления, и именно поэтому так быстро.

Время расходуется в методах декомпозиции внутри Intel MKL. Не требуется копирование данных. Таким образом, не проблема, является ли CLI быстрой или нет. О том, где выполняется выполнение.

Также блог @Paul также хорошо читается. Здесь резюме.

С# быстро, выделение памяти не является. Повторно использовать переменные как параметры ref или out, вместо того, чтобы возвращать новые переменные из методов. Выделение новой переменной требует памяти и замедляет выполнение. @Хаймо Кутчбах объяснил это хорошо.

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

Для многих коротких вычислений вызывать подпрограмму С++/cli из С#, привязывая все указатели к данным, выделенным в управляемом пространстве, а затем вызывать библиотеку Intel, как правило, лучше, чем использовать P/Invoke для вызова библиотеки непосредственно из С#, из-за стоимости маршалинга данных. Как упоминалось в комментариях, Хайме Кутбах в комментариях, однако, для неясных типов нет никакой разницы между С++/CLI и С#. Массивы типов и классов, смягчаемых с помощью blittable, закрепляются вместо скопированных во время маршалинга. Обратитесь к https://msdn.microsoft.com/en-us/library/75dwhxf7(v=vs.110).aspx для списка типов blittable и non-blittable.