Производительность F# в научных вычислениях

Мне любопытно относительно того, как производительность F# выдерживает сравнение с производительностью C++? Я задал подобный вопрос относительно Java, и впечатление, которое я получил, было то, что Java не подходит для тяжелого перемалывания чисел.

Я считал, что F#, как предполагается, более масштабируем и более производителен, но как эта реальная производительность, выдерживает сравнение с C++? конкретные вопросы о текущей реализации:

  • Как хорошо это делает с плавающей точкой?
  • Это позволяет векторные инструкции
  • насколько дружественный это к оптимизирующим компиляторам?
  • Как большой след памяти это имеет? Это позволяет мелкомодульное управление местностью памяти?
  • это имеет способность к процессорам распределенной памяти, например, Cray?
  • какие функции это имеет, который может представлять интерес для вычислительной науки, где тяжелая обработка числа включена?
  • Есть ли фактические реализации научных вычислений, которые используют его?

Спасибо

71
задан Anycorn 2 May 2010 в 02:42
поделиться

9 ответов

  • F # выполняет вычисления с плавающей запятой настолько быстро, насколько это позволяет .NET CLR. Не сильно отличается от C # или других языков .NET.
  • F # не позволяет использовать векторные инструкции, но если в вашей среде CLR есть API для них, у F # не должно возникнуть проблем с его использованием. См., Например, Mono .
  • Насколько мне известно, на данный момент существует только один компилятор F #, поэтому, возможно, следует задать вопрос: «Насколько хорош компилятор F # с точки зрения оптимизации?». В любом случае ответ таков: «потенциально такой же хороший, как компилятор C #, возможно, на данный момент немного хуже». Обратите внимание, что F # отличается от, например, C # поддерживает встраивание во время компиляции, что потенциально позволяет создавать более эффективный код, основанный на обобщениях.
  • Отпечатки памяти программ на F # аналогичны таковым в других языках .NET. Степень контроля над распределением и сборкой мусора такая же, как и в других языках .NET.
  • Я не знаю о поддержке распределенной памяти.
  • В F # есть очень хорошие примитивы для работы с плоскими структурами данных, например массивы и списки. Взгляните, например, на содержимое модуля Array: map, map2, mapi, iter, fold, zip ... Массивы популярны в научных вычислениях, я думаю, из-за их изначально хороших свойств локализации памяти.
  • Для пакетов научных вычислений, использующих F #, вы можете посмотреть, что делает Джон Харроп.
40
ответ дан 24 November 2019 в 12:53
поделиться

Я не думаю, что вы, к сожалению, найдете много достоверной информации. F # по-прежнему является очень новым языком, поэтому, даже если бы он идеально подходил для рабочих нагрузок с высокой производительностью, все равно не было бы так много людей со значительным опытом, о которых можно было бы отчитываться. Кроме того, очень сложно точно измерить производительность и обобщить результаты микротестов. Даже внутри C ++ вы можете увидеть кардинальные различия между компиляторами - вам интересно, может ли F # конкурировать с любым компилятором C ++ или с гипотетическим «наилучшим возможным» исполняемым файлом C ++?

Что касается конкретных тестов производительности C ++ , вот некоторые, возможно, релевантные ссылки: O'Caml vs. F #: QR-разложение ; F # против неуправляемого C ++ для параллельных чисел . Обратите внимание, что как автор материалов, относящихся к F #, и как поставщик инструментов F #, автор лично заинтересован в успехе F #, поэтому относитесь к этим утверждениям с долей скептицизма.

Я думаю, можно с уверенностью сказать, что в некоторых приложениях F # будет конкурентоспособным по времени выполнения, а в некоторых других - нет. F #, вероятно, в большинстве случаев потребует больше памяти. Конечно, конечная производительность также будет сильно зависеть от навыков программиста - я думаю, что F # почти наверняка будет более продуктивным языком программирования для умеренно компетентного программиста. Более того, я думаю, что на данный момент CLR в Windows работает лучше, чем Mono, в большинстве операционных систем для большинства задач, что также может повлиять на ваши решения.Конечно, поскольку F #, вероятно, легче распараллелить, чем C ++, это также будет зависеть от типа оборудования, на котором вы планируете работать.

В конечном счете, я думаю, что единственный способ действительно ответить на этот вопрос - написать код на F # и C ++, представляющий тип вычислений, которые вы хотите выполнить, и сравнить их.

7
ответ дан 24 November 2019 в 12:53
поделиться

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

F # является производным от OCaml. Я был удивлен, узнав, что OCaml часто используется в финансовом мире, где производительность обработки чисел очень важна. Еще я был удивлен, узнав, что OCaml - один из самых быстрых языков, с производительностью на уровне самых быстрых компиляторов C и C ++.

F # построен на CLR . В среде CLR код выражается в виде байт-кода, называемого общим промежуточным языком. Таким образом, он использует возможности оптимизации JIT и имеет производительность, сопоставимую с C # (но не обязательно C ++), если код написан хорошо.

Код CIL может быть скомпилирован в собственный код на отдельном этапе перед запуском во время выполнения с помощью генератора собственных изображений (NGEN). Это ускоряет все последующие запуски программного обеспечения, поскольку компиляция CIL-to-native больше не требуется.

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

16
ответ дан 24 November 2019 в 12:53
поделиться

Это зависит от того, какие научные вычисления вы выполняете.

Если вы выполняете традиционные тяжелые вычисления , например линейная алгебра, различные оптимизации, то вы не должны помещать свой код в .Net framework, по крайней мере, не подходит в F #. Поскольку это находится на уровне алгоритма, большинство алгоритмов должны быть написаны на императивных языках, чтобы иметь хорошую производительность по времени выполнения и использованию памяти. Другие упоминали параллельность, я должен сказать, что это, вероятно, бесполезно, когда вы делаете вещи низкого уровня, такие как параллельная реализация SVD. Поскольку, когда вы знаете, как распараллеливать SVD, вы просто не будете использовать языки высокого уровня, Fortran, C или модифицированный C (например, cilk ) - ваши друзья.

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

Как отмечали другие, .Net хорошо поддерживает Platform Invoke, на самом деле довольно много проектов внутри MS используют .Net и P / Invoke вместе, чтобы улучшить производительность в узком месте.

9
ответ дан 24 November 2019 в 12:53
поделиться

Насколько мне известно, большинство научных вычислений все еще выполнялось на ФОРТРАНЕ. Он по-прежнему быстрее, чем что-либо еще, для задач линейной алгебры - ни Java, ни C, ни C ++, ни C #, ни F #. LINPACK хорошо оптимизирован.

Но замечание о том, что «ваш пробег может отличаться», справедливо для всех тестов. Общие заявления (кроме моего) редко бывают правдой.

1
ответ дан 24 November 2019 в 12:53
поделиться

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

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

Что касается распределенных вычислений, вы можете использовать любой фреймворк для распределенных вычислений, доступный для платформы . NET. Существует проект MPI.NET, который хорошо работает с F#, но вы также можете использовать DryadLINQ, который является проектом MSR.

42
ответ дан 24 November 2019 в 12:53
поделиться

Вот два примера, которыми я могу поделиться:

  1. Умножение матриц: У меня есть сообщение в блоге , в котором сравниваются различные реализации умножения матриц. .

  2. LBFGS

У меня есть крупномасштабный решатель логистической регрессии, использующий оптимизацию LBFGS, которая написана на C ++. Реализация хорошо настроена. Я изменил код на C ++ / CLI, т.е. скомпилировал код в .Net. Версия .Net в 3-5 раз медленнее, чем наивная, скомпилированная на разных наборах данных.Если вы кодируете LBFGS на F #, производительность не может быть лучше, чем C ++ / CLI или C # (но будет очень близко).

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

4
ответ дан 24 November 2019 в 12:53
поделиться

Мне любопытно, как производительность F # сравнивается с производительностью C ++?

Очень сильно варьируется в зависимости от приложения. Если вы широко используете сложные структуры данных в многопоточной программе, то F #, вероятно, станет большим выигрышем. Если большую часть вашего времени вы проводите в тесных числовых циклах, изменяющих массивы, то C ++ может быть в 2–3 раза быстрее.

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

Я читал, что F # должен быть более масштабируемым и более производительным, но как эта реальная производительность по сравнению с C ++?

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

Это точно такое же преимущество, которое С ++ имел над Фортраном, а Фортран, конечно, имел над рукописным ассемблером.

Пример: QR-разложение Это основной численный метод линейной алгебры, предоставляемый такими библиотеками, как LAPACK. Эталонная реализация LAPACK - это 2077 строк Фортрана. Я написал реализацию F # менее чем в 80 строках кода, которая обеспечивает такой же уровень производительности. Но эталонная реализация не является быстрой: реализации, настроенные производителем, такие как Intel Math Kernel Library (MKL), часто в 10 раз быстрее. Примечательно, что мне удалось оптимизировать мой код F # , превосходящий производительность реализации Intel, работающей на оборудовании Intel, при этом мой код не превышает 150 строк и является полностью универсальным (он может обрабатывать одинарную и двойную точность, а также сложные и даже символьные матрицы!): для высоких тонких матриц мой код F # до 3 раз быстрее, чем Intel MKL.

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

Насколько хорошо он работает с числами с плавающей запятой?

Производительность аналогична ANSI C, но некоторые функции (например, режимы округления) недоступны в .NET.

Разрешены ли векторные инструкции

Нет.

Насколько он дружелюбен по отношению к оптимизации компиляторов?

Этот вопрос не имеет смысла: F # - это проприетарный язык .NET от Microsoft с одним компилятором.

Насколько велик объем памяти?

Пустое приложение использует здесь 1,3 МБ.

Позволяет ли он детально контролировать расположение памяти?

Лучше, чем большинство языков, безопасных для памяти, но не так хорошо, как C. Например, вы можете распаковать произвольные структуры данных в F #, представив их как «структуры».

есть ли у него емкость для процессоров с распределенной памятью, например Cray?

Зависит от того, что вы подразумеваете под «емкостью для». Если вы можете запустить .NET на этом Cray, вы можете использовать передачу сообщений на F # (как и в следующем языке), но F # предназначен в первую очередь для настольных многоядерных машин x86.

Какие у него есть функции, которые могут быть интересны для вычислительной науки, где задействована тяжелая обработка чисел?

Безопасность памяти означает, что вы не получаете ошибок сегментации и нарушений доступа. Поддержка параллелизма в .NET 4 хорошая. Возможность выполнять код на лету через интерактивный сеанс F # в Visual Studio 2010 чрезвычайно полезна для интерактивных технических вычислений.

Существуют ли реальные реализации научных вычислений, которые его используют?

Наши коммерческие продукты для научных вычислений на F # уже имеют сотни пользователей.

Однако ваша линия вопросов указывает на то, что вы думаете о научных вычислениях как о высокопроизводительных вычислениях (например, Cray), а не как о интерактивных технических вычислениях (например, MATLAB, Mathematica). F # предназначен для последнего.

62
ответ дан 24 November 2019 в 12:53
поделиться

Во-первых, C значительно быстрее, чем C++. Так что если вам нужно так много скорости, вы должны сделать lib и т.д. на C.

Что касается F#, большинство бенчмарков используют Mono, который до 2 * медленнее MS CLR из-за частичного использования boehm GC (у них есть новый GC и LVVM, но они все еще незрелые, не поддерживают generics и т.д.).

.Сами языки NEt компилируются в IR (CIL), который компилирует нативный код так же эффективно, как и C++. Есть один набор проблем, которым страдает большинство языков GC, и это большое количество изменяемых записей (это включает C++ .NET, как упоминалось выше). И есть определенный набор научных проблем, которые требуют этого, эти проблемы, когда это необходимо, вероятно, должны использовать родную библиотеку или использовать паттерн Flyweight для повторного использования объектов из пула (что уменьшает количество записей). Причина в том, что в .NET CLR существует барьер записи, когда при обновлении поля ссылки (включая ячейку) он устанавливает бит в таблице, говорящий, что эта таблица изменена. Если ваш код состоит из множества таких записей, он будет страдать.

С другой стороны, приложения .NET, такие как C#, использующие много статического кода, структур и ref/out на структурах, могут обеспечить производительность, подобную C, но очень трудно писать такой код или поддерживать его (как C).

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

Что касается плавающей точки, вам следует использовать альтернативную либу (т.е. .Net), а не oCaml из-за ее медлительности. C/C++ позволяет быстрее работать с более низкой точностью, чего oCaml не делает по умолчанию.

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

1
ответ дан 24 November 2019 в 12:53
поделиться
Другие вопросы по тегам:

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