73

F#のパフォーマンスとC ++のパフォーマンスの比較に興味がありますか?Javaについても同様の質問をしましたが、Javaは大量の処理には適していないという印象を受けました。

F#はよりスケーラブルでパフォーマンスが高いと思われることを読みましたが、この実際のパフォーマンスはC ++とどのように比較されますか?現在の実装に関する具体的な質問は次のとおりです。

  • 浮動小数点はどれくらいうまく機能しますか?
  • ベクトル命令を許可しますか
  • コンパイラーの最適化に対してどれほど友好的ですか?
  • メモリーフットプリントはどれくらいの大きさですか?メモリの局所性をきめ細かく制御できますか?
  • Crayなどの分散メモリプロセッサ用の容量はありますか?
  • 大量の処理が含まれる計算科学にとって興味深い機能は何ですか?
  • それを使用する実際の科学計算の実装はありますか?

ありがとう

4

10 に答える 10

65

F#のパフォーマンスとC ++のパフォーマンスの比較に興味がありますか?

アプリケーションによって大きく異なります。マルチスレッドプログラムで高度なデータ構造を多用している場合は、F#が大きなメリットになる可能性があります。ほとんどの時間が配列を変更するタイトな数値ループに費やされている場合、C ++は2〜3倍高速になる可能性があります。

ケーススタディ:レイトレーサーここでの私のベンチマークでは、階層的なカリングにツリーを使用し、光線と球の交差コードを数値化して出力画像を生成します。このベンチマークは数年前のものであり、C ++コードは何十年にもわたって改善され、何十万人もの人々に読まれてきました。MicrosoftのDonSymeは、MSVCでコンパイルし、OpenMPを使用して並列化した場合、最速のC ++コードよりもわずかに高速なF#実装を作成することができました。

F#はよりスケーラブルでパフォーマンスが高いと思われることを読みましたが、この実際のパフォーマンスはC ++とどのように比較されますか?

F#を使用すると、C ++よりもコードの開発がはるかに簡単かつ高速になります。これは、メンテナンスだけでなく最適化にも当てはまります。したがって、プログラムの最適化を開始するときに、C ++の代わりにF#を使用すると、同じ量の作業でパフォーマンスが大幅に向上します。ただし、F#は高級言語であるため、パフォーマンスの上限が低くなります。したがって、最適化に無限の時間を費やす場合は、理論的には、常にC++でより高速なコードを生成できるはずです。

もちろん、これは、C ++がFortranに対して、Fortranが手書きのアセンブラーに対して持っていたのとまったく同じ利点です。

ケーススタディ:QR分解これは、LAPACKなどのライブラリによって提供される線形代数からの基本的な数値手法です。参照LAPACK実装は、Fortranの2,077行です。同じレベルのパフォーマンスを実現するF#実装を80行未満のコードで記述しました。ただし、リファレンス実装は高速ではありません。IntelのMath Kernel Library(MKL)のようなベンダーが調整した実装は、多くの場合10倍高速です。驚くべきことに、私はF#コードを、インテルハードウェアで実行されているインテルの実装のパフォーマンスをはるかに超えて最適化することができました。その一方で、コードは150行未満のコードであり、完全に汎用的です(単精度、倍精度、複雑なシンボリックマトリックスも処理できます)。背の高い薄いマトリックスの場合、私のF#コードはIntelMKLよりも最大3倍高速です。

このケーススタディの教訓は、F#がベンダーが調整したライブラリよりも高速であることを期待する必要があるということではなく、Intelのような専門家でさえ、低レベルの言語のみを使用する場合、生産的な高レベルの最適化を見逃すことに注意してください。Intelの数値最適化の専門家は、並列処理を十分に活用できなかったのではないかと思います。なぜなら、彼らのツールは並列処理を非常に面倒にするのに対し、F#は並列処理を簡単にするからです。

浮動小数点はどれくらいうまく機能しますか?

パフォーマンスはANSICに似ていますが、一部の機能(丸めモードなど)は.NETからは利用できません。

ベクトル命令を許可しますか

いいえ。

コンパイラーの最適化に対してどれほど友好的ですか?

この質問は意味がありません。F#は、単一のコンパイラを備えたMicrosoft独自の.NET言語です。

メモリーフットプリントはどれくらいの大きさですか?

空のアプリケーションはここで1.3Mbを使用します。

メモリの局所性をきめ細かく制御できますか?

ほとんどのメモリセーフ言語よりは優れていますが、Cほどではありません。たとえば、F#で任意のデータ構造を「構造体」として表すことにより、ボックスを解除できます。

Crayなどの分散メモリプロセッサ用の容量はありますか?

「容量」の意味によって異なります。そのCrayで.NETを実行できる場合は、(次の言語と同じように)F#でメッセージパッシングを使用できますが、F#は主にデスクトップマルチコアx86マシンを対象としています。

大量の処理が含まれる計算科学にとって興味深い機能は何ですか?

メモリの安全性とは、セグメンテーション違反やアクセス違反が発生しないことを意味します。.NET4での並列処理のサポートは良好です。Visual Studio 2010のF#インタラクティブセッションを介してオンザフライでコードを実行する機能は、インタラクティブなテクニカルコンピューティングに非常に役立ちます。

それを使用する実際の科学計算の実装はありますか?

F#の科学計算用の商用製品には、すでに数百人のユーザーがいます。

しかし、あなたの質問の行は、科学計算をインタラクティブな技術計算(MATLAB、Mathematicaなど)ではなく、高性能計算(Crayなど)と考えていることを示しています。F#は後者を対象としています。

于 2010-05-10T00:45:51.137 に答える
44

他の人が言ったことに加えて、F#について1つの重要なポイントがあり、それは並列処理です。通常のF#コードのパフォーマンスはCLRによって決定されますが、F#からLAPACKを使用できる場合や、プロジェクトの一部としてC ++/CLIを使用してネイティブ呼び出しを行うことができる場合があります。

ただし、適切に設計された機能プログラムは、並列化がはるかに簡単になる傾向があります。つまり、科学計算を行っている場合に確実に利用できるマルチコアCPUを使用することでパフォーマンスを簡単に得ることができます。関連するリンクは次のとおりです。

分散コンピューティングに関しては、.NETプラットフォームで利用可能な任意の分散コンピューティングフレームワークを使用できます。F#でうまく機能するMPI.NETプロジェクトがありますが、MSRプロジェクトであるDryadLINQを使用することもできる場合があります。

于 2010-05-02T09:48:47.050 に答える
41
  • F#は、.NETCLRで許可されている速度で浮動小数点の計算を実行します。C#や他の.NET言語とあまり違いはありません。
  • F#はそれ自体ではベクトル命令を許可しませんが、CLRにこれらのAPIがある場合、F#はそれを使用しても問題はありません。たとえば、Monoを参照してください。
  • 私の知る限り、現時点ではF#コンパイラは1つしかないので、「最適化に関してF#コンパイラはどれだけ優れているか」という質問が必要かもしれません。いずれにせよ、答えは「C#コンパイラと同じくらい良い可能性があり、現時点ではおそらく少し悪い」です。F#は、コンパイル時のインライン化のサポートがC#などとは異なることに注意してください。これにより、ジェネリックスに依存するより効率的なコードが可能になる可能性があります。
  • F#プログラムのメモリフットプリントは、他の.NET言語のものと似ています。割り当てとガベージコレクションを制御できる量は、他の.NET言語と同じです。
  • 分散メモリのサポートについてはわかりません。
  • F#には、配列やリストなどのフラットなデータ構造を処理するための非常に優れたプリミティブがあります。たとえば、配列モジュールのコンテンツを見てください:map、map2、mapi、iter、fold、zip ...配列は、本質的に優れたメモリローカリティプロパティのために、科学計算で人気があります。
  • F#を使用した科学計算パッケージの場合、JonHarropが行っていることを確認することをお勧めします。
于 2010-05-05T15:29:43.400 に答える
16

すべての言語/パフォーマンスの比較と同様に、マイレージはコーディングの程度に大きく依存します。

F#はOCamlの派生物です。OCamlが金融の世界でよく使われていることに驚きました。金融の世界では、数値計算のパフォーマンスが非常に重要です。私はさらに、OCamlが最速のCおよびC ++コンパイラと同等のパフォーマンスを備えた、より高速な言語の1つであることを知って驚いた。

F#はCLR上に構築されています。CLRでは、コードは共通中間言語と呼ばれるバイトコードの形式で表現されます。そのため、JITの最適化機能の恩恵を受けており、コードが適切に記述されていれば、C#(ただし、必ずしもC ++である必要はありません)に匹敵するパフォーマンスを発揮します。

CILコードは、ネイティブイメージジェネレーター(NGEN)を使用して、実行前の別の手順でネイティブコードにコンパイルできます。これにより、CILからネイティブへのコンパイルが不要になるため、ソフトウェアの以降のすべての実行が高速化されます。

考慮すべきことの1つは、F#のような関数型言語は、より宣言型のプログラミングの恩恵を受けるということです。ある意味で、C ++などの命令型言語でソリューションを過剰に指定しているため、コンパイラーの最適化機能が制限されます。より宣言型のプログラミングスタイルは、理論的にはコンパイラにアルゴリズム最適化の追加の機会を与えることができます。

于 2010-05-02T02:17:51.790 に答える
9

それはあなたがしている科学計算の種類に依存します。

線形代数やさまざまな最適化などを行っている場合はtraditional heavy computing、コードを.Net Frameworkに配置しないでください。少なくとも、F#には適していません。これはアルゴリズムレベルであるため、実行時間とメモリ使用量のパフォーマンスを向上させるには、ほとんどのアルゴリズムを命令型言語でコーディングする必要があります。他の人は並列について言及しましたが、SVD実装の並列のような低レベルの作業を行う場合はおそらく役に立たないと言わなければなりません。SVDを並列化する方法を知っていると、高水準言語を使用しないため、Fortran、C、または変更されたC(例:cilk)が友達になります。

ただし、今日の科学計算の多くはこの種のものではありません。これは、統計計算やデータマイニングなど、ある種の高レベルのアプリケーションです。これらのタスクでは、線形代数や最適化の他に、多くのデータフロー、IO、構想、グラフィックスの実行などもあります。これらのタスクでは、F#は非常に強力で、簡潔で、機能的で、安全で、簡単に実行できます。並列など。

他の人が述べているように、.NetはPlatform Invokeを十分にサポートしています。実際、MS内のかなりの数のプロジェクトが.NetとP/Invokeを一緒に使用してボトルネックのパフォーマンスを向上させています。

于 2010-05-03T01:50:57.680 に答える
7

残念ながら、信頼できる情報がたくさん見つかるとは思いません。F#はまだ非常に新しい言語であるため、パフォーマンスの高いワークロードに最適であったとしても、豊富な経験を持つ多くの人が報告することはありません。さらに、パフォーマンスを正確に測定することは非常に困難であり、マイクロベンチマークを一般化することは困難です。C ++内でも、コンパイラ間の劇的な違いを見ることができます。F#がC ++コンパイラと競合するのか、それとも架空の「可能な限り最高の」C ++実行可能ファイルと競合するのか疑問に思っています

C ++に対する特定のベンチマークに関しては、関連する可能性のあるリンクがいくつかあります。O'CamlとF#:QR分解並列数値のF#とアンマネージC++。F#関連の資料の作成者として、またF#ツールのベンダーとして、作成者はF#の成功に既得権を持っているので、これらの主張を一粒の塩で受け止めてください。

F#が実行時間で競争力のあるアプリケーションもあれば、そうでないアプリケーションもあると言っても過言ではありません。ほとんどの場合、F#はより多くのメモリを必要とします。もちろん、最終的なパフォーマンスはプログラマーのスキルにも大きく依存します。F#は、適度に有能なプログラマーにとって、プログラミングするためのより生産的な言語になると思います。さらに、現時点では、ほとんどのタスクで、ほとんどのOSでWindowsのCLRのパフォーマンスがMonoよりも優れていると思います。これは、意思決定にも影響を与える可能性があります。もちろん、F#はおそらくC ++よりも並列化が容易であるため、実行する予定のハードウェアの種類によっても異なります。

最終的に、この質問に実際に答える唯一の方法は、実行する計算の種類を表すF#およびC ++コードを記述し、それらを比較することだと思います。

于 2010-05-02T17:43:56.627 に答える
4

これが私が共有できる2つの例です:

  1. 行列の乗算:さまざまな行列の乗算の実装を比較するブログ投稿があります。

  2. LBFGS

C++でコード化されたLBFGS最適化を使用した大規模なロジスティック回帰ソルバーがあります。実装は適切に調整されています。一部のコードをC++/ CLIのコードに変更しました。つまり、コードを.Netにコンパイルしました。.Netバージョンは、さまざまなデータセットでコンパイルされた単純なバージョンよりも3〜5倍遅くなります。LBFGSをF#でコーディングする場合、パフォーマンスはC ++ / CLIまたはC#よりも優れていることはありません(ただし、非常に近いでしょう)。

F#がデータマイニングの言語である理由について別の投稿があります。ここで懸念するパフォーマンスの問題とはあまり関係ありませんが、F#の科学計算とはかなり関係があります。

于 2010-05-05T01:29:28.453 に答える
3

「2〜3年後にもう一度聞いてください」と言えば、あなたの質問に完全に答えると思います:-)

まず、意図的に複雑な再帰を実行している場合を除いて、F#がC#のパフォーマンスと異なることを期待しないでください。数値について質問したので、そうではないと思います。

浮動小数点に関しては、CLRはクロスプラットフォームの均一性を目的としていないため、Javaよりも優れているはずです。つまり、JITは可能な限り80ビットになります。一方、十分なFPレジスタがあることを確認するために変数の数を監視する以外に、それを制御することはできません。

ベクトル的には、Direct3Dが一般的なAPIとして.NETに入り、XNAで実行されるC#コードがXboxで実行されるため、2〜3年で何かが起こる可能性があります。これは、CLRで取得できるベアメタルに限りなく近いものです。 。それでも、自分でいくつかの中間コードを実行する必要があることを意味します。

したがって、CUDAや、NVIDIAライブラリをリンクして実行する機能さえ期待しないでください。Haskellは純粋な必要性からリンクしやすいように設計されているので、何らかの理由で本当に「関数型」言語が本当に必要な場合は、Haskellでそのアプローチを試してみるとはるかに幸運になります。

Mono.Simdはすでに言及されており、CLRにバックポータブルである必要がありますが、実際にそれを行うにはかなりの作業が必要になる場合があります。

.NETでのSSE3の使用に関するsocial.msdnの投稿には、C ++ / CLIおよびC#でかなりの数のコードがあり、配列ブリッティング、パフォーマンス用のSSE3コードの挿入などがあります。

コンパイルされたC#でCECILを実行して、パーツをHLSLに抽出し、シェーダーにコンパイルし、グルーコードをリンクしてスケジュールすることについての話がありました(CUDAはとにかく同等のことを行っています)が、そこから実行可能なものはないと思います。

すぐに何かを試したい場合は、codeplex上のPhysX.Netがもっと価値があるかもしれません。開梱して魔法をかけるだけだとは思わないでください。ただし、ihには現在アクティブな作成者がいて、コードは通常のC++とC++ / CLIの両方であり、詳細を調べてCUDAに同様のアプローチを使用したい場合は、yopuが作成者の助けを借りることができます。フルスピードのCUDAを使用するには、独自のカーネルをコンパイルしてから、.NETにインターフェイスするだけでよいので、その部分が簡単になるほど幸せになります。

無料のCUDA.NETlibがありますが、ページには電子メールアドレスしか記載されていないため、いくつかの文字列が添付されていることを期待してください。作成者がブログを書いている間、libの内容については特におしゃべりではありません。

ああ、予算があれば、そのPsi Lambdaを見てみるかもしれません(KappaCUDAnetは.NETの部分です)。どうやら彼らは11月に価格を引き上げるつもりです(それが販売のトリックでなければ:-)

于 2010-10-13T12:30:27.563 に答える
2

まず、CはC ++よりも大幅に高速です。したがって、非常に高速が必要な場合は、cでlibなどを作成する必要があります。

F#に関しては、ほとんどのベンチマークは、部分的にベームGCを使用しているためにMSCLRよりも最大2*遅いMonoを使用しています(新しいGCとLVVMがありますが、これらはまだ未成熟であり、ジェネリックなどをサポートしていません)。

.NEt言語自体は、C ++と同じくらい効率的にネイティブコードにコンパイルされるIR(CIL)にコンパイルされます。ほとんどのGC言語が苦しんでいる問題セットが1つあります。それは、大量の可変書き込みです(これには、前述のC ++ .NETが含まれます)。そして、これを必要とする特定の科学的な問題セットがあります。これらは、必要に応じて、ネイティブライブラリを使用するか、Flyweightパターンを使用してプールからのオブジェクトを再利用する必要があります(書き込みが減少します)。その理由は、.NET CLRに書き込みバリアがあり、参照フィールド(ボックスを含む)を更新すると、このテーブルが変更されたことを示すビットがテーブルに設定されるためです。あなたのコードがそのような書き込みの多くで構成されている場合、それは苦しむでしょう。

とはいえ、多くの静的コード、構造体、および構造体のref / outを使用するC#のような.NETアプリは、Cのようなパフォーマンスを生み出すことができますが、このようにコーディングしたり、コードを維持したりすることは非常に困難です(Cのように)。

ただし、F#が優れているのは、不変データに対する並列処理であり、読み取りベースの問題が増えています。ほとんどのベンチマークは、実際のアプリケーションよりも可変書き込みの方がはるかに高いことに注意してください。

浮動小数点に関しては、遅いため、oCamlのものに代わるlib(つまり.Netのもの)を使用する必要があります。C / C ++は、oCamlがデフォルトで提供していない、より低い精度を可能にします。

最後に、C#、F#のような高級言語と適切なプロファイリングにより、同じ開発者時間でcやC++よりも優れたパフォーマンスが得られると私は主張します。ボトルネックをaclibpinvoke callに変更すると、重要な領域でCのようなパフォーマンスが得られます。とはいえ、無制限の予算があり、速度を重視する場合は、Cよりもメンテナンスが(C ++ではなく)進むべき道です。

于 2010-06-18T00:59:55.587 に答える
1

最後に私が知っていたのは、ほとんどの科学計算はまだFORTRANで行われていたことです。線形代数の問題では、Java、C、C ++、C#、F#ではなく、他の何よりも高速です。LINPACKは適切に最適化されています。

ただし、「マイレージは異なる場合があります」という記述は、すべてのベンチマークに当てはまります。包括的な声明(私のものを除く)が真実になることはめったにありません。

于 2010-05-02T02:21:43.603 に答える