Mengambang vs Kinerja Ganda

92

Saya melakukan beberapa tes waktu dan juga membaca beberapa artikel seperti ini (komentar terakhir), dan sepertinya dalam Rilis nilai build, float dan double membutuhkan waktu pemrosesan yang sama.

Bagaimana ini mungkin? Ketika float kurang tepat dan lebih kecil dibandingkan dengan nilai ganda, bagaimana CLR bisa berlipat ganda ke dalam waktu pemrosesan yang sama?

Joan Venge
sumber
10
Saya tidak berpikir itu duplikat persis karena yang satu ini menanyakan alasan di baliknya di mana pengguna lain bertanya apakah itu sebenarnya lebih cepat, tetapi belum tentu mengapa,
Joan Venge
Seharusnya duplikat yang tepat dari Apakah ganda lebih cepat daripada pelampung di C #? (diklaim pada 2009 oleh pengguna lain).
Peter Mortensen

Jawaban:

156

Pada prosesor x86, setidaknya, floatdan doublemasing-masing akan dikonversi menjadi 10-byte nyata oleh FPU untuk diproses. FPU tidak memiliki unit pemrosesan terpisah untuk berbagai jenis floating-point yang didukungnya.

Saran kuno yang floatlebih cepat daripada yang doublediterapkan 100 tahun yang lalu ketika sebagian besar CPU tidak memiliki FPU bawaan (dan hanya sedikit orang yang memiliki chip FPU terpisah), jadi sebagian besar manipulasi floating-point dilakukan dalam perangkat lunak. Pada mesin ini (yang didukung oleh uap yang dihasilkan oleh lubang lava), itu adalah lebih cepat untuk menggunakan floats. Sekarang satu-satunya manfaat nyata untuk floats adalah bahwa mereka mengambil lebih sedikit ruang (yang hanya penting jika Anda memiliki jutaan).

P Ayah
sumber
9
Mungkin tidak 100 tahun yang lalu ... Beberapa FPU mendukung penanganan asli pada level float, double, dan 80-bit dan akan dieksekusi lebih cepat pada panjang yang lebih pendek. Beberapa benar-benar akan mengeksekusi beberapa hal lebih lambat dengan durasi yang lebih pendek juga ... :-)
Brian Knoblauch
4
Kemungkinan pengecualian: Saya pikir waktu untuk divisi tergantung pada jumlah bit (1 siklus jam / 2 bit). Pengaturan waktu yang saya buat dari divisi float vs double tampaknya cocok dengan ini.
Neil Coffey
22
Peringatan untuk kode SIMD - karena Anda dapat mengemas 2x float dari dua kali lipat ke dalam register SIMD (misalnya SSE), operasi potensial pada float bisa lebih cepat. Tapi karena itu C #, kemungkinan itu tidak akan terjadi.
Calyth
14
@P Ayah: Menurut saya, keuntungan ruang penting di setiap tingkat hierarki cache. Ketika cache data tingkat pertama Anda berukuran 16KB dan Anda mengolah array 4000 angka, float bisa dengan mudah menjadi lebih cepat.
Peter G.
4
@ artificialidiot Jangan pernah mengatakan tidak pernah;). SIMD didukung dalam .NET sejak 4.6
ghord
14

Itu tergantung pada sistem 32-bit atau 64-bit . Jika Anda mengompilasi ke 64-bit, penggandaan akan lebih cepat. Dikompilasi menjadi 32-bit pada 64-bit (mesin dan OS) membuat float sekitar 30% lebih cepat:

    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);
    }
Bitterblue
sumber
3
Apakah Anda menganggap 30% itu bisa jadi karena pemeran tambahan yang Anda gunakan ??
Rasmus Damgaard Nielsen
@RasmusDamgaardNielsen Para pemeran adalah bagian dari masalah karena Mathbekerja dengan ganda. Tapi Anda salah membaca posting saya: tes saya menunjukkan kinerja saya mengambang lebih baik.
Bitterblue
2
Hasil yang diposting di atas adalah palsu. Pengujian saya menunjukkan bahwa pada mesin 32-bit yang lebih lama dengan .NET 4.0 dalam mode Rilis, kinerja floatdan doublehampir identik. Perbedaan kurang dari 0,3% ketika dirata-ratakan pada banyak uji coba independen, di mana setiap uji coba melakukan operasi perkalian, bagi, dan penambahan pada variabel yang dirantai secara berurutan (untuk menghindari pengoptimalan compiler menghalangi). Saya mencoba rangkaian tes kedua dengan Math.Sin()dan Math.Sqrt()dan juga mendapatkan hasil yang sama.
Saus Spesial
13

Saya memiliki proyek kecil di mana saya menggunakan CUDA dan saya ingat bahwa float juga lebih cepat dari dua kali lipat di sana. Untuk sekali lalu lintas antara Host dan Perangkat lebih rendah (Host adalah CPU dan RAM "normal" dan Perangkat adalah GPU dan RAM yang sesuai di sana). Tetapi bahkan jika data berada di Perangkat sepanjang waktu itu lebih lambat. Saya rasa saya pernah membaca bahwa ini telah berubah baru-baru ini atau seharusnya berubah dengan generasi berikutnya, tetapi saya tidak yakin.

Jadi tampaknya GPU tidak dapat menangani presisi ganda secara native dalam kasus tersebut, yang juga menjelaskan mengapa GLFloat biasanya digunakan daripada GLDouble.

(Seperti yang saya katakan itu hanya sejauh yang saya ingat, baru saja menemukan ini saat mencari float vs. double pada CPU.)

Mene
sumber
7
GPU adalah hewan yang sangat berbeda dari FPU. Seperti yang disebutkan orang lain, format asli FPU adalah presisi ganda 80 bit. Dan itu sudah lama sekali. Namun GPU mendekati bidang ini dari presisi tunggal. Diketahui dengan baik bahwa kinerja DP FP (double precision floating point) mereka seringkali persis setengah dari kinerja SP FP. Tampaknya mereka sering memiliki unit titik mengambang SP, dan mereka harus menggunakan kembali unit tersebut untuk menutupi presisi ganda. Yang menghasilkan tepat dua siklus dibandingkan dengan satu. Itu adalah perbedaan kinerja yang sangat besar , yang membuat saya tercengang ketika saya menghadapinya.
Csaba Toth
1
Beberapa perhitungan ilmiah memerlukan DP FP, dan pabrikan GPU utama tidak mengiklankan hukuman kinerja di sekitarnya. Sekarang mereka (AMD, nVidia) tampaknya agak memperbaiki topik DP vs SP itu. Banyak inti Intel Xeon Phi berisi FPU Pentium, dan perhatikan bahwa Intel menekankan kemampuan presisi ganda itu . Di situlah mungkin benar-benar bisa bersaing dengan monster GPGPU.
Csaba Toth
12

Masih ada beberapa kasus di mana float lebih disukai - dengan pengkodean OpenGL misalnya, jauh lebih umum menggunakan tipe data GLFloat (umumnya dipetakan langsung ke float 16 bit) karena lebih efisien pada sebagian besar GPU daripada GLDouble.

Cruachan
sumber
3
Mungkin karena throughput data yang lebih tinggi? Jika Anda memiliki matriks angka (z-buffer dll.), Ukuran data menjadi lebih penting, dan menghindari konversi antara float dan double mempercepat penanganan. Tebakanku.
Lucero
2
Tidak diragukan lagi throughput. Juga mengingat konteks khusus, tidak mungkin ada sesuatu yang terlihat dapat diperoleh dari penggunaan double over float jadi mengapa membuang-buang memori - terutama karena persediaannya lebih pendek pada GPU daripada CPU
Cruachan
1
Throughput dan juga fakta bahwa SP FP (single precision floating point) lebih merupakan format asli FPU internal GPU daripada DP FP (presisi ganda). Lihat komentar saya untuk jawaban @ Mene. GPU dan FPU CPU adalah hewan yang sangat berbeda, FPU CPU berpikir dalam DP FP.
Csaba Toth