Why in this example does using float make me go 2x slower than with doubles?

Recently, I have been doing profiling, and I came across one case that turns me nuts. The following is a snippet of unsafe C # code that basically copies the source fetch buffer to the target buffer with a different sample rate. As of now, it takes ~ 0.17% of the total processing time per frame. I do not understand that if I use float instead of double, the processing time will increase to 0.38%. Can someone explain what is going on here?

Fast version (~ 17%)

double rateIncr = ...
double readOffset = ...
double offsetIncr = ...

float v = ... // volume

// Source and target buffers.
float* src = ...
float* tgt = ...

for( var c = 0; c < chunkCount; ++c)
{
    for( var s = 0; s < chunkSampleSize; ++s )
    {
        // Source sample            
        var iReadOffset = (int)readOffset;

        // Interpolate factor
        var k = (float)readOffset - iReadOffset;

        // Linearly interpolate 2 contiguous samples and write result to target.
        *tgt++ += (src[ iReadOffset ] * (1f - k) + src[ iReadOffset + 1 ] * k) * v;

        // Increment source offset.
        readOffset += offsetIncr;
    }
    // Increment sample rate
    offsetIncr += rateIncr;
}

Slow Version (~ 38%)

float rateIncr = ...
float readOffset = ...
float offsetIncr = ...

float v = ... // volume

// Source and target buffers.
float* src = ...
float* tgt = ...

for( var c = 0; c < chunkCount; ++c)
{
    for( var s = 0; s < chunkSampleSize; ++s )
    {
        var iReadOffset = (int)readOffset;

        // The cast to float is removed
        var k = readOffset - iReadOffset;

        *tgt++ += (src[ iReadOffset ] * (1f - k) + src[ iReadOffset + 1 ] * k) * v;
        readOffset += offsetIncr;
    }
    offsetIncr += rateIncr;
}

Odd Version (~ 22%)

float rateIncr = ...
float readOffset = ...
float offsetIncr = ...

float v = ... // volume

// Source and target buffers.
float* src = ...
float* tgt = ...

for( var c = 0; c < chunkCount; ++c)
{
    for( var s = 0; s < chunkSampleSize; ++s )
    {
        var iReadOffset = (int)readOffset;
        var k = readOffset - iReadOffset;

        // By just placing this test it goes down from 38% to 22%,
        // and the condition is NEVER met.
        if( (k != 0) && Math.Abs( k ) < 1e-38 )
        {
           Console.WriteLine( "Denormalized float?" );
        }

        *tgt++ += (src[ iReadOffset ] * (1f - k) + src[ iReadOffset + 1 ] * k) * v;
        readOffset += offsetIncr;
    }
    offsetIncr += rateIncr;
}

Now i know i don't know anything

+3
7

64- 32- ? , , , , ( , 64- ). , , 32- ...

, , ++ ( , , ). ++, .


:

MSDN float .NET, float, , CLR float:

x87 FPU. , CLR ( , 80- x87) ( ), . , IL conv.r4 conv.r8 , .

, float , 80- FPU x87 - , . IL, , , , , . , #, fp ++, , .

+4

, , -, . IL , ?

+3

, float "denormal", x86. , . , , .

, , , , , .

http://en.wikipedia.org/wiki/Denormal

+2

, , - x86, . , # , , , - . , , .

, , , JIT . , , , .

+1

, 3 , , , , / .

32- :

// NOTE: runnable - copy in paste into your own project
class Program
    {
        static int endVal = 32768;
        static int runCount = 100;
        static void Main(string[] args)
        {
            Stopwatch doublesw = Stopwatch.StartNew();
            for (int i = 0; i < runCount; ++i)
                doubleTest();
            doublesw.Stop();
            Console.WriteLine("Double: " + doublesw.ElapsedMilliseconds);
            Stopwatch floatsw = Stopwatch.StartNew();
            for (int i = 0; i < runCount; ++i)
                floatTest();
            floatsw.Stop();
            Console.WriteLine("Float: " + floatsw.ElapsedMilliseconds);
            Console.ReadLine();
        }

        static void doubleTest()
        {
            double value = 0;
            double incr = 0.001D;

            while (value < endVal)
            {
                value += incr;
            }
        }

        static void floatTest()
        {
            float value = 0;
            float incr = 0.001f;

            while (value < endVal)
            {
                value += incr;
            }
        }
    }
}

:

Double: 12897
Float: 10059

, . , .

, , , , , , , , () , .

( №3 - - )

+1

, , :

(float)readOffset

float readOffset .

0

. , , - . , , ?

, , , - , .

I hope that my letter makes sense and is understandable. But in short, if your whole process requires a longer time, the percentage value for this function (which remains constant all the time due to the fact that it will not be changed) will drop.

0
source

Source: https://habr.com/ru/post/1708333/


All Articles