5

Java、C#、および C++ で数値計算を行います。それらのいくつかは、大量のデータを (テキスト ファイルに) 保存します。それを行う最も速い方法は何ですか?

C++ .

ofstream file;
file.open(plik);
for(int i=0;i<251;i++){
    for(int j=0;j<81;j++)
        file<<(i-100)*0.01<<" "<<(j-40)*0.01<<" "<<U[i][j]<<endl;
    file<<endl;
}

私はどちらが非常に速いと思いますか(私は正しいですか?:))

ジャワ

void SaveOutput(double[][] U, String fileName) throws IOException
{
    PrintWriter tx = new PrintWriter(new FileWriter(fileName));
    for(int i=0;i<251;i++)
    {
        for(int j=0;j<81;j++)
        {
            tx.println(String.format("%e %e %e ",(i - 100) * dz, (j - 40) * dz, U[i][j]));
        }
        tx.println();
    }
    tx.close();
}

C# の例も同様です。

ここで私を悩ませます。行ごとに String オブジェクトを作成します (大量のゴミ)。この例ではそれほど多くはありませんが、10 000 000 行になることもあります。これは私に質問を導きます:

  1. C++ の例はもっと速くできますか?
  2. JavaにStringBuilderを使用する必要がありますか、それとも行数のために悪いかもしれません
  3. 他の方法やライブラリはありますか?
  4. C# はどうですか?

ありがとうございました

4

8 に答える 8

5

プロファイリングします。コードを実行し、時間を計って、所要時間を確認します。かかる時間が許容できる場合は、それを使用してください。そうでない場合は、実行に時間がかかっている部分を特定し、最適化します。

  • それを正しくしてください。
  • 速くしてください。

その注文。(これら2つの前に「make it run/build」を追加する人もいます...)

そうは言っても、私は実際にこの種のメトリックを以前に実行したことがあります。簡単に言うと、ディスクを待っていますが、ディスクは信じられないほど遅いです。C、C++、または Java で書いているかどうかは関係ありません。それらはすべてハードディスクを待っています。

これは、C のさまざまな I/O メソッドについて行った以前の投稿です。まさにあなたが探しているものではありませんが、参考になるかもしれません。

于 2010-11-04T23:08:42.620 に答える
4

一言:プロフィール。

バッファリングされた (ファイル) ストリームに挿入するとフラッシュが発生し、おそらくパフォーマンスが低下することに注意してくださいstd::endl(言語 POV からは、バッファが「出力」されることを意味しますが、これは必ずしも物理ディスク アクセスを意味するわけではありません)。単純に改行を印刷するには、使用して'\n'ください - それは決して悪いことではありません。

于 2010-11-04T23:10:48.423 に答える
2

何よりもまず、バッファ付きライターを使用してください。

これには、一部の言語でのチャネルでのバッファリングの有効化、または他の言語でのBufferedWriter (Java での)または同等の使用が含まれる場合があります。そうしないと、出力ストリームが「オーバーフラッシュ」される可能性があるため、パフォーマンスが大幅に低下する可能性があります。上記のサンプル コードはこれに違反しています (FileWriter はバッファリングについて何も知りません)。

多くの場合、CPU とメイン メモリへのアクセスは「安価」であり、IO は「高価」であると考えることができます。目に見える利益。最新の VM と JIT は非常にうまく機能しており、寿命の短いオブジェクトの割り当て/割り当て解除は、ここでの「心配事」の中で最も少ないと思われます。

于 2010-11-04T23:24:45.307 に答える
1

最初に、この I/O バウンド プログラムは、細かい部分 (たとえば、C++ ストリームまたは を使用する場合printf) によってはあまり改善されないことに注意してください。

C/C++ の部分については、古いprintf操作を使用する方が速いと言う人もいます。それはより速いかもしれませんが、それほど桁違いではないので、私は気にしません.

Java版に関しては、すでにかなり最適化されていると思います。

C#についてはわかりません。私の医者は私を許可していません:)

于 2010-11-04T23:11:41.577 に答える
1

代わりに Java.nio クラスを使用してチャネルを作成してください。チャネルは Java にとって新しく、古いストリームよりもはるかに高速です。また、書き込みをバッファリングする必要があります。チャネルがデフォルトでバッファリングされるかどうか思い出せません。それを伝えるには、いくつか読む必要があります。

最後に、大量の文字列を作成しても問題ありません。あなたはそれらを即座に捨てています。ディスクへの書き込みが遅くなるとは思えません。ディスク IO は CPU よりもはるかに遅いです。

これが私が考えていたことです:

fileChannel = new FileOutputStream("test.txt").getChannel();
for(int i=0;i<251;i++) {
  for(int j=0;j<81;j++) {
    fileChannel.write(ByteBuffer.wrap((String.format("%e %e %e ",(i - 100) * dz, (j - 40) * dz, U[i][j]) + "\n").toBytes());
  }
fileChannel.close();
于 2010-11-04T23:08:46.400 に答える
0

ルーカス、

まず、私は主に C# を知っているので、ここにあるものはすべて .NET に関するものです。

あなたが扱っている行数では、私は文字列を作成したり、StringBuilder を使用したりしません。StringBuilder は、多数の小さなセグメントから文字列を作成する場合にのみ役立ちます。

最善の策は、ファイル システム オブジェクトのストリーム バージョンを使用することだと思います。そうすれば、文字列をまったく保存しないので、メモリ使用量はかなり少なくなります。

また、メモリが非常に不足している場合は、いつでもアンマネージ文字列を作成して P/Invoke することができます。

エリック

于 2010-11-04T23:12:51.733 に答える
0

Java に関して言えば、これらすべての文字列を作成する必要はありません。String.formatバイトを取り除き、直接書き込みます。

nio と profile を容赦なく使う

于 2010-11-04T23:13:04.383 に答える
0

fprintfC または C++ で使用する方が速いと思います。

于 2010-11-04T23:08:12.480 に答える