0

いくつかの操作を行う必要がある文字の 2 次元配列があります。場合によっては、キャラクターがああかどうかを確認する必要があります。以前は、その文字が他の文字と等しくないかどうかを確認することでこれを達成していました (他の文字は 5 つしかありません)。ただし、最近、文字が < 'j' であるかどうかを代わりにチェックして、できれば少ないアセンブリ命令で同じ結果を得ることができるという考えを最近思いつきました。

いくつかの場所では、わずかなスピードアップをもたらしましたが、他の場所ではかなり大幅な減速をもたらしました. これはなぜですか?if ステートメントの < とは対照的に、!= の相対的な費用はいくらですか?

コード スニペットの例を次に示します。

if( arr[r][c] == arr[r][c+1] && arr[r][c] == arr[r][c+2]
         && arr[r][c] != 'q' && arr[r][c] != 'r' && arr[r][c] != 's' && arr[r][c] != 't')

if( arr[r][c] == arr[r][c+1] && arr[r][c] == arr[r][c+2]
         && arr[r][c] < 'j')
4

3 に答える 3

5

私があなたの質問を正しく理解していれば、配列列のすべての要素が文字 'a' と 'h' の間にあり、同一であるかどうかを確認したいと考えており、このプロセスを最適化したいと考えています。

アセンブリ言語を知っている場合は、逆アセンブラを使用して、実行中に関数で何が起こっているかを正確に調べることを強くお勧めします。すべてのコンパイラと最適化レベルはわずかに異なります。ただし、メモリ内の 2 つの値を比較するための最低限の操作は次のとおりです。

. メモリ内の 2 つの変数をプロセッサ レジスタにロードする (数クロック サイクル)

. 2 つのレジスタの値に対する等価性テストの実行 (1 クロック サイクル)

. フラグ レジスタに基づいてジャンプ コマンドを実行する (インテル プロセッサ) (別のクロック サイクル)

これは、プロセッサで得られる操作と同じくらい単純ですが、比較操作が積み重ねられているため、これらのチェックに必要な時間が累積されます (特に、メモリ アクセスに必要なクロック サイクル.

したがって、これらの比較に必要な時間を短縮するには、比較の数を減らす必要があります。文字 'a' から 'h' までの ASCII 値は 0x61 から 0x68 (10 進数で 97 から 104) の間であることに注意してください。文字が 'a' から 'h' の間にあるかどうかは、次の約 3 つの比較操作で確認できます。

if(arr[r][c] >= 97 && arr[r][c] <= 104)

列の 1 つの値のみをチェックし、このビット操作のトリックを使用して、列内のすべての要素が同じかどうかを判断します。

if(((arr[r][c] ^ arr[r][c+1]) + (arr[r][c] ^ arr[r][c+2]) + ...*etc*) == 0)

"xor"('^') 比較は、加算と同様に 1 クロック サイクルかかります。2 つの列エンティティ間に相違点がある場合、演算の結果は非ゼロになります。このメソッドは、列要素の数に応じて線形時間で増加する必要があり、追加のボーナスとして、最適化コンパイラは操作中にレジスタの 1 つに 'arr[r][c]' を保持できる場合があります。

于 2013-08-01T03:40:45.600 に答える
1

最新のコンパイラ/CPU は、分岐予測を使用して、他の実行パスよりも優先される候補結果をプリフェッチします。あなたのコンパイルは異なるものを予測し、したがって異なる結果を予測しました。結果は、2 次元配列の内容に依存する可能性があります。さらに、異なるコンパイラ/CPU では利点が異なる場合があります。分岐予測を検索してください - そこには素晴らしい答えがいくつかあります。

于 2013-08-01T03:44:59.667 に答える