Реконструкция условной оценки ускоряют цикл?

$firstDay = mktime(0,0,0, $month, 1, $year);
$lastDay = mktime(0,0,0, $month + 1, 0, $year);

$ lastDay имеет 0 в качестве дня, что делает его последним днем ​​прошлого месяца и, таким образом, $month + 1

11
задан chaos 3 August 2009 в 04:58
поделиться

13 ответов

Это больше связано с фольклором C ++, микрооптимизацией рук, которая когда-то работала над определенной версией конкретного компилятора и скончался когда-либо как какое-то предание, отличающее владельца от общего стада. Это мусор. Профилирование - это правда.

45
ответ дан 3 December 2019 в 00:38
поделиться

My suspicion is your friend is 100% wrong. But I wouldn't trust my opinion anymore than I would trust your friend. In fact, if there is a performance problem there is only one person you should trust.

The Profiler

This is only way you can ever claim with any authority that one way is or is not faster than another.

10
ответ дан 3 December 2019 в 00:38
поделиться

Probably not, but if it did, the compiler would probably make the optimization for you automatically anyways. So do it whatever way makes your code most readable.

17
ответ дан 3 December 2019 в 00:38
поделиться

This is absolutely a case of micro-optimization and really doesn't need to be done.

It is true that (especially) in C++ there is a small performance difference between a post-increment operation and a pre-increment operation but that difference in today's compilers is generally negligible. The reason for changing the order of the conditional is due to the change from post- to pre-increment.

-1
ответ дан 3 December 2019 в 00:38
поделиться

Я скромно полагаю, что на некоторых компиляторах на определенных архитектурах следующее может уменьшаться более эффективно, чем варианты:

i = constant - 1
while (--i) {
}

Чтобы получить постоянные итерации.

Как отмечалось во многих комментариях, компилятор хорошо поработает над оптимизацией цикла для вас (люди, занимающиеся оптимизацией компилятора, много и много времени думали об этом). Разборчивый код, вероятно, более ценен, но YMMV!

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

На высоком уровне вы также можете получить значительно более высокую производительность с помощью OpenMP или на более низком уровне с помощью набора векторных инструкций (например, MMX), чтобы сделать несколько вычислений в одной инструкции. Это немного выходит за рамки вопроса, и вам придется дать гораздо больше информации о том, что делает цикл, за полезные советы по этому поводу.

Надежда, которая помогает и подбадривает.

0
ответ дан 3 December 2019 в 00:38
поделиться

Сегодня на хорошем компиляторе совсем нет.

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

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

Кроме того, не все платформы созданы равными. Встраиваемые платформы часто страдают от некондиционных оптимизаторов из-за низкой вычислительной мощности и требований к обработке в реальном времени.

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

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


Было время, когда завершение цикла в нуле (например, путем обратного отсчета) на x86 фактически могло дать заметные улучшения для тесных циклов, как DEC CX / JCXNZ был быстрее (он все еще потенциально мог бы быть, поскольку мог бы сохранить доступ к регистру / памяти для сравнения; теперь оптимизация выполнения компилятора обычно выше этого). То, что слышал твой друг, может быть искаженной версией этого.

поскольку DEC CX / JCXNZ был быстрее (он все еще потенциально мог бы быть, так как он мог сохранить доступ к регистру / памяти для сравнения; теперь оптимизация выполнения компилятора обычно выше этого). То, что слышал твой друг, может быть искаженной версией этого.

поскольку DEC CX / JCXNZ был быстрее (он все еще потенциально мог бы быть, так как он мог сохранить доступ к регистру / памяти для сравнения; теперь оптимизация выполнения компилятора обычно выше этого). То, что слышал твой друг, может быть искаженной версией этого.

0
ответ дан 3 December 2019 в 00:38
поделиться

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

2
ответ дан 3 December 2019 в 00:38
поделиться

Хотя профилирование лучше, это не единственный способ .

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

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

4
ответ дан 3 December 2019 в 00:38
поделиться

Assuming short-circuit evaluation, the only time this should make much of a difference is if you have a call to a slow function in your loop. For example, if you had a function that queried a value from your database, and returned it, then this:

while(bContinue && QueryStatusFromDatabase==1){
}  //while

Would be much faster than:

while(QueryStatusFromDatabase==1 && bContinue){
}  //while

Even though they are logically identical.

That's because the first one can stop as soon as a simple boolean is FALSE - the query only has to run when the boolean is TRUE, but the second one will always run the query.

Unless you have a need to squeeze every possible CPU cycle out of your loop, then those extreme cases are probably the only ones worth spending your time on. Think of it this way: To make up the time you spent asking this question would probably take several billion iterations of your loop.

Worst of all is when you have a function as a condition, and that function has side-effects that are secretly expected by some other place in the code. So when you make your little optimization, the side effects only happen some of the time, and your code breaks in weird ways. But that's a bit of a tangent. The short answer to your question is "Sometimes, but it usually doesn't matter."

5
ответ дан 3 December 2019 в 00:38
поделиться

It is more of a best practice not to go out of your way for optimization tweaks like this which will give you negligible benefit (assuming it is a tweak).

3
ответ дан 3 December 2019 в 00:38
поделиться

The examples you gave should have absolutely no performance difference in C++, and I doubt they would differ in Python either.

Perhaps you're confusing it with a different optimisation:

for (int i = 0; i < variable; ++i)

// ...vs...

for (int i = variable; i ; --i)

The latter is faster in some architectures because the act of decrementing the variable will set the zero flag, which can then be checked in a jump-if-not-zero instruction, giving you the loop iteration and the conditional in one go. The former example needs to perform an explicit comparison or a subtraction to set a flag, and then jump based on that.

However, most of the time the compiler can optimise the first case into the second (especially if it sees that the variable is effectively a constant), and on some compiler/architecture combinations instructions may be generated that make the first method more like the second. Things like this are only worth trying if you have a tight inner loop that your profiler is telling you is expensive, but you'll never notice the difference otherwise, if there even is one.

8
ответ дан 3 December 2019 в 00:38
поделиться

Предоставленная оптимизация только оптимизирует больше для данного компилятора (возможно). В абстрактном смысле он должен генерировать тот же самый код.

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

Например, i ++ может быть быстрее, чем i + 1. Зависит. В наивных процессорах равенство нулю намного быстрее, чем меньше чем. Если ваш компилятор / ЦП не поддерживает переупорядочение инструкций, вы можете обнаружить, что перемежение присвоений с вычислениями ускоряет ваш код. (определенные вычисления могут вызвать остановку конвейера) Но это то, что вам нужно будет специально определить для вашей комбинации компилятор / архитектура.

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

* Я знаю программу, которая после нескольких месяцев оптимизации и на современных машинах все еще могла бы занять много месяцев. обрабатывать данные. Время выполнения для одного набора данных находится в недельном диапазоне. Есть довольно много данных, которые нужно использовать ....

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

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

0
ответ дан 3 December 2019 в 00:38
поделиться

Сравнение с 0 выполняется очень быстро, поэтому на самом деле это будет немного быстрее:

for (int i = constant; i > 0; --i)
{ 
  //yo
}

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

1
ответ дан 3 December 2019 в 00:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: