web-dev-qa-db-ja.com

どちらが速いですか?比較または割り当て?

私は少しコーディングを行っていますが、この種のコードを作成する必要があります。

if( array[i]==false )
    array[i]=true;

次のように書き直すべきかしら

array[i]=true;

これは疑問を提起します:比較は割り当てよりも速いですか?

言語ごとの違いはどうですか? (Java&cppなどの対比)

注:「時期尚早の最適化はすべての悪の根源である」と聞きました。ここでは当てはまらないと思います:)

38
jrharshath

さて、あなたはこれが重要であると確信していると言うので、あなたはただテストプログラムを書いて違いを見つけるために測定するべきです。

このコードをメモリ内の分散アドレスに割り当てられた複数の変数で実行すると、比較が高速になります。比較すると、メモリからプロセッサキャッシュにデータを読み取るだけであり、キャッシュが行をフラッシュすることを決定したときに変数値を変更しない場合は、行が変更されていないことがわかり、書き戻す必要はありません。メモリに。これにより、実行を高速化できます。

19
sharptooth

これは 時期尚早の最適化 だけではありません、これはmicro-最適化、これは無関係な気晴らしです。

配列がブール型であると仮定すると、比較は不要です。これが唯一の関連する観測です。

27
cletus

編集:私はPHPでスクリプトを書きました。明白なエラーが含まれていることに気づきました。これは、ベストケースのランタイムが正しく計算されていないことを意味します(他の誰も気付かないのは怖いです!)

最良の場合ちょうど勝つ完全な割り当てですが、最悪の場合はかなり悪い単純な割り当てよりもです。割り当ては、実際のデータの観点からはおそらく最速です。

出力:

  • 0.0119960308075秒で割り当て
  • 0.0188510417938秒での最悪の場合の比較
  • 0.0116770267487秒でのベストケースの比較

コード:

<?php
$arr = array();

$mtime = explode(" ", microtime());
$starttime = $mtime[1] + $mtime[0];

reset_arr($arr);

for ($i=0;$i<10000;$i++)
    $arr[i] = true;


$mtime = explode(" ", microtime());
$firsttime = $mtime[1] + $mtime[0];
$totaltime = ($firsttime - $starttime);
echo "assignment in ".$totaltime." seconds<br />"; 

reset_arr($arr);

for ($i=0;$i<10000;$i++)
    if ($arr[i])
        $arr[i] = true;

$mtime = explode(" ", microtime());
$secondtime = $mtime[1] + $mtime[0];
$totaltime = ($secondtime - $firsttime);
echo "worst case comparison in ".$totaltime." seconds<br />"; 

reset_arr($arr);

for ($i=0;$i<10000;$i++)
    if (!$arr[i])
        $arr[i] = false;

$mtime = explode(" ", microtime());
$thirdtime = $mtime[1] + $mtime[0];
$totaltime = ($thirdtime - $secondtime);
echo "best case comparison in ".$totaltime." seconds<br />"; 

function reset_arr($arr) {
    for ($i=0;$i<10000;$i++)
        $arr[$i] = false;
}
15
Oli

比較ステートメントと代入ステートメントが両方ともアトミック(つまり、1つのプロセッサ命令)であり、ループがn回実行される場合、最悪の場合の比較では、割り当てにはn + 1(すべての反復での比較と割り当ての設定)の実行が必要になりますが、常にboolを割り当てるには、n回の実行が必要になります。したがって、2番目のものがより効率的です。

3
redbandit

なぜ最初のバージョンを書くのですか? trueに設定する前に、何かがfalseであるかどうかを確認することの利点は何ですか。常にtrueに設定する場合は、常にtrueに設定してください。

単一のブール値を不必要に設定することにまでさかのぼるパフォーマンスのボトルネックがある場合は、戻って私たちに相談してください。

1
Andy Lester

言語によって異なります。ただし、配列をループすることもコストがかかる可能性があります。配列が連続したメモリにある場合、言語/コンパイラがこれを実行できると仮定して、memcpyを使用して配列全体に1ビット(255秒)を書き込むのが最速です。

したがって、0回の読み取り-1回の書き込み合計、ループ変数/配列変数の読み取り/書き込みなし(2回の読み取り/ 2回の書き込み各ループ)を数百回実行します。

1
VeNoM

アセンブリ言語についてのある本の中で、著者は、可能であれば、条件を回避する必要があると主張したことを覚えています。条件がfalseで、実行を別の行にジャンプする必要がある場合は、パフォーマンスが大幅に低下します。また、プログラムは機械語で実行されるため、条件がほぼ常に真である場合を除いて、すべての(コンパイルされた)言語で「if」の方が遅いと思います。

0
Alatoo

他の人が指摘しているように、これはマイクロ最適化です。

(政治やジャーナリズムでは、これはへそ凝視として知られています;-)

プログラムは、関数/メソッド/サブルーチン呼び出しの2つ以上の層を持つのに十分な大きさですか?

もしそうなら、それはおそらくいくつかの回避可能な呼び出しを持っていました、そしてそれらは低レベルの非効率と同じくらい多くの時間を浪費する可能性があります。

削除した (ほとんどの人はそうしません)を持っていると仮定して、ストップウォッチの下で必ず10 ^ 9回実行し、どちらが速いかを確認します。

0
Mike Dunlavey

これほど些細なことでも、目立ったパフォーマンスの違いはないと思いますので、明確で読みやすいコードを提供することになります。私の意見では、それは常に真実を割り当てているでしょう。

0
Mark

これを試してみるかもしれません:

if(!array[i])
    array[i]=true;

しかし、実際に確実に知る唯一の方法は、プロファイリングすることです。ほとんどすべてのコンパイラーが、falseとの比較を不要と見なし、最適化すると確信しています。

0
Davy8

それはすべてデータ型に依存します。ブール値の割り当ては、最初にブール値を比較するよりも高速です。しかし、それはより大きな値ベースのデータ型には当てはまらないかもしれません。

0
Benoît