2011-06-30 7 views
0

私はCでマイクロコントローラ用のFFTアルゴリズムを研究しており、入力データの実数部と虚数部を単なる構造体の配列に格納するか、構造体の配列へのポインタを使用するかどうかを決定するのに問題があります。私は、コードがわずかなメモリ量で実行されなければならず、しかも可能な限り速くなければならないという矛盾する要件に直面しています。私は、構造体へのポインタの配列が若干大きくメモリのオーバーヘッドを持っていると考えているが、私のコードの行は、次のように基本的にあります:構造体へのポインタの配列を使用するか、構造体の配列のみを使用しますか?

for (uint8_t i = 0; i < RECORD_SIZE; i++) 
{ 
    uint8_t decimateValue = fft_decimate(i); 
    fftData[i]->realPart = fftTempData[decimateValue]->realPart; 
    fftData[i]->imPart = fftTempData[decimateValue]->imPart; 
} 

私のように、私はポインタの配列を使用する場合、構造体することを考えています上記の例では、構造体の配列の実装のように、実際には2つのデータ構造間のすべてのデータを実際にコピーするのではなく、コンパイルされたコードがポインタを再整理するだけで高速になります。上記のコードセクションができるだけ速く実行されるならば、私はいくつかの余分なメモリを犠牲にするつもりです。アドバイスありがとう。

+0

コードの両方のバージョンを実行して、どちらが高速であるのを確認してみませんか? –

答えて

3

ポインターの配列を使用してデータにアクセスするたびに、2つのメモリーアクセスがあります。これには、マイクロコントローラ上でさえ、パイプラインの停止が伴うことがよくあります(パイプラインのない実際に小型のマイクロコントローラでない限り)。

次に、データのサイズを考慮する必要があります。ポインタはどれくらい大きいですか? 2バイト? 4バイト?構造体の大きさはどれくらいですか? 4バイト? 8バイト?

構造体がポインタの2倍の大きさであれば、データのシャッフルはポインタの半分になります。しかし、他の方法でデータを読み込んだり変更したりするのは、より高価になります。したがって、あなたのプログラムが何をするかによって異なります。データの読み込みに多くの時間を費やし、少し時間をかけてシャッフルした場合は、データの読み込みを最適化します。他の人には正しいプロファイルがあります。ワークステーションではなく、マイコンでプロファイルを作成してください。

+0

アルゴリズムはシャッフルよりも読み込み時間が大幅に長くなりますので、まっすぐな配列実装にする必要があります。 IIRC、私はAVRメガシリーズは2段階のパイプラインを持っていると思う。 – Bitrex

0

あなたはそうです。ポインタの配列は高速ですが、メモリ使用量にオーバーヘッドがあります。ポインタを使用するメモリがある場合は、ポインタを使用します。

2

構造体が非常に小さい場合、構造体の配列を持ち、それらをシャッフルする方が実際には高速になります。あなたの構造体が大きい場合、ポインタの周りをシャッフルするだけであれば、この特定のアクションは速くなります。

ちょっと待ってください。ポインタの周りをシャッフルしているのではなく、それらのポインタが参照する構造体のフィールドにアクセスしています。実際には、ポインタではなく構造体自体をシャッフルしています。これはポインタを移動させるよりも遅くなるだけでなく、ポインタを逆参照してから構造体を移動する必要があるため、構造体を移動するよりも遅くなります。

+0

コンパイラが各構造の同じ要素をお互いに割り当てているので、実際に行う必要があるのは、fftData [i]のポインタの値をポイントに変更するだけなので、私は不思議ですどんなfftTempdata [decimateValue]が指しているところでも。 – Bitrex

0

最初:それに応じて異なります。プロフィール。

キャッシュのローカリティがここで統治されます。私は構造体が非常に小さくなることを期待しています(複素数を表していますか?)。 FFTでは、実数部と虚数部を別々の配列に格納するほうがはるかに多くの利益を期待します。

次に、CPUコア間で負荷を分割できます。

これは、かなり大きいチャンク(たとえば1024サンプルブロック)の場合、シャッフルポインタが効率的であると強く思っています。また、複数のスレッドから同じ(読み込み専用の)データを扱うことも可能になります。メモリを移動することは、多くのイテレータを無効にする特定の方法です。通常は、タスク(つまりスレッド)をデータのサブレンジ、つまりイテレータの部分範囲で処理する必要があります。

+0

質問には、特に複数のコアを持たず、しばしばキャッシュを持たないマイクロコントローラが挙げられます。 –

+0

@Dietrich:良い点。 Sry私はそれを逃した。その場合、CPUにオペランドの実効アドレスを計算させる以外に何らかの間接を避けるようにします。 – sehe

関連する問題