0.1f සිට 0 දක්වා වෙනස් කිරීම කාර්ය සාධනය 10x කින් මන්දගාමී කරන්නේ ඇයි?


1533

ඇයි මේ කේතය ටිකක් කරන්නේ,

const float x[16] = {  1.1,   1.2,   1.3,     1.4,   1.5,   1.6,   1.7,   1.8,
                       1.9,   2.0,   2.1,     2.2,   2.3,   2.4,   2.5,   2.6};
const float z[16] = {1.123, 1.234, 1.345, 156.467, 1.578, 1.689, 1.790, 1.812,
                     1.923, 2.034, 2.145,   2.256, 2.367, 2.478, 2.589, 2.690};
float y[16];
for (int i = 0; i < 16; i++)
{
    y[i] = x[i];
}

for (int j = 0; j < 9000000; j++)
{
    for (int i = 0; i < 16; i++)
    {
        y[i] *= x[i];
        y[i] /= z[i];
        y[i] = y[i] + 0.1f; // <--
        y[i] = y[i] - 0.1f; // <--
    }
}

පහත සඳහන් බිට් එකට වඩා 10 ගුණයකින් වේගයෙන් ධාවනය කරන්න (සටහන් කර ඇති ස්ථානය හැර)

const float x[16] = {  1.1,   1.2,   1.3,     1.4,   1.5,   1.6,   1.7,   1.8,
                       1.9,   2.0,   2.1,     2.2,   2.3,   2.4,   2.5,   2.6};
const float z[16] = {1.123, 1.234, 1.345, 156.467, 1.578, 1.689, 1.790, 1.812,
                     1.923, 2.034, 2.145,   2.256, 2.367, 2.478, 2.589, 2.690};
float y[16];
for (int i = 0; i < 16; i++)
{
    y[i] = x[i];
}

for (int j = 0; j < 9000000; j++)
{
    for (int i = 0; i < 16; i++)
    {
        y[i] *= x[i];
        y[i] /= z[i];
        y[i] = y[i] + 0; // <--
        y[i] = y[i] - 0; // <--
    }
}

විෂුවල් ස්ටුඩියෝ 2010 SP1 සමඟ සම්පාදනය කිරීමේදී. උපරිම තලයට නැංවීමට මට්ටමේ විය -02සමඟ sse2කටයුතු කර තිබෙනවා. මම වෙනත් සම්පාදකයින් සමඟ පරීක්ෂා කර නැත.


10
ඔබ වෙනස මනින්නේ කෙසේද? ඔබ සම්පාදනය කිරීමේදී භාවිතා කළ විකල්ප මොනවාද?
ජේම්ස් කන්සේ

158
සම්පාදකයා මේ අවස්ථාවේ දී +/- 0 අතහරින්නේ නැත්තේ ඇයි?!?
මයිකල් ඩෝගන්

127
Y Zyx2000 සම්පාදකයා එම මෝඩයා අසල කොතැනකවත් නැත. එය ඔබ භාවිතා යන්න එම කේතය පිටතට spits බව LINQPad සංදර්ශන එතරම් උදාහරණයක් Disassembling 0, 0f, 0d, හෝ (int)0එය ද, සන්ධර්භයක, doubleඅවශ්ය වේ.
මිලිමූස්

14
ප්‍රශස්තිකරණ මට්ටම කුමක්ද?
ඔටෝ ඇල්මන්ඩින්ගර්

Answers:


1620

අවලංගු කරන ලද පාවෙන ලක්ෂ්‍යයේ ලෝකයට සාදරයෙන් පිළිගනිමු ! ඔවුන්ට කාර්ය සාධනය විනාශ කළ හැකිය !!!

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

ඔබ අනුකරණ 10,000 පසු අංක මුද්රණය කරයි නම්, ඔබ ඔවුන් යන්න මත පදනම් විවිධ වටිනාකම් තුලට ඇති බව පෙනෙනු ඇත 0හෝ 0.1භාවිතා කරනු ඇත.

X64 මත සම්පාදනය කරන ලද පරීක්ෂණ කේතය මෙන්න:

int main() {

    double start = omp_get_wtime();

    const float x[16]={1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,1.9,2.0,2.1,2.2,2.3,2.4,2.5,2.6};
    const float z[16]={1.123,1.234,1.345,156.467,1.578,1.689,1.790,1.812,1.923,2.034,2.145,2.256,2.367,2.478,2.589,2.690};
    float y[16];
    for(int i=0;i<16;i++)
    {
        y[i]=x[i];
    }
    for(int j=0;j<9000000;j++)
    {
        for(int i=0;i<16;i++)
        {
            y[i]*=x[i];
            y[i]/=z[i];
#ifdef FLOATING
            y[i]=y[i]+0.1f;
            y[i]=y[i]-0.1f;
#else
            y[i]=y[i]+0;
            y[i]=y[i]-0;
#endif

            if (j > 10000)
                cout << y[i] << "  ";
        }
        if (j > 10000)
            cout << endl;
    }

    double end = omp_get_wtime();
    cout << end - start << endl;

    system("pause");
    return 0;
}

ප්‍රතිදානය:

#define FLOATING
1.78814e-007  1.3411e-007  1.04308e-007  0  7.45058e-008  6.70552e-008  6.70552e-008  5.58794e-007  3.05474e-007  2.16067e-007  1.71363e-007  1.49012e-007  1.2666e-007  1.11759e-007  1.04308e-007  1.04308e-007
1.78814e-007  1.3411e-007  1.04308e-007  0  7.45058e-008  6.70552e-008  6.70552e-008  5.58794e-007  3.05474e-007  2.16067e-007  1.71363e-007  1.49012e-007  1.2666e-007  1.11759e-007  1.04308e-007  1.04308e-007

//#define FLOATING
6.30584e-044  3.92364e-044  3.08286e-044  0  1.82169e-044  1.54143e-044  2.10195e-044  2.46842e-029  7.56701e-044  4.06377e-044  3.92364e-044  3.22299e-044  3.08286e-044  2.66247e-044  2.66247e-044  2.24208e-044
6.30584e-044  3.92364e-044  3.08286e-044  0  1.82169e-044  1.54143e-044  2.10195e-044  2.45208e-029  7.56701e-044  4.06377e-044  3.92364e-044  3.22299e-044  3.08286e-044  2.66247e-044  2.66247e-044  2.24208e-044

දෙවන ධාවනයේදී සංඛ්‍යා ශුන්‍යයට ඉතා ආසන්න වන්නේ කෙසේදැයි බලන්න.

සාමාන්‍යකරණය කරන ලද සංඛ්‍යා සාමාන්‍යයෙන් දුර්ලභ වන අතර එබැවින් බොහෝ සකසනයන් ඒවා කාර්යක්ෂමව හැසිරවීමට උත්සාහ නොකරයි.


කේතයේ ආරම්භයට මෙය එකතු කිරීමෙන් අප විසින් ශුන්‍යයට හරවා යැවුවහොත්, මේ සඳහා සංඛ්‍යාත සංඛ්‍යා සමඟ සෑම දෙයක්ම ඇති බව පෙන්වීමට :

_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);

එවිට ඇති අනුවාදය 0තවදුරටත් 10x මන්දගාමී නොවන අතර ඇත්ත වශයෙන්ම වේගවත් වේ. (මේ සඳහා කේතය SSE සක්‍රීය කිරීම සමඟ සම්පාදනය කිරීම අවශ්‍ය වේ.)

මෙයින් අදහස් කරන්නේ මෙම අමුතු අඩු නිරවද්‍යතාව පාහේ ශුන්‍ය අගයන් භාවිතා කරනවා වෙනුවට, අපි ඒ වෙනුවට ශුන්‍යයට හැරෙන බවයි.

වේලාවන්: මූලික i7 920 @ 3.5 GHz:

//  Don't flush denormals to zero.
0.1f: 0.564067
0   : 26.7669

//  Flush denormals to zero.
0.1f: 0.587117
0   : 0.341406

අවසානයේදී, මෙය සැබවින්ම එය පූර්ණ සංඛ්‍යාවක් හෝ පාවෙන ලක්ෂ්‍යයක් සමග කිසිදු සම්බන්ධයක් නැත. මෙම 0හෝ 0.1f/ වළළු දෙකම ලේඛනයක් පිටත බවට ගබඩා පරිවර්තනය කර ඇත. එබැවින් එය කාර්ය සාධනය කෙරෙහි කිසිදු බලපෑමක් ඇති නොකරයි.


100
පෙරනිමියෙන් සම්පාදකයා විසින් "+ 0" සම්පූර්ණයෙන්ම ප්‍රශස්තිකරණය නොකිරීම ගැන මම තවමත් ටිකක් අමුතුයි. ඔහු "+ 0.0f" දැමුවා නම් මෙය සිදුවනු ඇත්ද?
s73v3r

51
73 s73v3r එය ඉතා හොඳ ප්‍රශ්නයකි. දැන් මම එකලස් කිරීම දෙස බැලූවත්, + 0.0fප්‍රශස්තිකරණය නොකෙරේ . මට අනුමාන කිරීමට සිදුවුවහොත්, එය සං aling ා කිරීමක් හෝ යමක් සිදුවුවහොත් එය + 0.0fඅතුරු ආබාධ ඇති විය හැකිය ... මම වැරදියි. y[i]NaN
ගුප්ත

14
බොහෝ අවස්ථාවන්හිදී එකම සංඛ්‍යාතයකින් වෙනස් සංඛ්‍යාත්මකව විශාලත්වය දෙගුණයක් වේ. ශ්රව්ය යෙදුම් සඳහා ෆ්ලෂ්-සිට-ශුන්ය හොඳයි (සහ ඔබට මෙහි 1e-38 අහිමි කර ගත හැකි වෙනත් අය), නමුත් x87 සඳහා අදාළ නොවන බව මම විශ්වාස කරමි. FTZ නොමැතිව, ශ්‍රව්‍ය යෙදුම් සඳහා සුපුරුදු විසඳුම වන්නේ ඉතා අඩු විස්තාරයක් (ඇසිය නොහැකි) ඩීසී හෝ වර්ග තරංග සං signal ාවක් අවිනිශ්චිතතාවයෙන් away ත්වී ඇති ජිටර් අංකවලට එන්නත් කිරීමයි.
රසල් බොරොගෝව්

16
SIsaac මන්ද යත්, y [i] 0.1 ට වඩා සැලකිය යුතු තරම් කුඩා වන විට එය නිරවද්‍යතාව නැති වී යන නිසා සංඛ්‍යාවේ වඩාත්ම වැදගත් ඉලක්කම් වැඩි වන බැවිනි.
ඩෑන් ඊස් ෆයිඩ්ලිං ෆයර්ලයිට්

167
@ s73v3r: පාවෙන ලක්ෂ්‍යයට 0 ණ 0 ක් ඇති නිසා + 0.f ප්‍රශස්තිකරණය කළ නොහැකි අතර + 0.f සිට -.0f දක්වා එකතු කිරීමේ ප්‍රති result ලය + 0.f වේ. එබැවින් 0.f එකතු කිරීම අනන්‍යතා මෙහෙයුමක් නොවන අතර එය ප්‍රශස්තිකරණය කළ නොහැක.
එරික් පෝස්ට්පිස්චිල්

415

gccජනනය කරන ලද එකලස් කිරීම සඳහා වෙනසක් භාවිතා කිරීම සහ යෙදීමෙන් මෙම වෙනස පමණක් ලැබේ:

73c68,69
<   movss   LCPI1_0(%rip), %xmm1
---
>   movabsq $0, %rcx
>   cvtsi2ssq   %rcx, %xmm1
81d76
<   subss   %xmm1, %xmm0

මෙම cvtsi2ssqඑක් මන්දගාමී සැබවින්ම 10 ගුණයක් වීම.

පෙනෙන විදිහට, float අනුවාදය මතකයෙන් පටවා ඇති එක්ස්එම්එම් ලේඛනයක් භාවිතා කරන අතර intඅනුවාදය සත්‍ය intඅගය 0 උපදෙස් floatභාවිතා කිරීම සඳහා පරිවර්තනය කරයි cvtsi2ssq, බොහෝ කාලයක් ගතවේ. -O3Gcc වෙත ගමන් කිරීම උදව් නොකරයි. (gcc අනුවාදය 4.2.1.)

( doubleඒ වෙනුවට භාවිතා කිරීම floatවැදගත් නොවේ. එය cvtsi2ssqa ට වෙනස් කිරීම හැර cvtsi2sdq.)

යාවත්කාලීන කරන්න

සමහර අමතර පරීක්ෂණ වලින් පෙනී යන්නේ එය අනිවාර්යයෙන්ම cvtsi2ssqඋපදෙස් නොවන බවයි. ඉවත් කළ පසු ( ඒ වෙනුවට භාවිතා කිරීම int ai=0;float a=ai;සහ භාවිතා aකිරීම0 ), වේග වෙනස පවතී. එබැවින් y මිස්ටිකල් හරි, අවලංගු කළ පාවෙන වෙනස ඇති කරයි. 0සහ අතර අගයන් පරීක්ෂා කිරීමෙන් මෙය දැකිය හැකිය 0.1f. 0.00000000000000000000000000000001ලූප හදිසියේම 10 ගුණයක් දිගු වන විට ඉහත කේතයේ හැරවුම් ලක්ෂ්‍යය ආසන්න වශයෙන් වේ.

යාවත්කාලීන කරන්න << 1

මෙම සිත්ගන්නාසුලු සංසිද්ධිය පිළිබඳ කුඩා දෘශ්‍යකරණයක්:

  • 1 තීරුව: පාවෙන, සෑම පුනරාවර්තනයක් සඳහාම 2 න් බෙදනු ලැබේ
  • 2 තීරුව: මෙම පාවෙන ද්විමය නිරූපණය
  • 3 වන තීරුව: මෙම පාවෙන අගය 1e7 වාරයක් ගත කිරීමට ගතවන කාලය

නිර්‍මාණකරණය ආරම්භ වන විට on ාතකය (අවසාන බිටු 9) එහි අවම අගයට වෙනස් වන ආකාරය ඔබට පැහැදිලිව දැකගත හැකිය. එම අවස්ථාවේදී සරල එකතු කිරීම 20 ගුණයක් මන්දගාමී වේ.

0.000000000000000000000000000000000100000004670110: 10111100001101110010000011100000 45 ms
0.000000000000000000000000000000000050000002335055: 10111100001101110010000101100000 43 ms
0.000000000000000000000000000000000025000001167528: 10111100001101110010000001100000 43 ms
0.000000000000000000000000000000000012500000583764: 10111100001101110010000110100000 42 ms
0.000000000000000000000000000000000006250000291882: 10111100001101110010000010100000 48 ms
0.000000000000000000000000000000000003125000145941: 10111100001101110010000100100000 43 ms
0.000000000000000000000000000000000001562500072970: 10111100001101110010000000100000 42 ms
0.000000000000000000000000000000000000781250036485: 10111100001101110010000111000000 42 ms
0.000000000000000000000000000000000000390625018243: 10111100001101110010000011000000 42 ms
0.000000000000000000000000000000000000195312509121: 10111100001101110010000101000000 43 ms
0.000000000000000000000000000000000000097656254561: 10111100001101110010000001000000 42 ms
0.000000000000000000000000000000000000048828127280: 10111100001101110010000110000000 44 ms
0.000000000000000000000000000000000000024414063640: 10111100001101110010000010000000 42 ms
0.000000000000000000000000000000000000012207031820: 10111100001101110010000100000000 42 ms
0.000000000000000000000000000000000000006103515209: 01111000011011100100001000000000 789 ms
0.000000000000000000000000000000000000003051757605: 11110000110111001000010000000000 788 ms
0.000000000000000000000000000000000000001525879503: 00010001101110010000100000000000 788 ms
0.000000000000000000000000000000000000000762939751: 00100011011100100001000000000000 795 ms
0.000000000000000000000000000000000000000381469876: 01000110111001000010000000000000 896 ms
0.000000000000000000000000000000000000000190734938: 10001101110010000100000000000000 813 ms
0.000000000000000000000000000000000000000095366768: 00011011100100001000000000000000 798 ms
0.000000000000000000000000000000000000000047683384: 00110111001000010000000000000000 791 ms
0.000000000000000000000000000000000000000023841692: 01101110010000100000000000000000 802 ms
0.000000000000000000000000000000000000000011920846: 11011100100001000000000000000000 809 ms
0.000000000000000000000000000000000000000005961124: 01111001000010000000000000000000 795 ms
0.000000000000000000000000000000000000000002980562: 11110010000100000000000000000000 835 ms
0.000000000000000000000000000000000000000001490982: 00010100001000000000000000000000 864 ms
0.000000000000000000000000000000000000000000745491: 00101000010000000000000000000000 915 ms
0.000000000000000000000000000000000000000000372745: 01010000100000000000000000000000 918 ms
0.000000000000000000000000000000000000000000186373: 10100001000000000000000000000000 881 ms
0.000000000000000000000000000000000000000000092486: 01000010000000000000000000000000 857 ms
0.000000000000000000000000000000000000000000046243: 10000100000000000000000000000000 861 ms
0.000000000000000000000000000000000000000000022421: 00001000000000000000000000000000 855 ms
0.000000000000000000000000000000000000000000011210: 00010000000000000000000000000000 887 ms
0.000000000000000000000000000000000000000000005605: 00100000000000000000000000000000 799 ms
0.000000000000000000000000000000000000000000002803: 01000000000000000000000000000000 828 ms
0.000000000000000000000000000000000000000000001401: 10000000000000000000000000000000 815 ms
0.000000000000000000000000000000000000000000000000: 00000000000000000000000000000000 42 ms
0.000000000000000000000000000000000000000000000000: 00000000000000000000000000000000 42 ms
0.000000000000000000000000000000000000000000000000: 00000000000000000000000000000000 44 ms

ARM පිළිබඳ සමාන සාකච්ඡාවක් Stack Overflow ප්‍රශ්නයෙන් සොයාගත හැකිය Objective-C හි පාවෙන ලක්ෂ්‍යය? .


27
-Oඑය නිවැරදි නොකරන්න, නමුත් -ffast-mathඑසේ කරයි. (සියලු කාලය මම භාවිතය, එය නිරවද්යතාවයකින් කරදර කෙසේ හෝ නිසි පරිදි සැලසුම් වැඩසටහන තුල හැරී ගමන් කළ යුතු නොවේ හේතු එහිදී එක් රටකින් කොනේ නඩු.)
leftaroundabout

Gcc-4.6 සමඟ කිසිදු ධනාත්මක ප්‍රශස්තිකරණ මට්ටමක පරිවර්තනයක් නොමැත.
ජෙඩ්

ftleftaroundabout: MXCSR හි -ffast-mathFTZ (ෆ්ලෂ් බිංදුවට) සහ DAZ (ඩෙනෝමල් ශුන්‍යය) ලෙස සැකසෙන අමතර ආරම්භක කේත කිහිපයක් සබැඳි සමඟ ක්‍රියාත්මක කළ හැකි (පුස්තකාලයක් නොවේ) සම්පාදනය කිරීම , එබැවින් CPU කිසි විටෙකත් ප්‍රත්‍යාවර්ත සඳහා මන්දගාමී මයික්‍රෝ කේත ආධාරයක් ගත යුතු නොවේ.
පීටර් කෝර්ඩ්ස්

34

එය ප්‍රතිනිර්මාණය කළ පාවෙන ලක්ෂ්‍ය භාවිතය නිසාය. එය සහ කාර්ය සාධන ද penalty ුවම යන දෙකම ඉවත් කරන්නේ කෙසේද? සාමාන්‍ය සංඛ්‍යා killing ාතනය කිරීමේ ක්‍රම සඳහා අන්තර්ජාලය පරිහරණය කර ඇති අතර, මෙය කිරීමට තවමත් “හොඳම” ක්‍රමයක් නොමැති බව පෙනේ. විවිධ පරිසරයන් තුළ වඩාත් හොඳින් ක්‍රියාත්මක විය හැකි මෙම ක්‍රම තුන මම සොයාගෙන ඇත:

  • සමහර GCC පරිසරයන් තුළ ක්‍රියා නොකරනු ඇත:

    // Requires #include <fenv.h>
    fesetenv(FE_DFL_DISABLE_SSE_DENORMS_ENV);
  • සමහර දෘශ්‍ය ස්ටුඩියෝ පරිසරවල ක්‍රියා නොකරනු ඇත: 1

    // Requires #include <xmmintrin.h>
    _mm_setcsr( _mm_getcsr() | (1<<15) | (1<<6) );
    // Does both FTZ and DAZ bits. You can also use just hex value 0x8040 to do both.
    // You might also want to use the underflow mask (1<<11)
  • GCC සහ Visual Studio යන දෙඅංශයේම වැඩ කිරීමට පෙනී යයි:

    // Requires #include <xmmintrin.h>
    // Requires #include <pmmintrin.h>
    _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
    _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
  • නූතන ඉන්ටෙල් සීපීයූවල පෙරනිමියෙන් අක්‍රීය කිරීමට ඉන්ටෙල් සම්පාදකයාට විකල්ප ඇත. වැඩි විස්තර මෙතැනින්

  • සම්පාදක ස්විච. -ffast-math, -msseහෝ -mfpmath=sseඅවලංගු කිරීම් අක්‍රීය කර තවත් දේවල් කිහිපයක් වේගවත් කරයි, නමුත් අවාසනාවකට ඔබේ කේතය බිඳ දැමිය හැකි වෙනත් ආසන්න කිරීම් රාශියක් කරන්න. ප්රවේශමෙන් පරීක්ෂා කරන්න! විෂුවල් ස්ටුඩියෝ සම්පාදකයා සඳහා වේගවත් ගණිතයට සමාන /fp:fastනමුත් මෙය ප්‍රතික්ෂේප කරන්නන් අක්‍රීය කරන්නේද යන්න මට තහවුරු කිරීමට නොහැකි විය. 1


1
මෙය වෙනස් නමුත් ආශ්‍රිත ප්‍රශ්නයකට යහපත් පිළිතුරක් සේ පෙනේ (සංඛ්‍යාත්මක ගණනය කිරීම් සාමාන්‍ය ප්‍රති results ල ලබා ගැනීම වළක්වා ගන්නේ කෙසේද?) එය මෙම ප්‍රශ්නයට පිළිතුරු සපයන්නේ නැත.
බෙන් වොයිග්ට්

වින්ඩෝස් X64 .exe දියත් කරන විට හදිසියේම ගලා බසින පසුබිමක් පසුකර යන අතර වින්ඩෝස් 32-බිට් සහ ලිනක්ස් එසේ නොවේ. ලිනක්ස් වලදී, gcc -ffast-math හදිසියේම යටින් ගලා යා යුතුය (නමුත් මම හිතන්නේ වින්ඩෝස් වල නොවේ). ඉන්ටෙල් සම්පාදකයින් ප්‍රධාන () වලින් ආරම්භ කළ යුතු අතර එමඟින් මෙම මෙහෙයුම් පද්ධතියේ වෙනස්කම් නොපවතිනු ඇත, නමුත් මට දෂ්ට කර ඇති අතර එය පැහැදිලිවම වැඩසටහන තුළ සැකසිය යුතුය. සැන්ඩි බ්‍රිජ් වලින් ආරම්භ වන ඉන්ටෙල් සීපීයූස් එකතු කිරීම / අඩු කිරීම (නමුත් බෙදීම / ගුණ කිරීම නොවේ) තුළ ඇති වන අසාමාන්‍යතා කාර්යක්ෂමව හැසිරවිය යුතුය, එබැවින් ක්‍රමයෙන් ගලායාම භාවිතා කිරීම සඳහා නඩුවක් තිබේ.
tim18

1
මයික්‍රොසොෆ්ට් / එෆ්පී: වේගවත් (පෙරනිමියක් නොවේ) gcc -ffast-math හෝ ICL (පෙරනිමි) / fp: වේගයෙන් ආවේනික වූ ආක්‍රමණශීලී දේවල් කිසිවක් නොකරයි. එය ICL / fp: source වැනි ය. එබැවින් ඔබ මෙම සම්පාදකයින් සංසන්දනය කිරීමට අදහස් කරන්නේ නම් / fp: (සහ සමහර අවස්ථාවලදී යටි ප්‍රවාහ ප්‍රකාරය) සැකසිය යුතුය.
tim18

18

Gcc හි ඔබට මේ සමඟ FTZ සහ DAZ සක්‍රීය කළ හැකිය:

#include <xmmintrin.h>

#define FTZ 1
#define DAZ 1   

void enableFtzDaz()
{
    int mxcsr = _mm_getcsr ();

    if (FTZ) {
            mxcsr |= (1<<15) | (1<<11);
    }

    if (DAZ) {
            mxcsr |= (1<<6);
    }

    _mm_setcsr (mxcsr);
}

gcc ස්විචයන් ද භාවිතා කරන්න: -msse -mfpmath = sse

(කාල් හෙතරින්ටන්ට අනුරූප බැර කිරීම් [1])

[1] http://carlh.net/plugins/denormals.php


ද බලන්න fesetround()සිට fenv.hයයි වරදවා වටහා තවත් වැඩි අතේ ගෙන යා හැකි ආකාරයෙන් (සඳහා (C99 ප්රමිතියේ දී අර්ථ) linux.die.net/man/3/fesetround (නමුත් මෙම) පමණක් subnormals සියළුම ෆෙඩරල් පක්ෂයට මෙහෙයුම් වලට බලපානු ඇත, )
ජර්මන් ගාර්ෂියා

FTZ සඳහා ඔබට 1 << 15 සහ 1 << 11 අවශ්‍ය බව ඔබට විශ්වාසද? මා දැක ඇත්තේ 1 << 15 වෙනත් තැනක උපුටා දැක්වීමකි ...
fig

igfig: 1 << 11 යටි ප්‍රවාහ ආවරණ සඳහා වේ. වැඩි විස්තර මෙතැනින්: softpixel.com/~cwright/programming/simd/sse.php
ජර්මානු ගාර්ෂියා

Erman ජර්මන් ගාර්ෂියා මෙය OPs ප්‍රශ්නයට පිළිතුරු සපයන්නේ නැත; ප්රශ්නය වූයේ "මෙම කේතය ටිකක් වඩා 10 ගුණයකින් වේගයෙන් ධාවනය වන්නේ ඇයි ..." - මෙම විසඳුම ලබා දීමට පෙර එයට පිළිතුරු දීමට ඔබ උත්සාහ කළ යුතුය.

9

ඩෑන් නීලිගේ ප්‍රකාශය පිළිතුරක් දක්වා පුළුල් කළ යුතුය.

එය ශුන්‍ය නියතය 0.0fඅවලංගු කිරීම හෝ මන්දගාමී වීමට හේතු නොවේ, එය ලූපයේ එක් එක් පුනරාවර්තනය ශුන්‍යයට ළඟා වන අගයන් වේ. ඒවා ශුන්‍යයට සමීප වන විට, ඒවා නිරූපණය කිරීම සඳහා වඩාත් නිරවද්‍යතාව අවශ්‍ය වන අතර ඒවා අවලංගු වේ. මේවා y[i]අගයන් ය. (ඒවා ශුන්‍යයට ළඟා x[i]/z[i]වන්නේ සියල්ලන්ටම 1.0 ට වඩා අඩු නිසායi .)

කේතයේ මන්දගාමී හා වේගවත් අනුවාද අතර තීරණාත්මක වෙනස වන්නේ ප්‍රකාශයයි y[i] = y[i] + 0.1f; . මෙම රේඛාව ලූපයේ එක් එක් පුනරාවර්තනය ක්‍රියාත්මක කළ විගස, පාවෙන අමතර නිරවද්‍යතාවය නැති වී යන අතර, එම නිරවද්‍යතාවය නිරූපණය කිරීම සඳහා අවශ්‍ය වන අවලංගු කිරීම තවදුරටත් අවශ්‍ය නොවේ. පසුව, පාවෙන ලක්ෂ්‍ය මෙහෙයුම් y[i]අඛණ්ඩව පවතින්නේ ඒවා නිත්‍යකරණයට ලක් නොවන බැවිනි.

ඔබ එකතු කරන විට අමතර නිරවද්‍යතාවය නැති වන්නේ 0.1fඇයි? පාවෙන ලක්ෂ්‍ය සංඛ්‍යා වල ඇත්තේ සැලකිය යුතු සංඛ්‍යා පමණි. ඔබට සැලකිය යුතු ඉලක්කම් තුනක් සඳහා ප්‍රමාණවත් ආචයනයක් ඇති බව පවසන්න, එවිට 0.00001 = 1e-5, 0.00001 + 0.1 = 0.1අවම වශයෙන් මෙම උදාහරණය සඳහා පාවෙන ආකෘතිය, අවම වශයෙන් සැලකිය යුතු ප්‍රමාණයක් ගබඩා කිරීමට ඉඩක් නැති නිසා 0.10001.

කෙටියෙන් කිවහොත්, y[i]=y[i]+0.1f; y[i]=y[i]-0.1f;ඔබ සිතන ආකාරයට එය විවෘත නොවේ.

ගුප්ත විද්‍යාවද මෙය කීවේය : පාවෙන අන්තර්ගතය එකලස් කිරීමේ කේතය පමණක් නොව වැදගත් වේ.

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.