GCC විසින් * a * a * a * a * a (a * a * a) * (a * a * a) ප්‍රශස්තිකරණය නොකරන්නේ ඇයි?


2125

මම විද්‍යාත්මක යෙදුමක් මත සංඛ්‍යාත්මක ප්‍රශස්තිකරණයක් කරමි. මා දුටු එක් දෙයක් නම්, GCC විසින් ඇමතුම pow(a,2)සම්පාදනය කිරීමෙන් එය ප්‍රශස්ත කරනු ඇති a*aනමුත් ඇමතුම pow(a,6)ප්‍රශස්තිකරණය කර නොමැති අතර ඇත්ත වශයෙන්ම පුස්තකාල ක්‍රියාකාරිත්වය අමතනු ඇත pow, එමඟින් කාර්ය සාධනය බෙහෙවින් මන්දගාමී වේ. (ඊට වෙනස්ව, ක්‍රියාත්මක කළ හැකි ඉන්ටෙල් සී ++ සම්පාදකයicc පුස්තකාල ඇමතුම ඉවත් කරයි pow(a,6).)

මම කුතුහලයෙන් සිටිමි මම වෙනුවට විට බව ය pow(a,6)සමඟ a*a*a*a*a*a"ගල්ෆ් 4.5.1 හා විකල්ප භාවිතා -O3 -lm -funroll-loops -msse4" එය 5 භාවිතා කරයි, mulsdඋපදෙස්:

movapd  %xmm14, %xmm13
mulsd   %xmm14, %xmm13
mulsd   %xmm14, %xmm13
mulsd   %xmm14, %xmm13
mulsd   %xmm14, %xmm13
mulsd   %xmm14, %xmm13

මම ලියන අතර (a*a*a)*(a*a*a), එය නිපදවනු ඇත

movapd  %xmm14, %xmm13
mulsd   %xmm14, %xmm13
mulsd   %xmm14, %xmm13
mulsd   %xmm13, %xmm13

එමඟින් ගුණ කිරීමේ උපදෙස් ගණන 3 iccදක්වා අඩු කරයි .

සම්පාදකයින් මෙම ප්‍රශස්තිකරණ උපක්‍රමය හඳුනා නොගන්නේ ඇයි?


13
“පවු (අ, 6) හඳුනා ගැනීම” යන්නෙන් අදහස් කරන්නේ කුමක්ද?
වරුන් මාදියත්

661
අම්ම ... ඔබ දන්නවා ඇති වූ යම් යම් (අ a හා එය අ) * (අ අ * අ), නෑ ඔයා ඉපිලුම් ලක්ෂ්ය සංඛ්යා හා සමාන නොවේ ද? ඔබට ඒ සඳහා -funsafe-math හෝ -ffast-math හෝ යමක් භාවිතා කිරීමට සිදුවේ.
ඩේමන්

108
ඩේවිඩ් ගෝල්ඩ්බර්ග් විසින් රචිත "පාවෙන ලක්ෂ්‍ය අංක ගණිතය පිළිබඳව සෑම පරිගණක විද්‍යා ist යෙක්ම දැනගත යුතු දේ" කියවීමට මම ඔබට යෝජනා කරමි: download.oracle.com/docs/cd/E19957-01/806-3568/… ඉන්පසු ඔබට වඩාත් පූර්ණ අවබෝධයක් ලැබෙනු ඇත. ඔබ දැන් ගමන් කළ තාර වළ!
ෆිල් ආම්ස්ට්‍රෝං

189
පරිපූර්ණ සාධාරණ ප්‍රශ්නයක්. අවුරුදු 20 කට පෙර මම එකම පොදු ප්‍රශ්නය ඇසූ අතර, එම තනි බාධකය තලා දැමීමෙන්, මොන්ටේ කාලෝ අනුකරණයක ක්‍රියාත්මක කිරීමේ කාලය පැය 21 සිට පැය 7 දක්වා අඩු කළෙමි. මෙම ක්‍රියාවලියේදී අභ්‍යන්තර ලූපයේ කේතය ට්‍රිලියන 13 ක් ක්‍රියාත්මක කරන ලද නමුත් එය රාත්‍රී රාත්‍රී කවුළුවකට අනුකරණය කර ඇත. (පහත පිළිතුර බලන්න)

23
සමහර විට (a*a)*(a*a)*(a*a)ද මිශ්‍රණයට විසි කරන්න . එකම ගුණ කිරීමේ සංඛ්‍යාව, නමුත් බොහෝ විට වඩාත් නිවැරදි ය.
රොක් ක්‍රල්ජ්

Answers:


2742

නිසා ඉපිලුම් ලක්ෂ්ය ගණිතය Associative නොවේ . පාවෙන ලක්ෂ්‍ය ගුණ කිරීමේ දී ඔබ ක්‍රියාකරන ආකාරය පිළිතුරේ සංඛ්‍යාත්මක නිරවද්‍යතාවයට බලපායි.

එහි ප්‍රති As ලයක් වශයෙන්, බොහෝ සම්පාදකයින් පාවෙන ලක්ෂ්‍ය ගණනය කිරීම් නැවත සකස් කිරීම පිළිබඳව ඉතා සාම්ප්‍රදායික වන අතර, පිළිතුර එලෙසම පවතිනු ඇති බවට ඔවුන්ට සහතික විය නොහැකි නම් හෝ සංඛ්‍යාත්මක නිරවද්‍යතාව ගැන ඔබ තැකීමක් නොකරයි. උදාහරණයක් ලෙස: -fassociative-mathවිකල්පය gcc ඉපිලුම් ලක්ෂ්ය reassociate කිරීමට ඉඩ සලසා දෙයි gcc කිරීම හෝ පවා -ffast-mathවේගය එරෙහිව නිරවද්යතාවය වඩාත් ආක්රමණශීලී එබැව්න් ගවේෂණශීලි ඉඩ සලසා දෙයි විකල්පය.


10
ඔව්. -Fast-math සමඟ එය කරන්නේ එවැනි ප්‍රශස්තිකරණයකි. හොඳ අදහස! නමුත් අපගේ කේතය වේගයට වඩා නිරවද්‍යතාව ගැන සැලකිලිමත් වන බැවින් එය සම්මත නොකිරීමට වඩා හොඳ විය හැකිය.
xis

19
IIRC C99 විසින් සම්පාදකයාට එවැනි "අනාරක්ෂිත" FP ප්‍රශස්තිකරණය කිරීමට ඉඩ දෙයි, නමුත් GCC (x87 හැර වෙනත් ඕනෑම දෙයක්) IEEE 754 අනුගමනය කිරීමට සාධාරණ උත්සාහයක් දරයි - එය "දෝෂ සීමාවන්" නොවේ; එකම නිවැරදි පිළිතුරක් ඇත.
ටී.සී.

14
ක්‍රියාත්මක කිරීමේ තොරතුරු powමෙහි හෝ එහි නොමැත; මෙම පිළිතුරෙහි සඳහනක්වත් නැත pow.
ස්ටීවන් කැනන්

15
RedNR: නැවත සම්බන්ධ වීමට ඉඩ දීම ICC පැහැර හැර ඇත. ඔබට සම්මත අනුකූල හැසිරීමක් ලබා ගැනීමට අවශ්‍ය නම්, ඔබ -fp-model preciseඅයිසීසී සමඟ සැකසිය යුතුය. clangසහ gccපෙරනිමිය දැඩි අනුකූලතාවයට නැවත නැවත සම්බන්ධ කිරීම.
ස්ටීවන් කැනන්

49
@xis, එය ඇත්ත වශයෙන්ම -fassociative-mathසාවද්‍ය නොවේ; එය හුදෙක් බව ය a*a*a*a*a*aසහ (a*a*a)*(a*a*a)වෙනස් වේ. එය නිරවද්යතාව ගැන නොවේ; එය ප්‍රමිති අනුකූලතාව සහ තදින් පුනරාවර්තනය කළ හැකි ප්‍රති results ල ගැන ය, උදා: ඕනෑම සම්පාදකයෙකුගේ ප්‍රති results ල. පාවෙන ලක්ෂ්‍ය අංක දැනටමත් නිශ්චිත නැත. සම්පාදනය කිරීම කලාතුරකින් නුසුදුසු ය -fassociative-math.
පෝල් ඩ්‍රැපර්

653

Lambdageek නිවැරදිව associativity ඉපිලුම් ලක්ෂ්ය සංඛ්යා සඳහා පැවැත්වීමට නැති නිසා, වන "ප්රශස්තිකරණය" බව පෙන්වා දෙයිa*a*a*a*a*aකිරීමට(a*a*a)*(a*a*a)වටිනාකම වෙනස් විය හැක. C99 විසින් එය තහනම් කර ඇත්තේ මේ නිසාය (පරිශීලකයා විසින් විශේෂයෙන් අවසර දී නොමැති නම්, සම්පාදක ධජය හෝ ප්‍රාග්මා හරහා). සාමාන්‍යයෙන් උපකල්පනය වන්නේ ක්‍රමලේඛකයා ඇය කළ දේ යම් හේතුවක් නිසා ලියා ඇති අතර සම්පාදකයා එයට ගරු කළ යුතු බවයි. ඔබට අවශ්‍ය(a*a*a)*(a*a*a)නම් එය ලියන්න.

එය ලිවීමට වේදනාවක් විය හැකියි. ඔබ භාවිතා කරන විට සම්පාදකයාට [ඔබ සලකන දේ] නිවැරදි දේ කළ නොහැක්කේ ඇයි pow(a,6)? මන්ද එය වැරදි දෙයකි. හොඳ ගණිත පුස්තකාලයක් ඇති වේදිකාවක, pow(a,6)හෝ a*a*a*a*a*aඊට වඩා සැලකිය යුතු තරම් නිවැරදි ය (a*a*a)*(a*a*a). සමහර දත්ත සැපයීම සඳහා, මම මගේ මැක් ප්‍රෝ හි කුඩා අත්හදා බැලීමක් කළෙමි, [1,2) අතර ඇති සියලුම තනි නිරවද්‍යතාවයෙන් යුත් පාවෙන අංක සඳහා ඩොලර් 6 ක් තක්සේරු කිරීමේ දරුණුතම දෝෂය මැනීම:

worst relative error using    powf(a, 6.f): 5.96e-08
worst relative error using (a*a*a)*(a*a*a): 2.94e-07
worst relative error using     a*a*a*a*a*a: 2.58e-07

powගුණ කිරීමේ ගසක් වෙනුවට භාවිතා කිරීම 4 සාධකයකින් බැඳී ඇති දෝෂය අඩු කරයි . සම්පාදකයින් විසින් පරිශීලකයා විසින් එසේ කිරීමට බලපත්‍ර ලබා නොගතහොත් (උදා: හරහා -ffast-math) දෝෂ වැඩි කරන “ප්‍රශස්තිකරණය” නොකළ යුතුය .

ආන්තරික ගුණ කිරීමේ ගසක් ජනනය කළ යුතු __builtin_powi(x,n)විකල්පයක් ලෙස GCC සපයන බව සලකන්න pow( ). කාර්ය සාධනය සඳහා නිරවද්‍යතාවයෙන් වෙළඳාම් කිරීමට ඔබට අවශ්‍ය නම් එය භාවිතා කරන්න, නමුත් වේගවත් ගණිතය සක්‍රීය කිරීමට අවශ්‍ය නැත.


29
විෂුවල් සී ++ මගින් පවු () හි 'වැඩිදියුණු කළ' අනුවාදයක් සපයන බව සලකන්න. ආයාචනා කිරීම මගින් _set_SSE2_enable(<flag>)සමඟ flag=1, එය කළ හැකි නම්, SSE2 භාවිතා කරනු ඇත. මෙය නිරවද්‍යතාව ටිකක් අඩු කරයි, නමුත් වේගය වැඩි කරයි (සමහර අවස්ථාවල). MSDN: _set_SSE2_enable () සහ pow ()
TkTech

18
KTkTech: ඕනෑම අඩු නිරවද්‍යතාවයක් සිදුවන්නේ මයික්‍රොසොෆ්ට් ක්‍රියාත්මක කිරීම නිසා මිස භාවිතා කළ ලේඛනයේ ප්‍රමාණයෙන් නොවේ. පුස්තකාල ලේඛකයා එතරම් පෙළඹී ඇත්නම්, බිටු 32 ක් පමණක් භාවිතා කරමින් නිවැරදිව වටකුරු ලබා දිය හැකිය pow. බොහෝ x87 මත පදනම් වූ powක්‍රියාත්මක කිරීම් වලට වඩා නිරවද්‍ය වන SSE මත පදනම් වූ ක්‍රියාත්මක කිරීම් ඇති අතර වේගය සඳහා යම් නිරවද්‍යතාවයක් වෙළඳාම් කරන ක්‍රියාත්මක කිරීම් ද ඇත.
ස්ටීවන් කැනන්

9
KTkTech: ඇත්ත වශයෙන්ම, මට පැහැදිලි කිරීමට අවශ්‍ය වූයේ නිරවද්‍යතාව අඩුවීමට හේතු වී ඇත්තේ පුස්තකාල ලේඛකයින් විසින් කරන ලද තේරීම් මිස SSE භාවිතය සඳහා සහජයෙන්ම නොවේ.
ස්ටීවන් කැනන්

7
සාපේක්ෂ දෝෂ ගණනය කිරීම සඳහා ඔබ මෙහි “රන් ප්‍රමිතිය” ලෙස භාවිතා කළේ කුමක් දැයි දැන ගැනීමට මම උනන්දු වෙමි - සාමාන්‍යයෙන් එය එසේ වනු ඇතැයි මම අපේක්ෂා කළෙමි a*a*a*a*a*a, නමුත් පෙනෙන හැටියට එය එසේ නොවේ! :)
j_random_hacker

8
@j_random_hacker: මම තනි-නිරවද්යතාවයකින් ප්රතිඵල සංසන්දනය කර දා පටන් මේ දක්වා, රන් සම්මත සඳහා ද්විත්ව නිරවද්යතාවයකින් ප්රමාණවත්වේ - A සිට දෝෂයක් ඇති වූ යම් යම් ද්විත්ව දී ගණනය * බෙහෙවින් තනි-නිරවද්යතාව ගණනය ඕනෑම වැරදි වඩා කුඩා.
ස්ටීවන් කැනන්

168

තවත් සමාන අවස්ථාවක්: බොහෝ සම්පාදකයින් ප්‍රශස්තිකරණය නොකරනු a + b + c + dඇත (a + b) + (c + d)(මෙය දෙවන ප්‍රකාශනය වඩා හොඳින් නල මාර්ගගත කළ හැකි බැවින් මෙය ප්‍රශස්තිකරණයකි) සහ එය ලබා දී ඇති ආකාරයට ඇගයීමට ලක් කරන්න (එනම් (((a + b) + c) + d)). මෙයද කෙළවරේ සිදුවීම් නිසාය:

float a = 1e35, b = 1e-5, c = -1e35, d = 1e-5;
printf("%e %e\n", a + b + c + d, (a + b) + (c + d));

මෙය ප්‍රතිදානය කරයි 1.000000e-05 0.000000e+00


10
මෙය හරියටම සමාන නොවේ. එකතුව / අඩු කිරීමේ අනුපිළිවෙලට වඩා ගුණ කිරීමේ / බෙදීම් අනුපිළිවෙල වෙනස් කිරීම (0 න් බෙදීම හැර) ආරක්ෂිත වේ. මගේ නිහතමානී මතය අනුව, සම්පාදකයා විසින් බහු / ආශ්‍රිත ඇසුරු කිරීමට උත්සාහ කළ යුතුය. මක්නිසාද යත්, එසේ කිරීමෙන් සමස්ත මෙහෙයුම් සංඛ්‍යාව අඩු වන අතර කාර්ය සාධන ලාභයට අමතරව නිරවද්‍ය වාසියකි.
CoffeDeveloper

4
Ari ඩාරියෝඕ: එය ආරක්ෂිත නොවේ. ගුණ කිරීම හා බෙදීම on ාතයේ එකතු කිරීම හා අඩු කිරීම සමාන වන අතර අනුපිළිවෙල වෙනස් කිරීමෙන් තාවකාලිකයන් on ාතයේ විය හැකි පරාසය ඉක්මවා යා හැක. (හරියටම නොවේ එම එම නිපුනයා නිරවද්යතාවයකින් අහිමිවන නැති නිසා ... නමුත් නියෝජනය තවමත් බෙහෙවින් සීමා වන අතර, නැවත අනුපිළිවෙලට සෑදීමේ unrepresentable වටිනාකම් ඇති විය හැක)
බෙන් Voigt

8
මම හිතන්නේ ඔබට කැල්කියුලස් පසුබිමක් නැති වී ඇත. අංක 2 ගුණ කිරීම හා බෙදීම එකම දෝෂයක් හඳුන්වා දෙයි. සංඛ්‍යා 2 අඩු කිරීම / එකතු කිරීම විශාල දෝෂයක් හඳුන්වා දිය හැකි අතර විශේෂයෙන් සංඛ්‍යා 2 විශාලත්වයේ අනුපිළිවෙල වෙනස් වන විට, එය අවසාන දෝෂයේ සුළු වෙනසක් හඳුන්වා දෙන බැවින් උප / එකතු කිරීමට වඩා ආරක්ෂිත නැවත සැකසීමේ මුල් / බෙදීම ආරක්ෂිත වේ.
කෝපි ඩිවෙලොපර්

8
Ari ඩාරියෝඕ: අවදානම mul / div සමඟ වෙනස් වේ: නැවත සකස් කිරීම එක්කෝ අවසාන ප්‍රති result ලයෙහි නොසැලකිලිමත් වෙනසක් ඇති කරයි, නැතහොත් on ාතකය යම් වේලාවක පිටාර ගැලීම (එයට පෙර නොතිබූ තැන) සහ ප්‍රති result ලය විශාල වශයෙන් වෙනස් වේ (විභව + inf හෝ 0).
පීටර් කෝර්ඩ්ස්

@GameDeveloper අනපේක්ෂිත ආකාරවලින් නිරවද්‍ය වාසියක් පැනවීම අතිශයින්ම ගැටළු සහගතය.
කුතුහලයෙන්

80

ෆෝට්රාන් (විද්‍යාත්මක පරිගණනය සඳහා නිර්මාණය කර ඇති) සතුව බල සැපයුම්කරුවෙකු සිටින අතර, මා දන්නා පරිදි ෆෝට්රාන් සම්පාදකයින් සාමාන්‍යයෙන් ඔබ විස්තර කරන දෙයට සමාන ආකාරයකින් පූර්ණ සංඛ්‍යා දක්වා ඉහළ නැංවීම ප්‍රශස්ත කරනු ඇත. C / C ++ අවාසනාවකට බල ක්‍රියාකරුවෙකු නොමැත, පුස්තකාල ක්‍රියාකාරිත්වය පමණි pow(). මෙය ස්මාර්ට් සම්පාදකයින්ට විශේෂ ලෙස සැලකීම powහා විශේෂ අවස්ථා සඳහා වේගවත් ආකාරයකින් ගණනය කිරීම වළක්වන්නේ නැත , නමුත් ඔවුන් එය අඩුවෙන් කරන බව පෙනේ ...

මීට වසර කිහිපයකට පෙර මම පූර්ණ සංඛ්‍යා ප්‍රශස්ත ආකාරයකින් ගණනය කිරීම වඩාත් පහසු කිරීමට උත්සාහ කළ අතර පහත සඳහන් කරුණු ඉදිරිපත් කළෙමි. එය C ++ මිස C නොවේ, නමුත් තවමත් රඳා පවතින්නේ සම්පාදකයා යම් යම් දේ ප්‍රශස්තිකරණය කරන්නේ කෙසේද යන්න පිළිබඳව තරමක් බුද්ධිමත් වීම මත ය. කෙසේ වෙතත්, එය ප්‍රායෝගිකව ඔබට ප්‍රයෝජනවත් වේ යැයි සිතමු:

template<unsigned N> struct power_impl;

template<unsigned N> struct power_impl {
    template<typename T>
    static T calc(const T &x) {
        if (N%2 == 0)
            return power_impl<N/2>::calc(x*x);
        else if (N%3 == 0)
            return power_impl<N/3>::calc(x*x*x);
        return power_impl<N-1>::calc(x)*x;
    }
};

template<> struct power_impl<0> {
    template<typename T>
    static T calc(const T &) { return 1; }
};

template<unsigned N, typename T>
inline T power(const T &x) {
    return power_impl<N>::calc(x);
}

කුතුහලය දනවන අය සඳහා පැහැදිලි කිරීම: මෙය බලයන් ගණනය කිරීම සඳහා ප්‍රශස්ත ක්‍රමයක් සොයා නොගනී, නමුත් ප්‍රශස්ත විසඳුම සොයා ගැනීම එන්පී-සම්පුර්ණ ගැටළුවක් වන අතර මෙය කෙසේ හෝ කුඩා බලවතුන් සඳහා පමණක් කිරීම වටී (භාවිතා කිරීමට වඩා වෙනස්ව pow), කලබල වීමට හේතුවක් නැත විස්තර සහිතව.

ඉන්පසු එය භාවිතා කරන්න power<6>(a).

මෙය බලතල ටයිප් කිරීම පහසු කරයි ( aපරෙන්ස් සමඟ තත්පර 6 ක් අක්ෂර වින්‍යාසය කිරීමට අවශ්‍ය නැත ), සහ ඔබට වන්දි ගෙවන සාරාංශය-ffast-math වැනි නිරවද්‍යතාව මත රඳා පවතින යමක් තිබේ නම් (මේ ආකාරයේ ප්‍රශස්තිකරණයක් ලබා ගැනීමට ඔබට ඉඩ සලසයි) (මෙහෙයුම් අනුපිළිවෙල අත්‍යවශ්‍ය වන උදාහරණයක්) .

මෙය C ++ බව ඔබට බොහෝ විට අමතක කළ හැකි අතර එය C වැඩසටහනේ භාවිතා කරන්න (එය C ++ සම්පාදකයෙකු සමඟ සම්පාදනය කරන්නේ නම්).

මෙය ප්‍රයෝජනවත් වේ යැයි සිතමි.

සංස්කරණය කරන්න:

මගේ සම්පාදකයාගෙන් මට ලැබෙන්නේ මෙයයි:

සඳහා a*a*a*a*a*a,

    movapd  %xmm1, %xmm0
    mulsd   %xmm1, %xmm0
    mulsd   %xmm1, %xmm0
    mulsd   %xmm1, %xmm0
    mulsd   %xmm1, %xmm0
    mulsd   %xmm1, %xmm0

සඳහා (a*a*a)*(a*a*a),

    movapd  %xmm1, %xmm0
    mulsd   %xmm1, %xmm0
    mulsd   %xmm1, %xmm0
    mulsd   %xmm0, %xmm0

සඳහා power<6>(a),

    mulsd   %xmm0, %xmm0
    movapd  %xmm0, %xmm1
    mulsd   %xmm0, %xmm1
    mulsd   %xmm0, %xmm1

36
ප්‍රශස්ත බල වෘක්ෂය සොයා ගැනීම දුෂ්කර විය හැකි නමුත් එය කුඩා බලයන් සඳහා පමණක් සිත්ගන්නා සුළු බැවින් පැහැදිලි පිළිතුර නම් එය එක් වරක් කල්තියා ගණනය කිරීමයි (නුත් 100 ක් දක්වා වගුවක් සපයයි) සහ එම දෘ c කේත වගුව භාවිතා කරන්න (එයයි gcc අභ්‍යන්තරව පවී සඳහා කරන්නේ) .
මාක් ග්ලිස්

7
නවීන සකසනයන්හි වේගය ප්‍රමාදයෙන් සීමා වේ. උදාහරණයක් ලෙස, ගුණ කිරීමේ ප්‍රති result ලය චක්‍ර පහකට පසුව ලබා ගත හැකිය. එවැනි තත්වයක් තුළ, යම් බලයක් නිර්මාණය කිරීමට වේගවත්ම ක්‍රමය සොයා ගැනීම වඩා උපක්‍රමශීලී විය හැකිය.
gnasher729

3
සාපේක්ෂ වටකුරු දෝෂය සඳහා අවම ඉහළ සීමාව ලබා දෙන බල වෘක්ෂය හෝ අඩුම සාමාන්‍ය සාපේක්ෂ වටකුරු දෝෂය සොයා ගැනීමටද ඔබට උත්සාහ කළ හැකිය.
gnasher729

1
බූස්ට් සඳහා ද මේ සඳහා සහය ඇත, උදා: boost :: math :: pow <6> (n); මම හිතන්නේ එය පොදු සාධක උකහා ගැනීමෙන් ගුණ කිරීමේ සංඛ්‍යාව අඩු කිරීමට පවා උත්සාහ කරයි.
gast128

අවසාන එක (a ** 2) ට සමාන බව සලකන්න ** 3
minmaxavg

62

GCC ඇත්ත වශයෙන්ම පූර්ණ සංඛ්‍යාවක් වන විට ප්‍රශස්තිකරණය a*a*a*a*a*aකරයි (a*a*a)*(a*a*a). මම මෙම විධානය සමඟ උත්සාහ කළෙමි:

$ echo 'int f(int x) { return x*x*x*x*x*x; }' | gcc -o - -O2 -S -masm=intel -x c -

Gcc ධජ විශාල ප්‍රමාණයක් ඇති නමුත් කිසිවක් විසිතුරු නොවේ. ඔවුන් අදහස් කරන්නේ: stdin වෙතින් කියවන්න; O2 ප්‍රශස්තිකරණ මට්ටම භාවිතා කරන්න; ද්විමය වෙනුවට ප්‍රතිදාන එකලස් කිරීමේ භාෂා ලැයිස්තුගත කිරීම; ලැයිස්තුගත කිරීම ඉන්ටෙල් එකලස් කිරීමේ භාෂා සින්ටැක්ස් භාවිතා කළ යුතුය; ආදානය සී භාෂාවෙන් ඇත (සාමාන්‍යයෙන් භාෂාව ආදාන ගොනු දිගුවෙන් අනුමාන කෙරේ, නමුත් stdin වෙතින් කියවීමේදී ගොනු දිගුවක් නොමැත); stdout වෙත ලියන්න.

නිමැවුමේ වැදගත් කොටස මෙන්න. එකලස් කිරීමේ භාෂාවෙන් සිදුවන්නේ කුමක්ද යන්න දැක්වෙන අදහස් කිහිපයක් සමඟ මම එය විවරණය කර ඇත:

; x is in edi to begin with.  eax will be used as a temporary register.
mov  eax, edi  ; temp = x
imul eax, edi  ; temp = x * temp
imul eax, edi  ; temp = x * temp
imul eax, eax  ; temp = temp * temp

මම උබුන්ටු ව්‍යුත්පන්නයක් වන ලිනක්ස් මින්ට් 16 පෙට්‍රා හි පද්ධති ජීසීසී භාවිතා කරමි. මෙන්න gcc අනුවාදය:

$ gcc --version
gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1

අනෙකුත් පෝස්ටර් සටහන් කර ඇති පරිදි, පාවෙන ලක්ෂ්‍යයේදී මෙම විකල්පය කළ නොහැකි ය, මන්ද පාවෙන ලක්ෂ්‍ය අංක ගණිතය අනුබද්ධ නොවේ.


12
පූර්ණ සංඛ්‍යා ගුණ කිරීම සඳහා මෙය නීත්‍යානුකූල වන්නේ දෙදෙනෙකුගේ අනුපූරක පිටාර ගැලීම නිර්වචනය නොකළ හැසිරීම නිසාය. පිටාර ගැලීමක් සිදුවන්නේ නම්, මෙහෙයුම් නැවත සකස් කිරීම නොසලකා එය කොතැනක හෝ සිදුවනු ඇත. ඉතින්, පිටාර ගැලීමක් නොමැති ප්‍රකාශන එකම තක්සේරු කරයි, පිටාර ගැලීම නිර්වචනය නොකළ හැසිරීමක් වන බැවින් පිටාර ගැලීම සිදුවන ස්ථානය වෙනස් කිරීම සම්පාදකයාට කමක් නැත. gcc ද මෙය unsigned intකරයි.
පීටර් කෝර්ඩ්ස්

51

මක්නිසාද යත්, බිට් 32 පාවෙන ලක්ෂ්‍ය අංකයක් - 1.024 වැනි - 1.024 නොවේ. පරිගණකයක, 1.024 යනු පරතරයකි: (1.024-e) සිට (1.024 + e) ​​දක්වා, එහිදී "e" දෝෂයක් නිරූපණය කරයි. සමහර අය මෙය සාක්ෂාත් කර ගැනීමට අපොහොසත් වන අතර, * අ * හි අත්තනෝමතික-නිරවද්‍යතා සංඛ්‍යා ගුණ කිරීමෙන් එම සංඛ්‍යා සමඟ කිසිදු දෝෂයක් ඇති නොවී විශ්වාස කෙරේ. සමහර අය මෙය වටහා ගැනීමට අපොහොසත් වීමට හේතුව සමහර විට ඔවුන් ප්‍රාථමික පාසල්වල සිදු කළ ගණිතමය ගණනය කිරීම් ය: දෝෂ රහිතව පරිපූර්ණ සංඛ්‍යා සමඟ පමණක් වැඩ කිරීම සහ ගුණ කිරීමේ දී “ඊ” නොසලකා හැරීම හරි යැයි විශ්වාස කිරීම. "පාවෙන a = 1.2", "a * a * a" සහ ඒ හා සමාන C කේත වල "e" ඇඟවුම් ඔවුන් දකින්නේ නැත.

සී ප්‍රකාශනය a * a * a * a * a * a ඇත්ත වශයෙන්ම පරිපූර්ණ සංඛ්‍යා සමඟ ක්‍රියා නොකරයි යන අදහස බොහෝ ක්‍රමලේඛකයින් හඳුනාගෙන (ක්‍රියාත්මක කිරීමට හැකි නම්), GCC සම්පාදකයා “a * a ප්‍රශස්තිකරණය සඳහා නොමිලේ වේ. * a * a * a * a ”කියන්නට” t = (a * a); t * t * t ”සඳහා කුඩා ගුණනයක් අවශ්‍ය වේ. නමුත් අවාසනාවකට මෙන්, කේතය ලියන ක්‍රමලේඛකයා සිතන්නේ "a" යනු දෝෂයක් සහිත හෝ නැති අංකයක් යැයි GCC සම්පාදකයා නොදනී. එබැවින් GCC විසින් කරනු ලබන්නේ ප්‍රභව කේතය පෙනෙන ආකාරයට පමණි - මන්ද එය GCC සිය “පියවි ඇසින්” දකින බැවිනි.

... ඔබ වගේ ක්රමලේඛකයෙක් වන දේ දැන වරක් ඔබ , ඔබ සහ ගල්ෆ් කියන්න "හේයි, ගල්ෆ්, මම මා කරන්නේ මොකක්ද කියලා!" ඒ '-ffast-ගණිත "ස්විචය භාවිතා කළ හැකිය. මෙය * a * a * a * a * a වෙනත් පෙළ කැබැල්ලක් බවට පරිවර්තනය කිරීමට GCC ට ඉඩ දෙනු ඇත - එය * a * a * a * a * a ට වඩා වෙනස් ලෙස පෙනේ - නමුත් දෝෂ කාල පරතරය තුළ තවමත් සංඛ්‍යාවක් ගණනය කරයි a * a * a * a * a * a. මෙය හරි ය, මන්ද ඔබ වැඩ කරන්නේ පරමාදර්ශී සංඛ්‍යා සමඟ නොව කාල පරතරයන් සමඟ බව ඔබ දැනටමත් දන්නා බැවිනි.


52
පාවෙන ලක්ෂ්‍ය අංක හරියටම. ඒවා ඔබ බලාපොරොත්තු වූ දේම නොවේ. එප්සිලෝන් සමඟ ඇති තාක්‍ෂණය යථාර්ථයේ දී කටයුතු කරන්නේ කෙසේද යන්න පිළිබඳ දළ විශ්ලේෂණයකි, මන්ද සත්‍ය අපේක්ෂිත දෝෂය මැන්ටිස්සා පරිමාණයට සාපේක්ෂව ය, එනම් ඔබ සාමාන්‍යයෙන් එල්එස්බී 1 ක් පමණ වන නමුත් එය වැඩි විය හැකිය ඔබ පරිස්සම් නැතිනම් සිදුකරන සෑම මෙහෙයුමක්ම පාවෙන ලක්ෂ්‍යය සමඟ සුළු නොවන කිසිවක් කිරීමට පෙර සංඛ්‍යාත්මක විශ්ලේෂකයෙකුගෙන් විමසන්න. ඔබට හැකි නම් නිසි පුස්තකාලයක් භාවිතා කරන්න.
ඩොනල් ෆෙලෝස්

3
On ඩොනල් ෆෙලෝස්: ප්‍රභව ක්‍රියාකාරීත්වය නිශ්චිත අගයන් නම් පාවෙන ලක්ෂ්‍ය ගණනය කිරීම් මඟින් ප්‍රති result ලය කුමක් දැයි වඩාත් නිවැරදිව ගැලපෙන බව IEEE ප්‍රමිතියට අවශ්‍ය වේ, නමුත් එයින් අදහස් කරන්නේ ඒවා ඇත්ත වශයෙන්ම නිශ්චිත අගයන් නියෝජනය කරන බවයි. 0.1f (1,677,722 +/- 0.5) / 16,777,216 ලෙස සැලකීම බොහෝ අවස්ථාවන්හිදී වඩාත් ප්‍රයෝජනවත් වේ, එය නිශ්චිත ප්‍රමාණය ලෙස සැලකීමට වඩා එම අවිනිශ්චිතතාවයෙන් ගම්‍ය වන දශම සංඛ්‍යා ගණන සමඟ පෙන්විය යුතුය (1,677,722 +/- 0.5) / 16,777,216 (එය දශම ඉලක්කම් 24 දක්වා පෙන්විය යුතුය).
සුපර් කැට්

23
@supercat: IEEE-754 ඉපිලුම් ලක්ෂ්ය දත්ත විසින් පෙන්වා මත ලස්සන පැහැදිලි වේ කරන්න නිශ්චිත සාරධර්ම, 3.2 - 3.4 වගන්ති අදාළ අංශ වේ. 3 +/- 0.5 int x = 3යන අර්ථය ලෙස අර්ථ නිරූපණය කිරීමට ඔබට තෝරා ගත හැකි සේම, ඔබට වෙනත් ආකාරයකින් ඒවා අර්ථ නිරූපණය කිරීමට තෝරා ගත හැකිය x.
ස්ටීවන් කැනන්

7
up සුපර්කැට්: මම සම්පුර්ණයෙන්ම එකඟ වෙමි, නමුත් එයින් අදහස් කරන්නේ Distanceඑහි සංඛ්‍යාත්මක වටිනාකමට හරියටම සමාන නොවන බවයි; එහි අර්ථය වන්නේ සංඛ්‍යාත්මක අගය ආදර්ශනය කරනු ලබන යම් භෞතික ප්‍රමාණයකට ආසන්න කිරීමක් පමණි.
ස්ටීවන් කැනන්

10
සංඛ්යාත්මක විශ්ලේෂණය සඳහා, ඔබ පාවෙන ලක්ෂ්ය සංඛ්යා අන්තරයන් ලෙස නොව නිශ්චිත අගයන් ලෙස අර්ථ දැක්වුවහොත් ඔබේ මොළය ඔබට ස්තූති කරනු ඇත (ඒවා ඔබට අවශ්ය වූ අගයන් නොවේ). නිදසුනක් ලෙස, x 4.5 ට වඩා අඩු අගයක් 0.1 ට වඩා අඩු නම් සහ ඔබ (x + 1) - x ගණනය කරන්නේ නම්, “අන්තරය” අර්ථ නිරූපණය මඟින් ඔබට 0.8 සිට 1.2 දක්වා පරතරයක් ඉතිරි වන අතර “නිශ්චිත අගය” අර්ථ නිරූපණය පවසයි ප්‍රති result ලය 1 ක් වනුයේ උපරිම නිරවද්‍යතාව 2 ^ (- 50) ක ද්විත්ව නිරවද්‍යතාවයකින්.
gnasher729

34

පාවෙන ප්‍රකාශනවල හැකිලීම පිළිබඳව කිසිදු පෝස්ටරයක මෙතෙක් සඳහන් කර නොමැත (ISO C ප්‍රමිතිය, 6.5p8 සහ 7.12.2). FP_CONTRACTප්‍රාග්මාව සකසා ඇත්නම් ON, සම්පාදකයාට a*a*a*a*a*aතනි මෙහෙයුමක් වැනි ප්‍රකාශනයක් සලකා බැලීමට අවසර දෙනු ලැබේ . නිදසුනක් ලෙස, සම්පාදකයෙකු එය වේගවත් හා වඩා නිවැරදි අභ්‍යන්තර බල ශ්‍රිතයක් මගින් ප්‍රතිස්ථාපනය කළ හැකිය. ක්‍රමලේඛකයා විසින් හැසිරීම සෘජුවම ප්‍රභව කේතයෙන් පාලනය වන බැවින් මෙය විශේෂයෙන් සිත්ගන්නා සුළු වන අතර අවසාන පරිශීලකයා විසින් සපයනු ලබන සම්පාදක විකල්ප සමහර විට වැරදි ලෙස භාවිතා කළ හැකිය.

FP_CONTRACTප්‍රාග්මා හි පෙරනිමි තත්වය ක්‍රියාත්මක කිරීම-නිර්වචනය කර ඇති අතර එමඟින් සම්පාදකයෙකුට පෙරනිමියෙන් එවැනි ප්‍රශස්තිකරණයන් කිරීමට අවසර දෙනු ලැබේ. එබැවින් IEEE 754 රීති දැඩි ලෙස අනුගමනය කළ යුතු අතේ ගෙන යා හැකි කේතය එය පැහැදිලිවම සැකසිය යුතුය OFF.

සම්පාදකයෙකු මෙම ප්‍රායෝගිකයට සහය නොදක්වන්නේ නම්, සංවර්ධකයා විසින් එය සැකසීමට තෝරාගෙන තිබේ නම්, එවැනි ප්‍රශස්තිකරණයකින් වැළකී එය ගතානුගතික විය යුතුය OFF.

GCC මෙම ප්‍රායෝගිකයට සහය නොදක්වයි, නමුත් පෙරනිමි විකල්ප සමඟ එය එය යැයි උපකල්පනය කරයි ON; දෘඩාංග එෆ්එම්ඒ සමඟ ඉලක්ක සඳහා, යමෙකුට a*b+cඑෆ්මා (අ, ආ, සී) බවට පරිවර්තනය වීම වැළැක්වීමට අවශ්‍ය නම්, යමෙකුට (ප්‍රායෝගිකව -ffp-contract=offපැහැදිලිවම සැකසීමට OFF) හෝ -std=c99(සමහරුන්ට අනුකූල වන ලෙස ජීසීසීයට පැවසීමට ) වැනි විකල්පයක් සැපයිය යුතුය. සී සම්මත අනුවාදය, මෙහි C99, මේ අනුව ඉහත ඡේදය අනුගමනය කරන්න). අතීතයේ දී, දෙවන විකල්පය පරිවර්තනය වැළැක්වීම නොවේ, එයින් අදහස් වන්නේ GCC මෙම කරුණට අනුකූල නොවන බවයි: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37845


3
දිගු කලක් තිස්සේ පැවති ජනප්‍රිය ප්‍රශ්න සමහර විට ඔවුන්ගේ වයස පෙන්වයි. එවකට මෑතදී පැවති C99 ප්‍රමිතියට හරියටම ගරු නොකිරීම සම්බන්ධයෙන් GCC හට සමාව දිය හැකි මෙම ප්‍රශ්නය 2011 දී විමසන ලදී. ඇත්ත වශයෙන්ම දැන් එය 2014, එබැවින් GCC… ahem.
පැස්කල් කියුක්

ඒ වෙනුවට ඔබ පිළිගත් පිළිතුරක් නොමැතිව සාපේක්ෂව මෑතදී පාවෙන ලක්ෂ්‍ය ප්‍රශ්නවලට පිළිතුරු දිය යුතු නොවේද? කැස්ස stackoverflow.com/questions/23703408 කැස්ස
පැස්කල් කියුක්

මට එය හමු විය ... gcc විසින් C99 පාවෙන ලක්ෂ්‍ය ප්‍රාග්මා ක්‍රියාත්මක නොකිරීම කනස්සල්ලට කරුණකි.
ඩේවිඩ් මොන්නියාක්ස්

1
Av ඩේවිඩ් මොන්නියාක්ස් ප්‍රාග්මා යනු අර්ථ දැක්වීම අනුව ක්‍රියාත්මක කිරීමට විකල්පයකි.
ටිම් සෙගුයින්

2
ImTimSeguine නමුත් ප්‍රායෝගිකයක් ක්‍රියාත්මක නොවන්නේ නම්, එහි පෙරනිමි අගය ක්‍රියාත්මක කිරීම සඳහා වඩාත්ම සීමා කළ යුතුය. මම හිතන්නේ ඩේවිඩ් ඒ ගැන හිතුවා. යමෙකු අයිඑස්ඕ සී මාදිලියක් භාවිතා කරන්නේ නම් ජීසීසී සමඟ මෙය දැන් FP_CONTRACT සඳහා සවි කර ඇත : එය තවමත් ප්‍රාග්මාව ක්‍රියාත්මක නොකරයි, නමුත් අයිඑස්ඕ සී ප්‍රකාරයේදී එය දැන් උපකල්පනය කරන්නේ ප්‍රාග්මා අක්‍රිය වී ඇති බවයි.
vinc17

28

ලැම්බඩගීක් පෙන්වා දුන් පරිදි, පාවෙන ගුණ කිරීම අනුබද්ධ නොවන අතර ඔබට අඩු නිරවද්‍යතාවයක් ලබා ගත හැකිය, නමුත් වඩා හොඳ නිරවද්‍යතාවයක් ලබා ගත් විට ඔබට ප්‍රශස්තකරණයට එරෙහිව තර්ක කළ හැකිය, මන්ද ඔබට නිශ්චිත යෙදුමක් අවශ්‍යය. උදාහරණයක් ලෙස ක්‍රීඩා සමාකරණ සේවාදායකයා / සේවාදායකයා තුළ, සෑම සේවාදායකයෙකුටම එකම ලෝකය අනුකරණය කළ යුතු අතර, ඔබට අවශ්‍ය පාවෙන ලක්ෂ්‍ය ගණනය කිරීම් නිර්ණායක වේ.


3
@greggo නැත, එය තවමත් නිර්ණායකයි. වචනයේ කිසිදු අර්ථයකින් අහඹු ලෙස එකතු නොවේ.
ඇලිස්

9
L ඇලිස් තරමක් පැහැදිලිව පෙනෙන පරිදි මෙහි ජෝර්න් විවිධ වේදිකාවල සහ විවිධ සම්පාදක අනුවාදවල එකම ප්‍රති result ලය ලබා දෙන කේතයේ අර්ථයෙන් 'නිර්ණායකය' භාවිතා කරයි (ක්‍රමලේඛකයාගේ පාලනයෙන් ඔබ්බට ගිය බාහිර විචල්‍යයන්) - හිඟයට වඩා වෙනස්ව ධාවන වේලාවේ සත්‍ය සංඛ්‍යාත්මක අහඹු බව. මෙය වචනය නිසි ලෙස භාවිතා කිරීමක් නොවන බව ඔබ පෙන්වා දෙන්නේ නම්, මම ඒ සමඟ තර්ක කිරීමට යන්නේ නැත.
ග්‍රෙගෝ

5
@greggo ඔහු පවසන දේ පිළිබඳ ඔබේ අර්ථ නිරූපණය හැර, එය තවමත් වැරදිය. වේදිකා හරහා බොහෝ (සියල්ලම නොවේ නම්) මෙහෙයුම් සඳහා සමාන ලක්ෂණ සැපයීම සඳහා IEEE 754 හි සමස්ත ලක්ෂ්‍යය එයයි. දැන්, ඔහු වේදිකා හෝ සම්පාදක අනුවාදයන් ගැන කිසිදු සඳහනක් කර නැත, සෑම දුරස්ථ සේවාදායකයක / සේවාදායකයෙකුගේම සෑම මෙහෙයුමක්ම එක හා සමාන වීමට ඔබට අවශ්‍ය නම් එය වලංගු කාරණයක් වනු ඇත .... නමුත් මෙය ඔහුගේ ප්‍රකාශයෙන් පැහැදිලි නොවේ. වඩා හොඳ වචනයක් "විශ්වසනීයව සමාන" හෝ වෙනත් දෙයක් විය හැකිය.
ඇලිස්

8
Se ඔබ අර්ථකථන තර්ක කිරීමෙන් ඔබේ කාලය ඇතුළුව සෑම කෙනෙකුගේම කාලය නාස්ති කරන්න. ඔහුගේ තේරුම පැහැදිලිය.
ලනාරු

11
An ලනාරු ප්‍රමිතිවල සමස්ත ලක්ෂ්‍යය අර්ථ නිරූපණයකි; ඔහුගේ තේරුම පැහැදිලි නැත.
ඇලිස්

28

"පවු" වැනි පුස්තකාල කාර්යයන් සාමාන්‍යයෙන් අවම වශයෙන් හැකි අවම දෝෂයක් ලබා දීම සඳහා ප්‍රවේශමෙන් සකසා ඇත (සාමාන්‍ය අවස්ථාවෙහිදී). මෙය සාමාන්‍යයෙන් ස්ප්ලයින් සමඟ කාර්යයන් ආසන්න වශයෙන් සාක්ෂාත් කරගනු ලැබේ (පැස්කල්ගේ ප්‍රකාශයට අනුව වඩාත් පොදු ක්‍රියාත්මක කිරීම රෙමේස් ඇල්ගොරිතම භාවිතා කරන බව පෙනේ )

මූලික වශයෙන් පහත සඳහන් මෙහෙයුම:

pow(x,y);

ඕනෑම තනි ගුණ කිරීමක හෝ බෙදීමක දෝෂයට ආසන්න වශයෙන් විශාලත්වයේ ආවේනික දෝෂයක් ඇත .

පහත සඳහන් මෙහෙයුම අතරතුර:

float a=someValue;
float b=a*a*a*a*a*a;

තනි ගුණනයක හෝ බෙදීමක දෝෂයට වඩා 5 ගුණයකට වඩා වැඩි සහජ දෝෂයක් ඇත (ඔබ ගුණ කිරීම් 5 ක් ඒකාබද්ධ කරන නිසා).

සම්පාදකයා එය කරන ආකාරයේ ප්‍රශස්තිකරණය ගැන සැබවින්ම සැලකිලිමත් විය යුතුය:

  1. උපරිම ප්රතිලාභ නම් pow(a,6)කිරීමට a*a*a*a*a*aඑය විය හැක කාර්ය සාධනය වැඩි දියුණු, නමුත් විශාල ලෙස ඉපිලුම් ලක්ෂ්ය සංඛ්යා සඳහා නිරවද්යතාව අවම කර ඇත.
  2. උපරිම ප්රතිලාභ නම් a*a*a*a*a*a කිරීමට pow(a,6), ඒක ඇත්තටම "A" වූ නිසා දෝෂ තොරව ගුණ ඉඩ සමහර විශේෂ අගය (2 ක බලය හෝ සමහර කුඩා පූර්ණ සංඛ්යාමය අංකය) නිරවද්යතාව අඩු කර ගත හැක
  3. උපරිම ප්රතිලාභ නම් pow(a,6)කිරීමට (a*a*a)*(a*a*a)හෝ (a*a)*(a*a)*(a*a)තවමත් සාපේක්ෂව නිරවද්යතාව ක පාඩුවක් විය හැකි powකාර්යය.

පොදුවේ ගත් කල, අත්තනෝමතික පාවෙන ලක්ෂ්‍ය අගයන් සඳහා "පවු" ඔබට අවසානයේ ලිවිය හැකි ඕනෑම කාර්යයකට වඩා හොඳ නිරවද්‍යතාවයක් ඇති බව ඔබ දනී, නමුත් සමහර විශේෂ අවස්ථා වලදී බහු ගුණ කිරීම්වලට වඩා හොඳ නිරවද්‍යතාවයක් සහ ක්‍රියාකාරීත්වයක් තිබිය හැකිය, එය වඩාත් සුදුසු දේ තෝරා ගැනීම සංවර්ධකයාගේ ය, අවසානයේදී කේතය අදහස් දැක්වීමෙන් වෙනත් කිසිවෙකු එම කේතය "ප්‍රශස්තිකරණය" නොකරයි.

ප්‍රශස්තිකරණය කිරීම සඳහා අර්ථවත් වන එකම දෙය (පුද්ගලික මතය සහ පෙනෙන පරිදි GCC හි තේරීමක් ඕනෑම විශේෂිත ප්‍රශස්තිකරණයක් හෝ සම්පාදක ධජයක්) “පවු (අ, 2)” වෙනුවට “අ * අ” ආදේශ කිරීම විය යුතුය. සම්පාදක වෙළෙන්දෙකු විසින් කළ යුතු එකම දෙය එයයි.


7
මෙම පිළිතුර පරිපූර්ණ බව පහළ මට්ටමේ අය තේරුම් ගත යුතුය. මගේ පිළිතුරට සහය දැක්වීම සඳහා මට මූලාශ්‍ර සහ ලියකියවිලි දුසිම් ගණනක් උපුටා දැක්විය හැකි අතර, ඕනෑම පහත් ක්‍රීඩකයෙකුට වඩා මම පාවෙන ලක්ෂ්‍ය නිරවද්‍යතාව සමඟ සම්බන්ධ වී සිටිමි. StackOverflow හි වෙනත් පිළිතුරු ආවරණය නොවන තොරතුරු එකතු කිරීම ඉතා සාධාරණ ය, එබැවින් ආචාරශීලී වන්න සහ ඔබේ හේතු පැහැදිලි කරන්න.
CoffeDeveloper

1
මට පෙනෙන පරිදි ස්ටීවන් කැනන්ගේ පිළිතුර ඔබ පවසන දේ ආවරණය කරයි. ලිබ්ම්ස් ක්‍රියාත්මක වන්නේ ස්ප්ලයින් සමඟ බව ඔබ අවධාරනය කරන බව පෙනේ: ඒවා වඩාත් සාමාන්‍යයෙන් තර්ක අඩු කිරීම (ක්‍රියාත්මක කරන ශ්‍රිතය අනුව) සහ තනි බහුපදයක් වන අතර එම සංගුණක රෙමෙස් ඇල්ගොරිතමයේ වැඩි හෝ අඩු නවීන ප්‍රභේද මගින් ලබාගෙන ඇත. මංසන්ධි ස්ථානවල සුමට බව ලිබ්ම් කාර්යයන් සඳහා ලුහුබැඳිය යුතු පරමාර්ථයක් ලෙස නොසැලකේ (ඒවා ප්‍රමාණවත් තරම් නිවැරදි නම්, වසම කොපමණ කොටස් වලට බෙදී තිබුණද ඒවා ස්වයංක්‍රීයව සුමට වේ).
පැස්කල් කියුක්

ඔබේ පිළිතුරේ දෙවන භාගය සම්පුර්ණයෙන්ම මග හැරී ඇත්තේ සම්පාදකයින් විසින් කේතයක් නිපදවිය යුතු අතර එය ප්‍රභව කේතය පවසන කාල සීමාව ක්‍රියාත්මක කරයි. ඔබ “නිරවද්‍යතාව” යන වචනය භාවිතා කරන විට “නිරවද්‍යතාව” යන වචනය භාවිතා කරයි.
පැස්කල් කියුක්

ඔබගේ ආදානයට ස්තූතියි, මම පිළිතුර තරමක් නිවැරදි කළෙමි, අවසාන පේළි 2 තුළ අළුත් දෙයක් තවමත් පවතී ^^
කෝෆි සංවර්ධක

27

මෙම නඩුව කිසිසේත්ම ප්‍රශස්ත වේ යැයි මම බලාපොරොත්තු නොවෙමි. ප්‍රකාශනයක සම්පූර්ණ ක්‍රියාකාරකම් ඉවත් කිරීම සඳහා නැවත සංවිධානය කළ හැකි උප ප්‍රකාශන අඩංගු වන විට එය බොහෝ විට විය නොහැක. සම්පාදක ලේඛකයින් කලාතුරකින් හමු වූ අද්දර නඩුවක් ආවරණය කරනවාට වඩා සැලකිය යුතු දියුණුවක් ඇති කිරීමට ඉඩ ඇති ප්‍රදේශවල ඔවුන්ගේ කාලය ආයෝජනය කරනු ඇතැයි මම අපේක්ෂා කරමි.

නිසි සම්පාදක ස්විචයන් සමඟ මෙම ප්‍රකාශනය සැබවින්ම ප්‍රශස්තිකරණය කළ හැකි බව අනෙක් පිළිතුරු වලින් දැන ගැනීම මා පුදුමයට පත් කළෙමි. එක්කෝ ප්‍රශස්තිකරණය සුළුපටු ය, නැතහොත් එය වඩාත් පොදු ප්‍රශස්තිකරණයේ අද්දර නඩුවකි, නැතහොත් සම්පාදක ලේඛකයින් අතිශයින් ගැඹුරු ය.

ඔබ මෙහි කළ පරිදි සම්පාදකයාට ඉඟි ලබා දීමේ කිසිදු වරදක් නැත. ක්ෂුද්‍ර ප්‍රශස්තිකරණ ක්‍රියාවලියේ සාමාන්‍ය හා අපේක්ෂිත කොටස වන්නේ ප්‍රකාශ සහ ප්‍රකාශන නැවත සකස් කිරීම මගින් ඒවා ගෙන එන්නේ කුමන වෙනස්කම්ද යන්නයි.

නොගැලපෙන ප්‍රති results ල ලබා දීම සඳහා ප්‍රකාශන දෙක සලකා බැලීමේදී සම්පාදකයා සාධාරණීකරණය කළ හැකි වුවද (නිසි ස්විචයකින් තොරව), එම සීමාවට ඔබ බැඳී සිටිය යුතු නැත. වෙනස ඇදහිය නොහැකි තරම් කුඩා වනු ඇත - කොතරම්ද යත් වෙනස ඔබට වැදගත් නම්, ඔබ මුලින්ම සම්මත පාවෙන ලක්ෂ්‍ය අංක ගණිතය භාවිතා නොකළ යුතුය.


17
වෙනත් විචාරකයෙකු සඳහන් කළ පරිදි, මෙය විකාරයකි. වෙනස පිරිවැයෙන් අඩක් හෝ 10% ක් පමණ විය හැකි අතර, තද පුඩුවක් තුළ ධාවනය වන්නේ නම්, එය අතිවිශාල අමතර නිරවද්‍යතාවයක් ලබා ගැනීම සඳහා අපතේ යන බොහෝ උපදෙස් වලට පරිවර්තනය වේ. ඔබ මොන්ටේ කාලෝ කරන විට සම්මත එෆ්පී භාවිතා නොකළ යුතු යැයි පැවසීම හරියට ඔබ රට පුරා ගමන් කිරීමට සෑම විටම ගුවන් යානයක් භාවිතා කළ යුතු යැයි පැවසීම වැනි ය; එය බොහෝ බාහිර දේ නොසලකා හරියි. අවසාන වශයෙන්, මෙය අසාමාන්‍ය ප්‍රශස්තිකරණයක් නොවේ; මළ කේත විශ්ලේෂණය සහ කේත අඩු කිරීම / ප්‍රතික්‍රියාකාරකය ඉතා සුලභ ය.
ඇලිස්

21

මෙම ප්‍රශ්නයට දැනටමත් හොඳ පිළිතුරු කිහිපයක් ඇත, නමුත් සම්පූර්ණත්වය සඳහා මට පෙන්වා දීමට අවශ්‍ය වූයේ සී ප්‍රමිතියේ අදාළ කොටස 5.1.2.2.3 / 15 (එය 1.9 / 9 වගන්තියට සමාන වේ සී ++ 11 ප්‍රමිතිය). මෙම කොටසේ සඳහන් වන්නේ මෙහෙයුම්කරුවන් නැවත සංවිධානය කළ හැක්කේ ඔවුන් සැබවින්ම සහායක හෝ සංක්‍රමණික නම් පමණි.


12

පාවෙන ලක්ෂ්‍ය සංඛ්‍යා සඳහා පවා gcc හට මෙම ප්‍රශස්තිකරණය කළ හැකිය. උදාහරණයක් වශයෙන්,

double foo(double a) {
  return a*a*a*a*a*a;
}

බවට පත්වේ

foo(double):
    mulsd   %xmm0, %xmm0
    movapd  %xmm0, %xmm1
    mulsd   %xmm0, %xmm1
    mulsd   %xmm1, %xmm0
    ret

සමඟ -O -funsafe-math-optimizations. මෙම නැවත සකස් කිරීම IEEE-754 උල්ලං lates නය කරයි, නමුත් එයට ධජය අවශ්‍ය වේ.

අදහස් දැක්වීමේදී පීටර් කෝඩ්ස් පෙන්වා දුන් පරිදි අත්සන් කළ පූර්ණ සංඛ්‍යා වලට මෙම ප්‍රශස්තිකරණය කළ හැක්කේ -funsafe-math-optimizationsඑය පිටාර ගැලීමක් නොමැති විට හරියටම රඳවා තබාගෙන ඇති නිසා සහ පිටාර ගැලීමක් තිබේ නම් ඔබට නිර්වචනය නොකළ හැසිරීමක් ලැබෙනු ඇත. ඉතින් ඔබට ලැබෙනවා

foo(long):
    movq    %rdi, %rax
    imulq   %rdi, %rax
    imulq   %rdi, %rax
    imulq   %rax, %rax
    ret

සාධාරණයි -O. අත්සන් නොකළ පූර්ණ සංඛ්‍යා සඳහා, ඒවා 2 හි මෝඩ් බලයන් වැඩ කරන බැවින් එය වඩාත් පහසු වන අතර එමඟින් පිටාර ගැලීමකදී පවා නිදහසේ නැවත සකස් කළ හැකිය.


1
ගොඩ්බෝල්ට් සම්බන්ධතාවය ද්විත්ව, int සහ අත්සන් නොකළ. gcc සහ clang යන දෙකම එකම ආකාරයකින් ප්‍රශස්තිකරණය කරයි (සමඟ -ffast-math)
පීටර්

EtPeterCordes ස්තූතියි!
චාල්ස්
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.