Что быстрее? Сравнение или назначение?

performance optimization refactoring

13877 просмотра

12 ответа

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

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

Интересно, должно ли это быть переписано как

array[i]=true;

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

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

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

Автор: jrharshath Источник Размещён: 12.11.2019 09:18

Ответы (12)


19 плюса

Решение

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

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

Автор: sharptooth Размещён: 26.05.2009 12:32

27 плюса

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

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

Автор: cletus Размещён: 26.05.2009 12:33

15 плюса

Изменить: я написал скрипт на 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;
}
Автор: Oli Размещён: 26.05.2009 12:42

3 плюса

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

Автор: redbandit Размещён: 29.10.2014 01:46

1 плюс

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

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

Автор: VeNoM Размещён: 08.10.2010 05:45

0 плюса

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

Автор: Mark Размещён: 26.05.2009 12:35

0 плюса

Могу попробовать это:

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

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

Автор: Davy8 Размещён: 26.05.2009 12:37

0 плюса

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

Автор: Benoît Размещён: 26.05.2009 12:38

0 плюса

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

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

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

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

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

Автор: Mike Dunlavey Размещён: 26.05.2009 04:03

0 плюса

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

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

Автор: Andy Lester Размещён: 08.10.2010 10:32

0 плюса

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

Автор: Alatoo Размещён: 02.11.2016 05:58

-1 плюса

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

array[i] = !array[i];

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

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

Автор: David Anderson Размещён: 26.05.2009 04:09
Вопросы из категории :
32x32