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


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.