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

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

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

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

спасибо

10 ответов


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

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

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

тематическое исследование: 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.

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

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

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

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

нет.

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

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

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

пустое приложение использует 1.3 Mb здесь.

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

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

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

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

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

безопасность памяти означает, что вы не получаете ошибок сегментации и нарушение прав доступа. Поддержка параллелизма в .NET 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, prepossessing, занимаюсь графикой, и т. д. Для этих задач F# действительно мощный, для его краткости, функциональности,безопасности, прост в параллели и т. д.

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


Я не думаю, что вы найдете много достоверной информации, к сожалению. F# по-прежнему является очень новым языком, поэтому, даже если бы он идеально подходил для работы с большими рабочими нагрузками, все равно не было бы так много людей со значительным опытом. Кроме того, производительность очень трудно точно определить и microbenchmarks сложно обобщать. Даже в 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 - 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 был разработан, чтобы быть дружественным к связыванию из чистой необходимости.

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

там, s довольно некоторый код в социальная.в MSDN проводки при использовании SSE3 в .NET, vith C++ / CLI и c#, приходите массив blitting, впрыскивая код SSE3 для perf etc.

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

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

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

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


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

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


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

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

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

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

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

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

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