Что быстрее? Сравнение или назначение? - PullRequest
32 голосов
/ 26 мая 2009

Я немного занимаюсь кодированием, где я должен написать такой код:

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

Интересно, стоит ли его переписать как

array[i]=true;

Возникает вопрос: сравнения выполняются быстрее, чем присвоения?

А как насчет различий от языка к языку? (контраст между java и cpp, например.)

ПРИМЕЧАНИЕ. Я слышал, что «преждевременная оптимизация - это корень всего зла». Я не думаю, что это применимо здесь:)

Ответы [ 12 ]

27 голосов
/ 26 мая 2009

Это не просто преждевременная оптимизация , это микрооптимизация , что не имеет значения.

Предполагая, что ваш массив имеет логический тип, сравнение не требуется, что является единственным релевантным наблюдением.

19 голосов
/ 26 мая 2009

Ну, так как вы говорите, что уверены, что это важно, вы должны просто написать тестовую программу и измерить, чтобы найти разницу.

Сравнение может быть быстрее, если этот код выполняется для нескольких переменных, размещенных по разным адресам в памяти. При сравнении вы будете только читать данные из памяти в кеш процессора, и если вы не измените значение переменной, когда кеш решит сбросить строку, он увидит, что строка не была изменена, и нет необходимости записывать ее обратно в память. Это может ускорить выполнение.

15 голосов
/ 26 мая 2009

Редактировать: я написал скрипт на 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;
}
3 голосов
/ 29 октября 2014

Я полагаю, что если операторы сравнения и присваивания являются атомарными (то есть одна инструкция процессора) и цикл выполняется n раз, то при сравнении в худшем случае присвоение потребует n + 1 (сравнение на каждой итерации плюс установка назначения) казни, тогда как постоянное назначение bool потребует n казней. Поэтому второй более эффективен.

1 голос
/ 08 октября 2010

Зависит от языка. Однако циклически проходить по массивам также может быть дорогостоящим. Если массив находится в последовательной памяти, самое быстрое - записать 1 бит (255 с) по всему массиву с помощью memcpy, если ваш язык / компилятор может это сделать.

Таким образом, выполнение 0 операций чтения-1 записи, отсутствие чтения / записи переменной цикла / переменной массива (2 чтения / 2 записи в каждом цикле) несколько сотен раз.

0 голосов
/ 02 ноября 2016

Я помню, как в одной книге о языке ассемблера автор утверждал, что, если условия следует избегать, по возможности. Это намного медленнее, если условие ложно и выполнение должно перейти на другую строку, что значительно замедляет производительность. Кроме того, поскольку программы выполняются в машинном коде, я думаю, что «if» медленнее на каждом (скомпилированном) языке, если его условие не выполняется почти все время.

0 голосов
/ 09 октября 2010

Зачем вам вообще писать первую версию? Какая польза от проверки, если что-то не так, перед установкой этого значения. Если вы всегда собираетесь установить значение true, всегда устанавливайте значение true.

Если у вас есть узкое место в производительности, которое вы проследили до ненужной установки одного логического значения, вернитесь и поговорите с нами.

0 голосов
/ 26 мая 2009

Если вы просто хотите перевернуть значения, выполните:

array[i] = !array[i];

Производительность при использовании этого на самом деле хуже, так как вместо того, чтобы выполнять только одну проверку истинного ложного значения, а затем устанавливать, она проверяет дважды.

Если вы объявляете массив из 1000000 элементов true, false, true, false, сравнение шаблонов происходит медленнее. (var b =! b), по сути, делает проверку дважды, а не один раз

0 голосов
/ 26 мая 2009

Как уже отмечали другие, это микрооптимизация.

(В политике или журналистике это известно как наблюдение за пупком; -)

Достаточно ли велика программа, чтобы иметь более двух уровней вызовов функций / методов / подпрограмм?

Если это так, то, вероятно, было несколько звонков, которых можно избежать, и они могут потратить на сотни больше времени, чем неэффективность низкого уровня.

Если предположить, что вы удалили эти (что делают немногие), то непременно запустите его 10 ^ 9 раз под секундомер и посмотрите, что быстрее.

0 голосов
/ 26 мая 2009

Все зависит от типа данных. Назначение логических значений выполняется быстрее, чем их первое сравнение. Но это может быть не так для больших типов данных на основе значений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...