Як падняць да ўлады работ? Ці варта выкарыстоўваць Pow (х, 2)?

Гэта больш эфектыўна рабіць множанне, чым падняць да ўлады 2 у C ++?

Я спрабую зрабіць канчатковыя дэталёвыя аптымізацыі. Ці будзе лячыць кампілятар х * х гэтак жа, як магутна (х, 2)? Калі я правільна памятаю, множанне было лепш па нейкай прычыне, але, магчыма, гэта не мае значэння ў C ++ 11.

дзякуй

7
Я ўяўляю х << 1 з'яўляецца тое, што на самой справе адбываецца.
дададзена аўтар Hunter McMillen, крыніца
Залежыць ад таго, ці прымае аптымізатар (або рэалізацыя функцыянальнага напрамкі магчыма) клапаціцца пра яго. Паглядзіце на выпрацоўваемую зборцы або бенчмарку яго.
дададзена аўтар chris, крыніца
Я, вядома, спадзяюся, што кампілятар не будзе ставіцца да х * х так жа, як х ^ 2 , паколькі ^ з'яўляецца XOR не Паў .
дададзена аўтар syam, крыніца
<�Код> х ^ 2 гэта <�я> не </я> падняць да ўлады 2!
дададзена аўтар Lol4t0, крыніца
ах да прабачце, я меў на ўвазе Pow замест ^
дададзена аўтар user2381422, крыніца

8 адказы

Калі вы параўноўваеце множанне з Магутны() стандартная функцыя бібліятэкі, то так, множанне, безумоўна, хутчэй.

20
дададзена
так, я меў на ўвазе Паў, дзякуй!
дададзена аўтар user2381422, крыніца
Мне трэба пачакаць 5 хвілін, каб прыняць ваш адказ;)
дададзена аўтар user2381422, крыніца

Я наогул, вы не павінны турбавацца аб піка-аптымізацый, як, што, калі ў вас ёсць <�моцны> доказы , што ёсць хот-спот (г.зн. калі вы не прафіляваны код у рэальных сцэнарах і вызначылі канкрэтны кавалак код. Акрамя таго, майце на ўвазе, што вашыя разумныя трукі на самай справе можа прывесці да рэгрэсіі прадукцыйнасці ў новых працэсарах, дзе вашыя здагадкі больш не трымаюць.

Алгарытмічныя змены, дзе вы атрымаеце максімальную аддачу ад выдаткаванага вылічальнага. Засяродзьцеся на гэтым.

Луджанай з множання і рабіць разумныя бітавую калёсы, запрэжаныя вол ... а не так шмат выбуху там * Паколькі цяперашняе пакаленне аптымізуюць кампілятараў сапраўды <�моцнае> цалкам выдатна на іх працы. Гэта не азначае, што яны не могуць біць. Яны могуць, але не так лёгка, і, верагодна, толькі некалькі чалавек, як Agner туман.

* Ёсць, вядома, выключэнні.

6
дададзена
+1 за «Яны могуць, але не так лёгка, і, верагодна, толькі некалькі чалавек, як Agner туман.» Хіба гэта не праўда!
дададзена аўтар Marc Claesen, крыніца
@MikeS Розніца можа быць алгарытмічнага канцэптуальна, але я ўпэўнены, што кампілятар разумее, што POW і што семантыка мае і таму можа (як правіла) аптымізаваць яго даволі добра само па сабе. Так што, калі няма <�б> жорсткі доказы таго, што гэта кропка доступу, такога роду рэчы варта разглядаць як мікра-аптымізацыі.
дададзена аўтар Nik Bougalis, крыніца
Я не згодны з вамі; як на самой справе, я думаю, мы згодныя канцэптуальна, але падыходзіць да гэтага пытання з трохі рознымі кутамі. Я, вядома, лічу, што трэба паспрабаваць напісаць эфектыўны код, каб пачаць з, і гэта азначае, што навучанне, што робіць і не робіць розніцу ў , што кантэкст. Але гэта цалкам адрозніваецца ад мікра-аптымізацыі, як вы ідзяце.
дададзена аўтар Nik Bougalis, крыніца
Цікава, што розніца паміж Магутны() і множання на самай справе алгарытмічная розніца. ;) Разгледзім, калі ОП запытаўся пра тое ж самае з іншым прыкладам і фармулёўкі: «Паў (х, 8) выказвае свой намер больш выразна, чым х <�я> х </я> х <�я> х </я> х < я> х </я> х <�я х.> Ці з'яўляецца множанне хутчэй? » Вы маглі б назваць гэта піка-аптымізацыі, але паходзіць ад Магутны() для множання тэхнічна алгарытмічная (+ канстанта) паляпшэнне. (... і ў параўнанні з наіўным паслядоўным памнажэннем, "x2 = х х; х4 = х2 * х2; адказ = x4 * x4;". Таксама handcoded пашырэння алгарытмічная палепшанай спаважнаю функцыі цэлага ліку)
дададзена аўтар Mike S, крыніца
Ёсць яшчэ дзве праблемы: 1.) Прымаючы гэта стаўленне праз ваш кодавую азначае, што вы маглі б мець цэлую кучу Магутны() 's, які павінен быць заменены множання (плюс сотні падобных паўсюдныя праблемы). Пытанні прадукцыйнасці часта ізаляваныя на «некалькі гарачых кропак», але толькі тады, калі праграма была закадаваная ў звыкла эфектыўным спосабам, каб пачаць з. Напісанне усё, што ад «прадукцыйнасці апошняга» пункт гледжання азначае, што замест некалькіх кропак доступу, праграма можа быць паслядоўна павольна усюды (часцей, як людзі ўсё больш і больш злоўжыванняў/растрачваць ў «заўчаснай аптымізацыі» выслоўе).
дададзена аўтар Mike S, крыніца
2.) Пытанні, як гэта важна, таму што яны не ізаляваны, каб overanalyzing некаторыя вельмі канкрэтны блок кода. Замест гэтага яны ідыёматычны пытанні, якія дазваляюць людзям развіваць навыкі, каб эфектыўна Звыкла код рэчы на ​​пастаяннай аснове. Развіццё добрых звычак на гайкі і балты ўзроўню можа зэканоміць кучу прафілявання часу, так як колькасць намаганняў для таго, каб ізаляваць гарачыя кропкі (не кажучы ўжо правільна якая распаўсюджваецца млявасць) нашмат перавышае колькасць намаганняў для таго, каб напісаць асноўнай «будаўнічы блок» код эфектыўная ў першы раз (як толькі вы даведаліся, як).
дададзена аўтар Mike S, крыніца
Таксама сцеражыцеся сляпой веры ў кампілятарах: Нават дзесяць гадоў назад, большасць людзей мяркуецца кампілятары ажыццяўляецца аптымізацый ў маштабе яны да гэтага часу не сёння. (На ўзроўні мікра-аптымізацыі, планавання інструкцый па-ранейшаму выйграе ад перапрызначэння крыніцы радкоў кода!) Пау() рэдка замяняюцца цэлымі ўбудаванымі функцыямі: Звычайна поўны int-> float-> парашковым> Int зроблена, і Паў не можа быць аптымізаваныя, так як Ф.П. матэматыка не з'яўляецца асацыятыўнай. Хуткі тэст: З GCC 4.8, Паў (я, 2) гэтак жа хутка, як я я, але Паў (я, 4) у 115 разоў больш павольна, чым я I , З Clang 3.3, гэта 337 разоў больш павольна, так як яна аптымізуе размнажаецца лепш.
дададзена аўтар Mike S, крыніца
Проста ўбачыў свой каментар: Micro-аптымізацыі, як вы ідзяце жорстка павольна/непрадуктыўны шлях да кода, асабліва калі захапіцца і напісаць код нечытэльным біт круціў (які, верагодна, не дапаможа), або калі вы праводзіце шмат час перапрызначэння інструкцыі для дапамогі планавальніка і г.д. Гэта ніколі не з'яўляецца добрай ідэяй, каб напісаць нечытэльныя "аптымізацыю" перад прафілявання, але калі вы вырашаеце паміж двума аднолькава выразнымі версіямі ідыёматычны коды распаўсюджваецца па ўсім праекту, інвестыцыі ў пачатку «звычайнага навучанне працэс », верагодна, мудры ... нават калі гэта азначае, што мікра-аптымізацыі Склад ў першы раз.
дададзена аўтар Mike S, крыніца

Калі гаворка заходзіць пра прадукцыйнасць, заўсёды робяць вымярэння для рэзервовага капіявання вашых здагадак. Ніколі не давярай тэорыі, калі ў вас ёсць тэст, які даказвае, што тэорыя права.

Акрамя таго, майце на ўвазе, што х ^ 2 робіць не выхад квадрат 2 у C ++:

#include 

int main()
{
    int x = 4;
    std::cout << (x ^ 2);//Prints 6
}

Live example.

5
дададзена

Рэалізацыя магутная (), як правіла, уключае ў сябе лагарыфмы, множанне і expononentiaton, так што гэта вызначана зойме больш часу, чым простае множанне. Большасць сучасных працэсараў высокага класа можа зрабіць множанне на пару ClockCycles для цэлалікавых значэнняў, і тузіны цыклаў для множання з якая плавае коскі. экспоненцирование ажыццяўляецца альбо ў комплексе (microcoded) інструкцыі, прымае некалькі дзясяткаў ці больш цыклаў, або ў выглядзе серыі множання і дапаўненняў (як правіла, з чаргаваннем станоўчых і адмоўных лікаў, але не вядома). Узвядзенне аналагічны працэс.

На ніжніх працэсараў дыяпазону (напрыклад, ARM ці больш старых працэсараў x86), вынікі яшчэ горш. Сотні цыклаў у адну аперацыю з якая плавае кропкай, ці ў некаторых працэсарах, разлікі, нават з якая плавае кропкай шэраг цэлалікавых аперацый, якія выконваюць тыя ж крокі, інструкцыі з якая плавае кропкай на больш прасунутых працэсараў, так што час, неабходнае для Pow() можа быць тысячы цыклаў, у параўнанні з тузін або каля таго для множання.

Які б выбар выкарыстоўваецца, увесь разлік будзе значна больш, чым простае множанне.

<�Код> POW() функцыя карысная, калі паказчык з'яўляецца альбо вялікім, альбо не з'яўляецца цэлым лікам. Нават пры адносна вялікіх паказчыкаў, можна зрабіць разлік шляхам ўзвядзення ў квадрат або кубатуры некалькі разоў, і гэта будзе хутчэй, чым Паў() .

Вядома, часам кампілятар можа быць у стане зразумець, што вы хочаце зрабіць, і зрабіць гэта ў выглядзе паслядоўнасці множання ў якасці аптымізацыі. Але я б не стаў спадзявацца на гэта.

Нарэшце, як заўсёды, на пытанні прадукцыйнасці: Калі гэта сапраўды важна, каб ваш код, а затым вымераць яго - ваш кампілятар можа быць разумнейшыя, чым вы тонкі. Калі прадукцыйнасць не важная, а затым выканаць разлік, які з'яўляецца робіць код найбольш чытаным.

2
дададзена

pow is a library function, not an operator. Unless the compiler is able to optimize out the call (which it legitimately do by taking advantage of its knowledge of the behavior of the standard library functions), calling pow() will impose the overhead of a function call and of all the extra stuff the pow() function has to do.

Другі аргумент POW() не павінен быць цэлым лікам; напрыклад Паў (х, 1,0/3,0) дасць вам набліжэнне кораня кубічнага з X . Гэта будзе патрабаваць некаторых даволі складаных вылічэнняў. Ён можа зваліцца назад да шматразовага множаньню, калі другі аргумент з'яўляецца невялікім Інтэгральным значэннем, але тады ён павінен праверыць, што падчас выканання.

Калі нумар, які вы хочаце квадрат ўяўляе сабой цэлы лік, Паў будзе ўключаць у сябе пераўтварэнне яго ў двайны , затым пераўтварэнне вынік назад да цэлага тыпу, які з'яўляецца адносна дарагім і можа прывесці да тонкія памылкі акруглення.

Выкарыстоўваючы х * х вельмі верагодна, будзе хутчэй і надзейней, чым Pow (х, 2) , і гэта прасцей. (У большасці кантэкстаў, прастата і надзейнасць з'яўляюцца больш важнымі фактарамі, чым хуткасць.)

1
дададзена

C/C ++ не родны «ўлада» аператара. <�Код> ^ з'яўляецца пабітавае якое выключае або (XOR). Такім чынам, сказана, Паў функцыя, верагодна, што вы шукаеце.

На самай справе, для ўзвядзення ў квадрат цэлага ліку, х * х з'яўляецца самым непасрэдным чынам, і некаторы кампілятар можа аптымізаваць яго для працы машыны пры наяўнасці.

0
дададзена

you should look into boost.math's pow function template. it takes the exponent as template parameter and automatically calculate, for example, pow<4>(x) as (x*x)*(x*x).

Http://www.boost.org/doc/libs/1_53_0/libs/math/doc/sf_and_dist/html/math_toolkit/special/powers/ct_pow.html

0
дададзена

You should read the following link Why doesn't GCC optimize a*a*a*a*a*a to (a*a*a)*(a*a*a)?

Паў (х, 2), хутчэй за ўсё, будзе ператвораны ў е х. Тым не менш, вышэйшыя сілы, такія як магутны (х, 4) не могуць быць зроблены як аптымальным чынам, наколькі гэта магчыма. Напрыклад, Магутны (х, 4) можа быць зроблена ў 3 множання х х <�ет> х х ці ў два (х <�ет> х) (х * х) у залежнасці ад наколькі строгія вам патрабуецца вызначэнне з якая плавае коскі, каб быць (па змаўчанні я думаю, што ён будзе выкарыстоўваць 3 множання.

Было б цікава паглядзець, што, напрыклад, Магутны (х * х, 2) вырабляе і без -ffast-мат.

0
дададзена