Float vs Double Performance


91

Tôi đã thực hiện một số bài kiểm tra thời gian và cũng đọc một số bài viết như bài này (nhận xét cuối cùng) và có vẻ như trong bản dựng Release, các giá trị float và double mất cùng một lượng thời gian xử lý.

Sao có thể như thế được? Khi float kém chính xác hơn và nhỏ hơn so với các giá trị gấp đôi, làm thế nào CLR có thể nhận được gấp đôi trong cùng một thời gian xử lý?


10
Tôi không nghĩ rằng nó là một bản sao chính xác như cái này là hỏi lý do đằng sau nó mà như là người dùng khác được yêu cầu nếu nó thực sự nhanh hơn, nhưng không nhất thiết do tại sao,
Joan Venge

Được cho là một bản sao chính xác của Double nhanh hơn float trong C #? (được xác nhận vào năm 2009 bởi một người dùng khác).
Peter Mortensen

Câu trả lời:


155

Trên các bộ xử lý x86, ít nhất floatdoublemỗi bộ sẽ được chuyển đổi thành giá trị thực 10 byte bởi FPU để xử lý. FPU không có các đơn vị xử lý riêng biệt cho các kiểu dấu phẩy động khác nhau mà nó hỗ trợ.

Lời khuyên lâu đời floathơn doubleđược áp dụng cách đây 100 năm khi hầu hết các CPU không có FPU tích hợp (và ít người có chip FPU riêng biệt), vì vậy hầu hết các thao tác dấu phẩy động đều được thực hiện trong phần mềm. Trên các máy (mà được cung cấp bởi hơi nước được tạo ra bởi các hố nham thạch), nó nhanh hơn để sử dụng floats. Giờ đây, lợi ích thực sự duy nhất đối với floats là chúng chiếm ít dung lượng hơn (điều này chỉ quan trọng nếu bạn có hàng triệu người trong số chúng).


9
Có lẽ không phải 100 năm trước ... Một số FPU hỗ trợ xử lý gốc ở các mức float, double và 80-bit và sẽ thực thi nhanh hơn ở độ dài ngắn hơn. Một số thực sự sẽ thực hiện một số điều chậm hơn ở độ dài ngắn quá ... :-)
Brian Knoblauch

4
Ngoại lệ có thể xảy ra: Tôi nghĩ thời gian phân chia phụ thuộc vào số lượng bit (1 chu kỳ đồng hồ / 2 bit). Thời gian tôi đã thực hiện bằng float và chia đôi dường như kiểm đếm với điều này.
Neil Coffey

21
Lưu ý đối với mã SIMD - vì bạn có thể đóng gói số lượng nổi gấp đôi so với số lượng gấp đôi vào một thanh ghi SIMD (ví dụ: SSE), khả năng hoạt động trên số nổi có thể nhanh hơn. Nhưng vì nó là C #, điều đó có thể sẽ không xảy ra.
Calyth

13
@P Daddy: Tôi muốn nói rằng lợi thế về không gian quan trọng ở mọi cấp độ của hệ thống phân cấp bộ nhớ cache. Khi bộ nhớ cache dữ liệu cấp đầu tiên của bạn lớn 16KB và bạn đang xử lý một mảng 4000 số, float có thể dễ dàng nhanh hơn.
Peter G.

4
@artinkingidiot Đừng bao giờ nói không bao giờ;). SIMD được hỗ trợ trong .NET kể từ ngày 4.6
bóng ma

13

Tôi đã có một dự án nhỏ trong đó tôi sử dụng CUDA và tôi có thể nhớ rằng float cũng nhanh hơn gấp đôi ở đó. Khi lưu lượng giữa Máy chủ và Thiết bị thấp hơn (Máy chủ là CPU và RAM "bình thường" và Thiết bị là GPU và RAM tương ứng ở đó). Nhưng ngay cả khi dữ liệu luôn nằm trên Thiết bị, nó vẫn chậm hơn. Tôi nghĩ rằng tôi đã đọc ở đâu đó rằng điều này đã thay đổi gần đây hoặc được cho là sẽ thay đổi với thế hệ tiếp theo, nhưng tôi không chắc.

Vì vậy, có vẻ như GPU chỉ đơn giản là không thể xử lý độ chính xác gấp đôi nguyên bản trong những trường hợp đó, điều này cũng sẽ giải thích tại sao GLFloat thường được sử dụng hơn là GLDouble.

(Như tôi đã nói, nó chỉ theo chừng mực tôi có thể nhớ được, tôi chỉ tình cờ phát hiện ra điều này khi đang tìm kiếm float so với double trên CPU.)


6
GPU hoàn toàn khác với FPU. Như những người khác đã đề cập định dạng gốc của FPU là độ chính xác kép 80 bit. Và đó là một thời gian dài bây giờ. Tuy nhiên, GPU tiếp cận trường này từ độ chính xác duy nhất. Ai cũng biết rằng hiệu suất DP FP (dấu chấm động chính xác kép) của họ thường chính xác bằng một nửa hiệu suất SP FP. Có vẻ như họ thường có đơn vị dấu phẩy động SP, và họ phải sử dụng lại đơn vị đó để che đi độ chính xác gấp đôi. Mà sinh ra đúng hai chu kỳ so với một. Đó là một sự khác biệt lớn về hiệu suất , khiến tôi choáng váng khi đối mặt với nó.
Csaba Toth

1
Một số tính toán khoa học yêu cầu DP FP và các nhà sản xuất GPU hàng đầu đã không quảng cáo về hình phạt hiệu suất xung quanh điều đó. Bây giờ họ (AMD, nVidia) dường như đã cải thiện phần nào về chủ đề DP vs SP đó. Nhiều lõi của Intel Xeon Phi chứa FPU của Pentium và lưu ý rằng Intel nhấn mạnh rằng nó có khả năng chính xác gấp đôi . Đó là nơi nó có thể thực sự có thể cạnh tranh với quái vật GPGPU.
Csaba Toth

12

Tuy nhiên, vẫn có một số trường hợp mà float được ưu tiên hơn - ví dụ như với mã hóa OpenGL, việc sử dụng kiểu dữ liệu GLFloat (thường được ánh xạ trực tiếp tới float 16 bit) phổ biến hơn nhiều vì nó hiệu quả hơn trên hầu hết các GPU so với GLDouble.


3
Có thể do thông lượng dữ liệu cao hơn? Nếu bạn có một ma trận các số (z-buffer, v.v.), kích thước dữ liệu trở nên quan trọng hơn và việc tránh chuyển đổi giữa float và double sẽ tăng tốc độ xử lý. Tôi đoán.
Lucero

2
Không nghi ngờ gì nữa, thông lượng. Cũng trong bối cảnh chuyên có điều gì không thể nhìn thấy được thu được từ việc sử dụng đôi qua nổi vậy tại sao lãng phí bộ nhớ - đặc biệt vì nó là nguồn cung ngắn trên GPU hơn CPU
Cruachan

1
Thông lượng thực tế là SP FP (dấu chấm động chính xác đơn) là định dạng gốc của FPU bên trong GPU hơn là DP FP (độ chính xác kép). Xem bình luận của tôi cho câu trả lời của @ Mene. FPU của GPU và CPU là những động vật rất khác nhau, FPU của CPU đang suy nghĩ trong DP FP.
Csaba Toth


12

Nó phụ thuộc vào hệ thống 32 bit hoặc 64 bit . Nếu bạn biên dịch sang 64-bit, gấp đôi sẽ nhanh hơn. Được biên dịch thành 32-bit trên 64-bit (máy và hệ điều hành) giúp trôi nổi nhanh hơn khoảng 30%:

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

2
Bạn đã xem 30% đó có thể là do bạn sử dụng thêm phôi chưa ??
Rasmus Nielsen Damgaard

@RasmusDamgaardNielsen Các phôi là một phần của vấn đề vì Mathhoạt động với double. Nhưng bạn đã đọc sai bài đăng của tôi: các bài kiểm tra của tôi cho thấy tôi nổi hơn về hiệu suất.
Bitterblue

2
Kết quả được đăng ở trên là không có thật. Các thử nghiệm của tôi cho thấy rằng trên máy 32-bit cũ hơn có .NET 4.0 ở chế độ Phát hành, hiệu suất floatdoublehiệu suất hầu như giống hệt nhau. Chênh lệch ít hơn 0,3% khi được tính trung bình trong nhiều thử nghiệm độc lập, trong đó mỗi thử nghiệm thực hiện các hoạt động nhân, chia và cộng trên các biến chuỗi liên tiếp (để tránh bất kỳ tối ưu hóa trình biên dịch nào cản trở). Tôi đã thử một bộ thử nghiệm thứ hai với Math.Sin()Math.Sqrt()và cũng nhận được kết quả giống hệt nhau.
Sốt đặc biệt
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.