1

ファイルAの行をループするときに、行を解析し、各文字列(char*)を。に入れchar**ます。

行の終わりで、ファイルBを開き、を使用して、そのファイルから文字を取得する手順を実行しfgetsます。次に、ファイルBを閉じます。fseekfgetc

行ごとにファイルBの再オープンと再クローズを繰り返します。

私が知りたいのは:

  1. を使用することでパフォーマンスが大幅に低下するため、動的ではなく静的なものを使用する必要がありますmallocか?freemyArray[NUM_STRINGS][MAX_STRING_WIDTH]char** myArray

  2. ファイルBを開いたり閉じたりすることによるパフォーマンスのオーバーヘッドはかなりありますか(概念的には、何千回も)?ファイルAがソートされている場合、fseekファイルBで「後方」に移動し、ファイルBで以前に配置されていた場所をリセットする方法はありますか?

編集2つのアプローチにより、実行時間が大幅に短縮されたことがわかりました。

  1. 私のファイルBは実際には24個のファイルの1つです。同じファイルB1を1000回開き、次にB2を1000回開くのではなく、ファイルB1を1回開き、閉じ、B2を1回、閉じるなどします。これにより、数千回のfopen操作fcloseが約24回に減ります。

  2. 以前rewind()はファイルポインタをリセットしていました。

これにより、速度が約60倍向上しましたが、これで十分です。を指摘していただきありがとうございますrewind()

4

8 に答える 8

4

動的配列が時間の経過とともに大きくなる場合、一部reallocのsにはコピーコストがかかります。「常に2倍」のヒューリスティックを使用する場合、これはO(n)に償却されるため、ひどいことではありません。事前にサイズがわかっている場合は、スタックに割り当てられた配列の方が高速です。

2番目の質問については、について読んでくださいrewind。常に開閉するよりも高速である必要があり、リソース管理を少なくすることができます。

于 2009-06-12T19:07:53.017 に答える
3

私が知りたいのは:

  • あなたのコードは正しく動作しますか?
  • あなたの目的に十分な速度で実行されていますか?

これらの両方の答えが「はい」の場合は、何も変更しないでください。

于 2009-06-12T19:10:24.807 に答える
1

他のプログラムがそのリソースを競合しているかどうかに応じて、開閉のオーバーヘッドは変動します。

最初にファイルサイズを測定し、それを使用して事前にアレイサイズを計算し、1つの大きなヒープ割り当てを実行します。

多次元配列をすぐに取得することはできませんが、ポインタ演算を少し行うだけで済みます。

他のファイルに位置情報をキャッシュしてから、それを開いたり閉じたりするのではなく、以前のシークインデックスをオフセットとして使用することはできませんか?正確なロジックに本当に依存します。

于 2009-06-12T19:08:00.023 に答える
1
  1. ファイルが大きい場合、ディスク I/O はメモリ管理よりもはるかにコストがかかります。プロファイリングの前に malloc/free のパフォーマンスを心配することは、それがボトルネックであることを示しており、それは時期尚早の最適化です。

  2. プログラムで頻繁なオープン/クローズによるオーバーヘッドが大きい可能性がありますが、ファイルが小さい場合を除き、実際の I/O はより高価になる可能性があります。余分なディスク I/O を引き起こします。はい、 ftell() を使用してファイル内の現在の位置を取得し、SEEK_SET で fseek を使用してその位置に到達できます。

于 2009-06-12T19:14:15.390 に答える
0

動的メモリを使用すると、常にパフォーマンスが低下します。静的バッファを使用すると、速度が向上します。

また、ファイルを再度開くとパフォーマンスが低下します。fseek(pos、SEEK_SET)を使用してファイルポインタをファイル内の任意の位置に設定したり、fseek(offset、SEEK_CUR)を使用して相対移動を実行したりできます。

パフォーマンスへの重大な影響は相対的なものであり、それが自分にとって何を意味するのかを判断する必要があります。

于 2009-06-12T19:09:21.173 に答える
0
  1. 必要な実際のスペースを割り当てる方が良いと思います。オーバーヘッドはおそらく重要ではありません。これにより、スペースの浪費とスタックオーバーフローの両方が回避されます

  2. はい。IOはキャッシュされますが、不要なシステムコール(オープンとクローズ)を行っています。SEEK_CURおそらくまたはでfseekを使用しSEEK_SETます。

于 2009-06-12T19:10:08.830 に答える
0

どちらの場合もパフォーマンスに多少の影響がありますが、その影響はファイルのサイズとプログラムが実行されるコンテキストによって異なります。

  1. 文字列の最大数と最大幅が実際にわかっている場合、これははるかに高速になります (ただし、「最大」未満を使用すると、大量のメモリが浪費される可能性があります)。幸せな方法は、C++ での多くの動的配列実装と同じことを行うことです: myArray を再割り当てする必要があるときはいつでも、必要なスペースを 2 倍割り当て、スペースがなくなったら再度再割り当てします。これには O(log n) のパフォーマンス コストがあります。

  2. これは、パフォーマンスに大きな影響を与える可能性があります。詳細はアルゴリズムによって異なりますが、fseek を使用することを強くお勧めします。

于 2009-06-12T19:10:26.303 に答える
0

パフォーマンスのオーバーヘッドよりも、付属の直接メモリ管理とメモリmalloc上の低レベル C ハンドラの方が重要であることがよくあります。メモリのこれらの領域が、このメモリに触れるよりも償却時間で長い時間、静的で触れられないままになる場合を除き、静的配列を使い続ける方が有益な場合があります。最後に、それはあなた次第です。

于 2009-06-12T19:13:04.660 に答える