2016-11-14 25 views
-2

同じパターンを持つ関数を最適化するために、2つの実装方法を検討しています。 この関数の環境は、組み込みソフトウェアの割り込みの内部で使用できます。これは、スピード能力を考慮する必要があるため、私は難しさに直面しています。 私の意見では、次のケース1と2には同じ速度機能があります。しかし、私の同僚は、ポインタを使って最初のケースにアクセスする必要があるので違いがあると言いましたが、2番目のケースはそうではありません。 どちらがより高速ですか? 効率的なコードをスピードで実装するには、あなたの助けが必要です。関数の入力引数として構造体と変数を使用する速度の差

typedef struct 
{ 
    unsigned char member1; 
    unsigned char member2; 
    .. 
    unsigned char member10; 
} my_struct 

my_struct input[10]; 

void My_ISR1(void) 
{ 
    ... 
    sub_func1(input[1]); 
    return 0; 
} 
void My_ISR2(void) 
{ 
    ... 
    sub_func1(input[2]); 
    return 0; 
} 
void sub_func1(my_struct my_struct_input) 
{ 
    if(my_struct_input.member1 < my_struct_input.member2) 
    { 
    ... 
    } 
    ... 
    return 0; 
} 

CASE2)

unsigned char member1of1; 
unsigned char member2of1; 
... 
unsigned char member10of10; 

void My_ISR1(void) 
{ 
    ... 
    sub_func1(member1of1, ..., member10of1); 

    return 0; 
} 

void My_ISR2(void) 
{ 
    ... 
    sub_func1(member1of2, ..., member10of2); 

    return 0; 
} 

void sub_func1(unsigned char member1, 
       unsigned char member2, ..., 
       unsigned char member 10) 
{ 
    if(member1 < member2) 
    { 
    ... 
    } 
    ... 
    return 0; 
} 
+5

特定のユースケースに対して、ある実装が他の実装より速いか、コンパイラで、コード内で、ハードウェア上で問題が発生するかを確認する唯一の方法は、それを測定することです。 – mjs

+2

あなたは構造体へのポインタを渡していません。投稿した両方のスニペットは同じ量のデータをスタックにコピーします。あなたは、毎回(今やっているように)それをコピーするのではなく、よりパフォーマンスの高い(そしておそらくコンパイラのインライン化が容易な)参照を使って構造体を参照(つまりポインタを使用)する必要があります。それ以外は、パフォーマンス上の理由だけでなく、実際のコンシューマに透過的な同じ方法で構造体インスタンスを渡すことを可能にするために、10個のフィールドを複製するのではなく、 'struct'を使用する必要があります。 – Groo

+2

構造体*をコピー*によって渡しているので、ポインタによるアクセスはありません。この種のマイクロ最適化はめったに生産的ではありません。コンパイラにそのようなことを任せ、効率的なデータ構造とアルゴリズムを使用して設計レベルでの最適化に集中します。最終的には、「より速い」という質問に対する答えは、それを測定することによってのみ答えることができ、答えはコンパイラ、ターゲット、およびコンパイラオプションによって異なることさえあります。 – Clifford

答えて

2

一つの実施は、あなたの特定のために、あなたのハードウェア上で、あなたのコードでは、コンパイラ、およびあなたの問題空間のために、他のよりも高速である場合を確認してくださいする唯一の方法ユースケースは、それを測定することです。二つのオプションが提示の

しかし、私はパスごとの構造体がわずかに速いことを期待するの両方で

(ところで、あなたのコードでは、ポインタによってない通過しています)提示されたケースでは、変数のコピーが関数に渡されます。 どちらの場合でも、結果として10バイトのコピーが生成されますが、構造体が連続している場合は、これはわずかに高速です。おそらく(代わりに、私たちは一つだけをコピーしている10個の個々の変数、または10バイトの構造体をコピーするので、

void sub_func1(my_struct* my_struct_input) 
{ 
    if(my_struct_input->member1 < my_struct_input<member2) 
    ///........ 
} 

この道32を:

しかし、より良いオプションは、ポインタなどを通過するかもしれませんビット、それに依存します)アドレス。

これは、呼び出し元と同じ構造体で現在動作しているが、constポインタを使用して解決できるという欠点があります。

これ以上考慮する必要があることは、あるシナリオや別のシナリオでは関数呼び出しが高速になるかもしれないが、より大きな画像を見なければならないことである。構造体ポインタを渡す方が速いはずですが、構造体を構築する際のオーバーヘッドも考慮する必要があります。既存の変数から構造体メンバを割り当てる必要がある場合は、明らかに余分な処理が追加されます。

+0

ターゲットが上位レベルのワードアライメントを必要としない場合、構造体は10バイトのコピーに過ぎません。32ビットアラインメントが必要なターゲットの場合、40バイトになります。構造体の使用はまた、いくつかの引数がレジスタに渡るのを防ぐかもしれません。この質問に対する答えはありません。あまりにも多くの未知数があります。それはあなたが測定されると言う通りです。 – Clifford

関連する問題