ลอยเทียบกับประสิทธิภาพสองเท่า


92

ฉันทำการทดสอบเวลาและอ่านบทความเช่นนี้ด้วย (ความคิดเห็นล่าสุด) และดูเหมือนว่าใน Release build ค่า float และ double ใช้เวลาในการประมวลผลเท่ากัน

เป็นไปได้อย่างไร? เมื่อ float มีความแม่นยำน้อยกว่าและมีขนาดเล็กกว่าเมื่อเทียบกับค่าสองค่า CLR จะเพิ่มเป็นสองเท่าในเวลาประมวลผลเดียวกันได้อย่างไร?


10
ฉันไม่คิดว่ามันจะซ้ำกันอย่างแน่นอนเนื่องจากคนนี้กำลังถามเหตุผลเบื้องหลังที่ผู้ใช้คนอื่นถามว่ามันเร็วขึ้นจริงหรือไม่ แต่ไม่จำเป็นว่าทำไม
Joan Venge

สมมติว่าซ้ำกันแน่นอนว่าเป็นสองเท่าเร็วกว่าลอยใน C # หรือไม่? (อ้างสิทธิ์ในปี 2552 โดยผู้ใช้รายอื่น)
Peter Mortensen

คำตอบ:


156

บนโปรเซสเซอร์ x86 เป็นอย่างน้อยfloatและdoubleแต่ละตัวจะถูกแปลงเป็น 10 ไบต์จริงโดย FPU สำหรับการประมวลผล FPU ไม่มีหน่วยประมวลผลแยกต่างหากสำหรับประเภททศนิยมต่างๆที่รองรับ

คำแนะนำที่เก่าแก่floatเร็วกว่าที่doubleใช้เมื่อ 100 ปีก่อนเมื่อซีพียูส่วนใหญ่ไม่มี FPU ในตัว (และมีไม่กี่คนที่มีชิป FPU แยกต่างหาก) ดังนั้นการจัดการทศนิยมส่วนใหญ่จึงทำในซอฟต์แวร์ บนเครื่องเหล่านี้ (ซึ่งถูกขับเคลื่อนโดยอบไอน้ำที่เกิดจากหลุมลาวา) ก็เป็นได้เร็วขึ้นเพื่อใช้floats ตอนนี้ประโยชน์ที่แท้จริงเพียงอย่างเดียวfloatคือพวกเขาใช้พื้นที่น้อยลง (ซึ่งสำคัญก็ต่อเมื่อคุณมีหลายล้านคน)


9
อาจจะไม่ถึง 100 ปีที่แล้ว ... FPU บางตัวรองรับการจัดการแบบเนทีฟที่ระดับ float, double และ 80-bit และจะทำงานได้เร็วขึ้นที่ความยาวสั้นลง บางคนจะดำเนินการบางอย่างช้าลงในความยาวที่สั้นลงด้วย ... :-)
Brian Knoblauch

4
ข้อยกเว้นที่เป็นไปได้: ฉันคิดว่าเวลาสำหรับการหารขึ้นอยู่กับจำนวนบิต (1 รอบนาฬิกา / 2 บิต) การกำหนดเวลาที่ฉันทำจาก float vs double division ดูเหมือนจะนับด้วยสิ่งนี้
Neil Coffey

22
ข้อแม้สำหรับรหัส SIMD - เนื่องจากคุณสามารถแพ็ค 2x float ได้มากกว่าสองเท่าในการลงทะเบียน SIMD (เช่น SSE) การทำงานบนโฟลตอาจเร็ว แต่เนื่องจากเป็น C # จึงไม่น่าจะเกิดขึ้น
Calyth

14
@P Daddy: ฉันจะบอกว่าข้อได้เปรียบของพื้นที่มีความสำคัญในทุกระดับของแคช hierachy เมื่อแคชข้อมูลระดับแรกของคุณมีขนาดใหญ่ถึง 16KB และคุณกำลังกระทืบอาร์เรย์จำนวน 4000 ตัวเลขการลอยตัวอาจเร็วขึ้นอย่างง่ายดาย
Peter G.

4
@art artificialidiot Never say never;). SIMD ได้รับการสนับสนุนใน. NET ตั้งแต่ 4.6
ghord

14

มันขึ้นอยู่กับ32 บิตหรือ64 บิตระบบ หากคุณคอมไพล์เป็น 64 บิต double จะเร็วขึ้น คอมไพล์เป็น 32 บิตบน 64 บิต (เครื่องและระบบปฏิบัติการ) ทำให้ float เร็วขึ้น 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);
    }

3
คุณคิดว่า 30% เหล่านั้นอาจเป็นเพราะการร่ายเสริมที่คุณใช้ ??
Rasmus Damgaard Nielsen

@RasmusDamgaardNielsen นักแสดงเป็นส่วนหนึ่งของปัญหาเนื่องจากMathทำงานร่วมกับ double แต่คุณอ่านโพสต์ของฉันผิด: การทดสอบของฉันแสดงให้เห็นว่าฉันมีประสิทธิภาพที่ดีขึ้น
Bitterblue

2
ผลลัพธ์ที่โพสต์ข้างต้นเป็นของปลอม การทดสอบของฉันแสดงให้เห็นว่าในเครื่อง 32 บิตรุ่นเก่าที่มี. NET 4.0 ในโหมดรีลีสประสิทธิภาพfloatและdoubleประสิทธิภาพแทบจะเหมือนกัน ความแตกต่างน้อยกว่า 0.3% เมื่อเฉลี่ยในการทดลองอิสระจำนวนมากโดยที่การทดลองแต่ละครั้งใช้การคูณหารและการเพิ่มตัวแปรที่ถูกล่ามโซ่ติดต่อกัน (เพื่อหลีกเลี่ยงการเพิ่มประสิทธิภาพคอมไพเลอร์ใด ๆ ที่ขวางทาง) ฉันพยายามชุดที่สองของการทดสอบด้วยMath.Sin()และMath.Sqrt()และยังมีผลเหมือนกัน
ซอสสูตรพิเศษ

13

ฉันมีโปรเจ็กต์เล็ก ๆ ที่ฉันใช้ CUDA และฉันจำได้ว่า float เร็วกว่าที่นั่นถึงสองเท่าด้วย เมื่อปริมาณการใช้งานระหว่างโฮสต์และอุปกรณ์ต่ำลง (โฮสต์คือ CPU และ RAM และอุปกรณ์ "ปกติ" คือ GPU และแรมที่เกี่ยวข้องที่นั่น) แต่แม้ว่าข้อมูลจะอยู่ในอุปกรณ์ตลอดเวลาก็ช้าลง ฉันคิดว่าฉันอ่านที่ไหนสักแห่งที่มีการเปลี่ยนแปลงเมื่อไม่นานมานี้หรือควรจะเปลี่ยนกับคนรุ่นต่อไป แต่ฉันไม่แน่ใจ

ดูเหมือนว่า GPU จะไม่สามารถจัดการความแม่นยำสองเท่าได้ในกรณีเหล่านั้นซึ่งจะอธิบายได้ว่าทำไมมักใช้ GLFloat มากกว่า GLDouble

(อย่างที่บอกไปเท่าที่จำได้ก็สะดุดกับสิ่งนี้ขณะค้นหา float เทียบกับ double บน CPU)


7
GPU เป็นสัตว์ที่แตกต่างจาก FPU โดยสิ้นเชิง ดังที่คนอื่นกล่าวถึงรูปแบบดั้งเดิมของ FPU คือความแม่นยำสองเท่า 80 บิต และนั่นเป็นเวลานานแล้ว อย่างไรก็ตาม GPU เข้าใกล้ฟิลด์นี้จากความแม่นยำเดียว เป็นที่ทราบกันดีอยู่แล้วว่าประสิทธิภาพของ DP FP (จุดลอยตัวที่มีความแม่นยำสองเท่า) มักจะเท่ากับครึ่งหนึ่งของประสิทธิภาพ SP FP ดูเหมือนว่าพวกเขามักจะมีหน่วยจุดลอยตัว SP และพวกเขาต้องใช้หน่วยซ้ำเพื่อให้ครอบคลุมความแม่นยำสองเท่า ซึ่งให้ผลตอบแทนสองรอบเมื่อเทียบกับหนึ่งรอบ นั่นคือความแตกต่างด้านประสิทธิภาพอย่างมากซึ่งทำให้ฉันตกตะลึงเมื่อต้องเผชิญกับมัน
Csaba Toth

1
การคำนวณทางวิทยาศาสตร์บางอย่างต้องใช้ DP FP และผู้ผลิต GPU ชั้นนำไม่ได้โฆษณาการลงโทษด้านประสิทธิภาพในรอบนั้น ตอนนี้พวกเขา (AMD, nVidia) ดูเหมือนจะปรับปรุงในหัวข้อ DP เทียบกับ SP นั้น คอร์จำนวนมากของ Intel Xeon Phi ประกอบด้วย FPU ของ Pentium และสังเกตได้ว่า Intel เน้นย้ำถึงความสามารถที่มีความแม่นยำสองเท่า นั่นคือสิ่งที่อาจจะสามารถแข่งขันกับมอนสเตอร์ GPGPU ได้
Csaba Toth

12

ยังคงมีบางกรณีที่ต้องการการลอยตัว - ด้วยการเข้ารหัส OpenGL เช่นการใช้ประเภทข้อมูล GLFloat เป็นเรื่องปกติมาก (โดยทั่วไปจะแมปโดยตรงกับ 16 บิตลอย) เนื่องจากมีประสิทธิภาพมากกว่า GPU ส่วนใหญ่มากกว่า GLDouble


3
อาจเป็นเพราะปริมาณข้อมูลที่สูงขึ้น? หากคุณมีเมทริกซ์ของตัวเลข (z-buffer เป็นต้น) ขนาดข้อมูลจะมีความสำคัญมากขึ้นและหลีกเลี่ยงการแปลงระหว่าง float และเพิ่มความเร็วในการจัดการเป็นสองเท่า ฉันเดา
Lucero

2
ปริมาณงานที่ไม่ต้องสงสัย นอกจากนี้ยังมีบริบทพิเศษที่ไม่น่าเป็นไปได้ที่จะได้รับจากการใช้ double over float ดังนั้นทำไมต้องสิ้นเปลืองหน่วยความจำโดยเฉพาะอย่างยิ่งเนื่องจากมีการจัดหา GPU ที่สั้นกว่า CPU
Cruachan

1
ปริมาณงานและข้อเท็จจริงที่ว่า SP FP (single precision floating point) เป็นรูปแบบดั้งเดิมของ FPU ภายใน GPU มากกว่า DP FP (double precision) ดูความคิดเห็นของฉันต่อคำตอบของ @ Mene FPU ของ GPU และ CPU เป็นสัตว์ที่แตกต่างกันมาก FPU ของ CPU กำลังคิดใน DP FP
Csaba Toth

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.