SORU
16 ŞUBAT 2012, PERŞEMBE


Neden 0 0,1 f değişen 10x performansını yavaşlatır?

Neden kod, bu biraz işe yarar

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 kat daha hızlı aşağıdaki bit (belirtilmediği sürece aynı) çalıştırmak?

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; // <--
    }
}

Visual Studio 2010 SP1 ile derleniyor. (Diğer Derleyiciler ile test etmedim.)

CEVAP
16 ŞUBAT 2012, PERŞEMBE


denormalized floating-point dünyasına hoş geldiniz!Performans üzerinde hasara yol açıyor!!!

Denormal (veya) normalin altında sayılar kayan nokta gösterimi dışında bazı ekstra değerler sıfıra çok yakın almak için hack türüdür. Normal dışı işlemleri kayan nokta olabilirbir kez daha yavaş yüzlerce onlarcadaha üzerinde kayan nokta normalleştirilmiş. Bu birçok işlemciler doğrudan kaldıramıyor, tuzak ve onları mikro kodları kullanarak çözmek gerekir çünkü.

Eğer 10,000 tekrar sayıları yazdırmak için 0 0.1 kullanılmasına bağlı olarak farklı değerler için birleştirilmiş olduğunu göreceksiniz.

İşte test kodu 64 derleyen:

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;
}

Çıkış:

#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

İkinci dönemde sayıları sıfıra yakın bir kaç not.

Normal dışı sayıları genellikle nadirdir ve çoğu işlemciler onları verimli bir şekilde işlemek için çalışmayın böylece.


Bu normal dışı sayıları ile yapmak için her şeye sahip olduğunu göstermek için, eğer bizsıfır floş denormalskod: başlangıç için bu ekleyerek

_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);

Sonra 0 ile sürümü artık 10x daha yavaş olur ve aslında daha hızlı olur. (Bu kodu SSE etkin ile derlenmiş olması gerekir.)

Bu garip düşük duyarlık neredeyse sıfır değerleri kullanmak yerine, biz sadece yerine sıfır yuvarlak anlamına gelir.

Zamanlama: Core @ 3.5 GHz i7 920:

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

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

Sonunda, bu gerçekten önemli bir tamsayı olsun ile yapmak veya kayan nokta vardır. 0 0.1f her iki döngü kayıt dışında saklı/dönüştürülür. Bu performansı üzerinde hiçbir etkisi olmaz.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • guau . .

    guau . .

    25 Ocak 2008
  • Michael Lummio

    Michael Lumm

    25 Mayıs 2007
  • SDSARG3

    SDSARG3

    14 Mart 2009