Сокращение для цикла накладных расходов - PullRequest
1 голос
/ 23 июля 2011

Мне нужно перебрать формулу амортизации, которая выглядит следующим образом:

R = ( L * (r / m) ) / ( 1 - pow( (1 + (r / m)), (-1 * m * t ) );

Я использую цикл for для итерации и увеличиваю L (стоимость кредита) на 1каждый раз.Цикл работает просто отлично, но он заставил меня задуматься о чем-то другом, а именно о значении (или его отсутствии) выполнения базовых операций перед выполнением цикла и последующей ссылки на эти значения через переменную.Например, я мог бы дополнительно изменить эту функцию, чтобы она выглядела как

// outside for loop
amortization = (r/m)/(1 - pow( (1+(r/m)), (-1*m*t) ) )

// inside for loop
R = L * amortization

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

Интересно, насколько это актуально?Есть ли какое-то реальное значение при извлечении этих операций, или сэкономленное время настолько мало, что мы говорим об экономии миллисекунд от цикла for, который повторяется прибл.200 000 раз.Последующий вопрос: стоило ли бы извлекать подобные операции, если бы я выполнял более дорогие операции, такие как sqrt?

(примечание: в случае, если это имеет значение, я спрашиваю об этом специально с помощью c ++в уме)

Ответы [ 4 ]

2 голосов
/ 23 июля 2011

Как уже упоминалось, хорошие компиляторы будут выполнять такую ​​оптимизацию автоматически.Однако ...

Во-первых, pow, вероятно, является библиотечной функцией, поэтому ваш компилятор может знать или не знать, что это "чистая" функция (т. Е. Что ее поведение зависит только от ее аргументов).Если нет, он не сможет выполнить эту оптимизацию, потому что все знают, что pow может напечатать сообщение или что-то в этом роде.

Во-вторых, я думаю, что выделение этого выражения из цикла облегчает понимание кода, тем не мение.Человек, читающий ваш код, также может вынести это выражение «автоматически», но зачем его создавать?Это просто отвлекает их от потока вашего алгоритма.

Так что я бы сказал, чтобы сделать это изменение независимо.

Тем не менее, если вы действительно заботитесь о производительности, найдите достойного профилировщика и не беспокойтесь омикро-оптимизация, пока он не скажет вам.Ваши приоритеты на раннем этапе должны быть (а) использовать достойный алгоритм и (б) четко его реализовать.И не в таком порядке.

2 голосов
/ 23 июля 2011

Компиляторы уже перемещают код инварианта цикла за пределы цикла. Эта оптимизация известна как " Движение по инвариантному циклу " или "Подъемные инварианты".

Если вы хотите знать, как это влияет на производительность, то единственный способ узнать это - попробовать. Я полагаю, что если вы делаете это 200 000 раз, то это, безусловно, может повлиять на производительность (если компилятор еще не сделал этого для вас).

2 голосов
/ 23 июля 2011

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

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

1 голос
/ 23 июля 2011

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

Но если это не такне кажется ли это разумной попыткой, а затем рассчитайте, ЕСЛИ это на самом деле занимает больше времени, чем вам требуется.

...