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


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

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

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

спасибо

10 69

10 ответов:

  • F# выполняет вычисления с плавающей запятой так быстро, как это позволяет среда CLR .NET. Не сильно отличается от C# или других языков .NET.
  • F# сам по себе не разрешает векторные инструкции, но если у вашей среды CLR есть API для них, F# не должен иметь проблем с его использованием. См., например,моно.
  • насколько я знаю, на данный момент существует только один компилятор F#, поэтому, возможно, вопрос должен быть "насколько хорош компилятор F#, когда дело доходит до оптимизация?". Ответ в любом случае "потенциально так хорошо, как компилятор C#, вероятно, немного хуже на данный момент". Обратите внимание, что F# отличается от, например, C# своей поддержкой встраивания во время компиляции, что потенциально позволяет более эффективный код, который полагается на дженерики.
  • отпечатки ног памяти программ F# похожи на другие языки .NET. Объем контроля над распределением и сборкой мусора такой же, как и в других .NET языки.
  • Я не знаю о поддержке распределенной памяти.
  • F# имеет очень хорошие примитивы для работы с плоскими структурами данных, например, массивами и списками. Взгляните, например, на содержание модуля массив: карта, карта2, мапи, ИТЭР, сложите, застежка-молния... Массивы популярны в научных вычислениях, я думаю, из-за их по своей сути хороших свойств локальности памяти.
  • для научных вычислительных пакетов, использующих F#, вы можете посмотреть, что такое Джон Харроп делающий.

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

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

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

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

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

это точно такое же преимущество, которое C++ имел над Fortran и Fortran имел над рукописным ассемблером, конечно.

Case study: QR декомпозиция это основной численный метод из линейной алгебры, предоставляемый библиотеками, такими как LAPACK. Эталонная реализация LAPACK - это 2 077 строк Fortran. Я написал реализация F# в рамках 80 строки кода, который достигает того же уровня производительности. Но эталонная реализация не является быстрой: настроенные поставщиком реализации, такие как математическая библиотека ядра Intel (MKL), часто в 10 раз быстрее. Замечательно, мне удалось оптимизировать мой F# код хорошо дальше производительность реализации Intel, работающей на оборудовании Intel, сохраняя при этом мой код под 150 строками кода и полностью общий (он может обрабатывать одинарную и двойную точность, а также сложные и даже символические матрицы!): для высоких тонкие матрицы мой код F# до 3× быстрее, чем Intel MKL.

насколько хорошо он делает с плавающей запятой?

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

позволяет ли это векторные инструкции

нет.

насколько это удобно для оптимизации компиляторов?

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

насколько большой отпечаток ноги памяти у него есть?

пустое приложение использует 1,3 мб здесь.

позволяет ли он мелкозернистый контроль над локальностью памяти?

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

имеет ли он емкость для распределенной памяти процессоры, например, Крэй?

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  2. LBFGS

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

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

Если я скажу "спросите еще раз через 2-3 года", я думаю, что полностью отвечу на ваш вопрос: -)

во-первых, не ожидайте, что F# будет отличаться от C# perf-wise, если вы не делаете некоторые запутанные рекурсии специально, и я бы предположил, что вы не так, поскольку вы спросили о цифрах.

с плавающей запятой это должно быть лучше, чем Java, так как CLR не стремится к кросс-платформенной однородности, что означает, что JIT будет идти до 80-бит, когда это возможно. С другой стороны ты не контролируйте это за пределами просмотра количества переменных, чтобы убедиться, что достаточно регистров FP.

векторно, если вы кричите достаточно громко, возможно, что-то произойдет через 2-3 года, так как Direct3D все равно входит в .NET как общий API, а код C#, выполненный в XNA, работает на Xbox whihc как можно ближе к голому металлу, который вы можете получить с помощью CLR. Это по-прежнему означает, что вам нужно будет сделать это какой-то промежуточный код самостоятельно.

Так что не ожидайте CUDA или даже возможность просто связать NVIDIA либс и вперед. Вам бы гораздо больше повезло попробовать этот подход с Haskell, если по какой-то причине вам действительно нужен "функциональный" язык, так как Haskell был разработан, чтобы быть дружественным к связыванию из чистой необходимости.

моно.Simd уже упоминался, и хотя он должен быть обратно переносимым для CLR, это может быть довольно большая работа, чтобы фактически сделать это.

там довольно много кода социальная.в MSDN проводки при использовании SSE3 в .NET, vith C++ / CLI и C#, приходите блитирование массив, впрыскивать код SSE3 для перфорации и т. д.

там были какие-то разговоры о работе Сесил на скомпилированном C#, чтобы извлечь части в HLSL, скомпилировать в шейдеры и связать код клея, чтобы запланировать его (CUDA все равно делает эквивалент), но я не думаю, что из этого выйдет что-то запускаемое.

вещь, которая может стоить больше для вас, если вы хотите попробовать что-то в ближайшее время PhysX.Net на codeplex. Не ожидайте, что он просто распакует и творите волшебство. Тем не менее, у ih в настоящее время есть активный автор, и код является обычным C++ и C++/CLI, и yopu, вероятно, может получить некоторую помощь от автора, если вы хотите вдаваться в подробности и, возможно, использовать аналогичный подход для CUDA. Для полной скорости CUDA вам все равно нужно скомпилировать свои собственные ядра, а затем просто взаимодействовать с .NET, поэтому чем проще эта часть идет, тем счастливее вы будете.

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

Ну и если у вас есть бюджет йо может дать, что Пси Лямбда взгляд (KappaCUDAnet-это часть .NET). По-видимому, они собираются поднять цены в ноябре (если это не трюк продаж: -)

насколько я знаю, большинство научных вычислений все еще делалось на Фортране. Это все еще быстрее, чем что - либо еще для задач линейной алгебры-не Java, не C, не c++, не C#, не F#. На тесте Linpack хорошо оптимизирован.

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

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

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

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

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

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

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

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