Domanda

Ho fatto alcuni test di temporizzazione e ho anche letto alcuni articoli come questo (ultimo commento), e sembra che in Build build, float e valori doppi prendano la stessa quantità di tempo di elaborazione.

Come è possibile? Quando il float è meno preciso e più piccolo rispetto ai doppi valori, come può il CLR raddoppiare nello stesso tempo di elaborazione?

È stato utile?

Soluzione

Sui processori x86, almeno, float e double saranno ciascuno convertiti in un reale a 10 byte dall'FPU per l'elaborazione. La FPU non ha unità di elaborazione separate per i diversi tipi in virgola mobile che supporta.

Il consiglio secolare che float è più veloce di double applicato 100 anni fa quando la maggior parte delle CPU non aveva FPU integrate (e poche persone avevano FPU separate chip), quindi la maggior parte delle manipolazioni in virgola mobile è stata eseguita nel software. Su queste macchine (che erano alimentate dal vapore generato dalle fosse di lava), era più veloce usare float . Ora l'unico vero vantaggio di float è che occupano meno spazio (il che conta solo se ne hai milioni).

Altri suggerimenti

Avevo un piccolo progetto in cui utilizzavo CUDA e ricordo che anche il float era più veloce del doppio. Per una volta il traffico tra Host e Device è inferiore (Host è la CPU e la RAM "normale" e Device è la GPU e la RAM corrispondente lì). Ma anche se i dati risiedono sul dispositivo tutto il tempo è più lento. Penso di aver letto da qualche parte che questo è cambiato di recente o dovrebbe cambiare con la prossima generazione, ma non sono sicuro.

Quindi sembra che la GPU semplicemente non riesca a gestire la doppia precisione in modo nativo in quei casi, il che spiegherebbe anche perché GLFloat viene solitamente utilizzato anziché GLDouble.

(Come ho detto, è solo per quanto posso ricordare, sono inciampato su questo durante la ricerca di float vs. double su una CPU.)

Dipende dal sistema 32 bit o 64 bit . Se si compila a 64 bit, il doppio sarà più veloce. Compilato a 32 bit su 64 bit (macchina e sistema operativo) ha reso il float circa il 30% più veloce:

    public static void doubleTest(int loop)
    {
        Console.Write("double: ");
        for (int i = 0; i < loop; i++)
        {
            double a = 1000, b = 45, c = 12000, d = 2, e = 7, f = 1024;
            a = Math.Sin(a);
            b = Math.Asin(b);
            c = Math.Sqrt(c);
            d = d + d - d + d;
            e = e * e + e * e;
            f = f / f / f / f / f;
        }
    }

    public static void floatTest(int loop)
    {
        Console.Write("float: ");
        for (int i = 0; i < loop; i++)
        {
            float a = 1000, b = 45, c = 12000, d = 2, e = 7, f = 1024;
            a = (float) Math.Sin(a);
            b = (float) Math.Asin(b);
            c = (float) Math.Sqrt(c);
            d = d + d - d + d;
            e = e * e + e * e;
            f = f / f / f / f / f;
        }
    }

    static void Main(string[] args)
    {
        DateTime time = DateTime.Now;
        doubleTest(5 * 1000000);
        Console.WriteLine("milliseconds: " + (DateTime.Now - time).TotalMilliseconds);

        time = DateTime.Now;
        floatTest(5 * 1000000);
        Console.WriteLine("milliseconds: " + (DateTime.Now - time).TotalMilliseconds);

        Thread.Sleep(5000);
    }

Ci sono ancora alcuni casi in cui si preferiscono i float - ad esempio con la codifica OpenGL è molto più comune usare il tipo di dati GLFloat (generalmente mappato direttamente su float a 16 bit) in quanto è più efficiente sulla maggior parte delle GPU rispetto a GLDouble.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top