2016-06-21 5 views
1

私は最近、次のようにあるコメントに出会っ:多次元配列のこれらの2つの実装の間にこのような実行時間の差があるのはなぜですか?

多次元配列は、配列アクセスのために多くの時間がかかります。キャッシュとアクセス速度を向上させるには、インデックスを小から大に、つまりrmq[1002][1002][11][11]ではなくrmq[11][11][1002][1002]のような配列をrmqと宣言することをお勧めします。

私は同じことをテストするコードを試しました。コード1:

int pre_compute[18][100001]; //global variable 

int main(){ 
    /*some precomputations on pre_compute array 
    of the order of size of the array*/ 

    /*Run 10^8 queries on pre_compute array, 
    O(1) per query.*/ 
} 

コード2:

int pre_compute[100001][18]; //global variable 

int main(){ 
    /*exact same precomputations on pre_compute array as done in Code 1 
    of the order of size of the array*/ 

    /*Run 10^8 queries on pre_compute array, 
    O(1) per query.*/ 
} 

両方のコード配列の分布を除いて同一です。それでも、2つのコード間に大きな実行時間差がありました。最初のコードは私のPCで平均で0.40 secsでしたが、他のコードは平均で1.42 secsでした。

配列の2つの実装の間にこのような大きな実行時間差が生じる理由は何でしょうか?

+5

これが役に立ちます:http://stackoverflow.com/questions/16699247/what-is-cache-friendly-code、http://stackoverflow.com/questions/9936132/why-does-the-orderループの影響を受けるパフォーマンス - 2d-arterを反復する場合 – vu1p3n0x

+1

@ vu1p3n0xこれらのうちの後者は問題となり、不都合に省略されたコードで何が起こっているのか実際に宣言された配列を使用します。良くやった。 – WhozCraig

+0

次回に[MCVE]を提供するか、質問の重複した回答に同意しない場合はここに投稿してください。 –

答えて

2

これは、行 - 主順序行列と列 - 主順序行列との違いです。アレイの列の連続した要素をメモリに連続して、行優先順に

;

差がWikipediaに説明されています列の主要な順序では、列の連続する要素は連続しています。

CおよびC++は行メジャーなので、局所的な理由で行のキャッシュを活用できます。これは、スピードアップの劇的な増加を説明します。

技術的には、時間を大幅に節約したい場合は、多次元配列を1D配列として表現する方がよい場合があります。 :)

+1

FortranがColumn Major Orderであるため、問題を処理せずにFortran - > Cを移植すると、パフォーマンスの問題が発生する可能性があります。 – EvilTeach

+0

@EvilTeach Yep - 絶対悪夢。 – erip

+1

多次元配列を1次元配列として表現しても、アクセスパターンが行メジャーの場合は、実際に何も変更されず、いつでも保存されることはありません。アクセスパターンを列メジャーから行メジャーに変更した場合や、列メジャーアクセスを使用してインデックス作成の計算を伴う1d表現を使用して列の主要な格納順序を実行すると、パフォーマンスが向上します。 –

関連する問題