ทำไมประเภทจำนวนเต็มแบบเร็วจึงเร็วกว่าประเภทจำนวนเต็มอื่น ๆ


107

ใน ISO / IEC 9899: 2018 (C18) แสดงไว้ภายใต้ 7.20.1.3:

7.20.1.3 ประเภทจำนวนเต็มความกว้างต่ำสุดที่เร็วที่สุด

1 แต่ละประเภทต่อไปนี้กำหนดประเภทจำนวนเต็มที่มักจะเร็วที่สุด268)เพื่อใช้งานกับประเภทจำนวนเต็มทั้งหมดที่มีความกว้างอย่างน้อยที่ระบุ

2 ชื่อ typedef int_fastN_tกำหนดประเภทจำนวนเต็มที่เร็วที่สุดที่ลงนามด้วยความกว้างอย่างน้อย N ชื่อ typedef uint_fastN_tกำหนดประเภทจำนวนเต็มที่ไม่ได้ลงชื่อที่เร็วที่สุดที่มีความกว้างอย่างน้อย N

3 ประเภทต่อไปนี้จำเป็นต้องใช้:

int_fast8_t, int_fast16_t, int_fast32_t, int_fast64_t, uint_fast8_t, uint_fast16_t, uint_fast32_t,uint_fast64_t

ประเภทอื่น ๆ ทั้งหมดของแบบฟอร์มนี้เป็นตัวเลือก


268)ประเภทที่กำหนดไม่รับประกันว่าจะเร็วที่สุดสำหรับทุกวัตถุประสงค์ หากการนำไปใช้ไม่มีเหตุผลที่ชัดเจนสำหรับการเลือกประเภทหนึ่งมากกว่าประเภทอื่นก็จะเลือกประเภทจำนวนเต็มบางอย่างที่ตอบสนองความต้องการของการลงนามและความกว้าง


แต่ไม่ได้ระบุว่าทำไมประเภทจำนวนเต็ม "เร็ว" เหล่านี้จึงเร็วกว่า

  • ทำไมจำนวนเต็มแบบเร็วเหล่านี้จึงเร็วกว่าประเภทจำนวนเต็มอื่น ๆ

ผมติดแท็กคำถามกับ C ++ เพราะประเภทจำนวนเต็มอย่างรวดเร็วนอกจากนี้ยังมีใน C ++ 17 cstdintในไฟล์ส่วนหัวของ น่าเสียดายที่ใน ISO / IEC 14882: 2017 (C ++ 17) ไม่มีส่วนดังกล่าวเกี่ยวกับคำอธิบายของพวกเขา ฉันได้นำส่วนนั้นไปใช้ในส่วนของคำถาม


ข้อมูล: ใน C stdint.hพวกเขาจะประกาศในแฟ้มของส่วนหัว


24
จุดสำคัญที่นี่คือประเภทจำนวนเต็มเหล่านี้ไม่ได้แยกจากกันประเภทที่เร็วกว่าอย่างน่าอัศจรรย์ พวกเขาเป็นเพียงนามแฝงกับประเภทที่มีอยู่ตามปกติคือเร็วที่สุดสำหรับเครื่องนั้นสำหรับการดำเนินการนั้น
mtraceur

3
คอมไพเลอร์ส่งเสียงการทำงานของซีพียูเพื่อโหลดจัดเก็บปิดบังและแก้ไขตำแหน่งหน่วยความจำและการลงทะเบียนขนาดเฉพาะ นั่นคือทั้งหมดที่ CPU เห็น ระบบปฏิบัติการไม่เกี่ยวอะไรกับมันเลย มันเป็นการทำงานของคอมไพเลอร์เหมือนกับว่าคุณได้ระบุ typedef ของคุณเอง (ฉันคิดว่าคอมไพเลอร์ได้รับอนุญาตให้ดำเนินการภายในแตกต่างกัน - อาจมีประสิทธิภาพมากขึ้นถ้าเป็นไปได้ - กว่าผู้ใช้ typedef ตราบใดที่ไม่มีความแตกต่างในพฤติกรรม)
Peter - Reinstate Monica

1
@ RobertS-ReinstateMonica เพื่อความแม่นยำ "นามแฝง" เหล่านี้เป็นเพียงtypedefข้อความ ดังนั้นโดยทั่วไปจะทำในระดับห้องสมุดมาตรฐาน แน่นอนข้อ จำกัด C ทำให้ไม่มีมาตรฐานจริงในสิ่งที่พวกเขาtypedefไป - ดังนั้นสำหรับตัวอย่างการใช้งานโดยทั่วไปคือการทำให้ของบนระบบ 32 บิต แต่เรียบเรียงสมมุติอาจตัวอย่างเช่นใช้ชนิดภายในและสัญญาว่าจะทำบางแฟนซี การเพิ่มประสิทธิภาพในการเลือกชนิดของเครื่องที่เร็วที่สุดบนพื้นฐานกรณีโดยกรณีสำหรับตัวแปรประเภทนั้นแล้วห้องสมุดก็สามารถไปที่ int_fast32_ttypedefint__int_fasttypedef
mtraceur

1
@ RobertS-ReinstateMonica ใช่จริง คุณได้รับโปรแกรมประสิทธิภาพสูงสุดด้วยแฟล็กการรวบรวมสถาปัตยกรรมเฉพาะซึ่งทำให้ไบนารีแบบพกพาน้อยลง
Peter - Reinstate Monica

1
@ โรเบิร์ต-ReinstateMonica มันจะมีประสิทธิภาพมากที่สุดบนเวทีมันก็รวบรวมสำหรับไม่จำเป็นต้องเกี่ยวกับ
HABO

คำตอบ:


152

ลองนึกภาพ CPU ที่มีการดำเนินการทางคณิตศาสตร์เพียง 64 บิต ลองจินตนาการว่าคุณจะใช้งานการเพิ่ม 8 บิตที่ไม่ได้ลงชื่อบนซีพียูดังกล่าวได้อย่างไร มันจะต้องเกี่ยวข้องกับการดำเนินงานมากกว่าหนึ่งเพื่อให้ได้ผลลัพธ์ที่ถูกต้อง บน CPU ดังกล่าวการดำเนินการ 64 บิตเร็วกว่าการดำเนินการกับความกว้างจำนวนเต็มอื่น ๆ ในสถานการณ์นี้ทั้งหมดXint_fastY_tอาจเป็นนามแฝงของชนิด 64 บิต

หาก CPU สนับสนุนการดำเนินการที่รวดเร็วสำหรับประเภทจำนวนเต็มแบบแคบและทำให้ประเภทที่กว้างกว่าไม่เร็วกว่าประเภทที่แคบกว่าดังนั้นXint_fastY_tจะไม่เป็นนามแฝงของประเภทที่กว้างกว่าที่จำเป็นในการเป็นตัวแทนบิต Y ทั้งหมด

จากความอยากรู้ฉันได้ตรวจสอบขนาดของการติดตั้งเฉพาะ (GNU, Linux) ในบางสถาปัตยกรรม สิ่งเหล่านี้ไม่เหมือนกันในการนำไปใช้งานทั้งหมดในสถาปัตยกรรมเดียวกัน:

┌────╥───────────────────────────────────────────────────────────┐
 Y     sizeof(Xint_fastY_t) * CHAR_BIT                         
    ╟────────┬─────┬───────┬─────┬────────┬──────┬────────┬─────┤
     x86-64  x86  ARM64  ARM  MIPS64  MIPS  MSP430  AVR 
╞════╬════════╪═════╪═══════╪═════╪════════╪══════╪════════╪═════╡
 8   8       8    8      32   8       8     16      8   
 16  64      32   64     32   64      32    16      16  
 32  64      32   64     32   64      32    32      32  
 64  64      64   64     64   64      64    64      64  
└────╨────────┴─────┴───────┴─────┴────────┴──────┴────────┴─────┘

โปรดทราบว่าแม้ว่าการดำเนินการกับชนิดที่มีขนาดใหญ่กว่าอาจเร็วกว่า แต่ประเภทดังกล่าวยังใช้พื้นที่ในแคชมากขึ้นด้วยดังนั้นการใช้งานดังกล่าวไม่จำเป็นต้องให้ประสิทธิภาพที่ดีกว่า นอกจากนี้เราไม่สามารถไว้วางใจได้เสมอว่าการดำเนินการได้เลือกทางเลือกที่ถูกต้องตั้งแต่แรก เช่นเคยการวัดจำเป็นสำหรับผลลัพธ์ที่ดีที่สุด


ภาพหน้าจอของตารางสำหรับผู้ใช้ Android:

สกรีนช็อตของตารางด้านบน

(Android ไม่มีตัวอักษรวาดกล่องในแบบอักษรโมโน - อ้างอิง )


ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
Samuel Liew

@RobertSsupportsMonicaCellio หมายเลข "ไม่เหมือนกันในทุกสถาปัตยกรรม" ก็เป็นความจริง แต่ก็เห็นได้ทันทีจากข้อมูลที่แสดงดังนั้นฉันจะไม่คิดว่าจำเป็นต้องระบุสิ่งที่ชัดเจน ฉันได้แสดงเฉพาะค่าจากการนำไปใช้อย่างใดอย่างหนึ่งและอื่น ๆ แน่นอนว่าจะมีตัวเลือกที่แตกต่างกัน ตรวจสอบตัวอย่าง x86-64 บน windows คุณจะพบขนาดแตกต่างกันเมื่อเทียบกับขนาดที่แสดงที่นี่
eerorika

@RobertSsupportsMonicaCellio ในความคิดของฉันความคิดเห็นเหล่านี้เกี่ยวข้องกับคำตอบและเหมาะสมที่นี่ ฉันจะให้ผู้ควบคุมย้ายพวกเขาหากพวกเขารู้สึกว่าจำเป็นต้องทำเช่นนั้น
eerorika

11

อย่างน้อยก็ไม่น่าเชื่อถือ

ประเภทรวดเร็วเป็นเพียงแค่พิมพ์สำหรับประเภทปกติ แต่มันก็ขึ้นอยู่กับการใช้งานวิธีการกำหนดพวกเขา อย่างน้อยต้องมีขนาดที่ร้องขอ แต่สามารถมีขนาดใหญ่กว่าได้

มันเป็นความจริงที่ในสถาปัตยกรรมบางประเภทจำนวนเต็มบางประเภทมีประสิทธิภาพที่ดีกว่าประเภทอื่น ๆ ตัวอย่างเช่นการใช้งานARMต้นมีคำแนะนำการเข้าถึงหน่วยความจำสำหรับคำ 32- บิตและไบต์ที่ไม่ได้ลงนาม แต่พวกเขาไม่ได้มีคำแนะนำสำหรับครึ่งคำหรือไบต์ที่ลงนาม คำแนะนำแบบครึ่งคำและแบบลายเซ็นต์ไบต์ถูกเพิ่มเข้ามาในภายหลัง แต่ยังคงมีตัวเลือกการกำหนดแอดเดรสที่ยืดหยุ่นน้อยลง ยิ่งไปกว่านั้นคำแนะนำการประมวลผลข้อมูลจริงทั้งหมดของ ARM ทำงานด้วยคำพูดดังนั้นในบางกรณีอาจจำเป็นต้องปิดบังค่าที่น้อยลงหลังจากการคำนวณเพื่อให้ได้ผลลัพธ์ที่ถูกต้อง

อย่างไรก็ตามยังมีข้อกังวลเกี่ยวกับการแข่งขันของแรงกดดันแคชแม้ว่าจะต้องใช้คำแนะนำเพิ่มเติมในการโหลด / จัดเก็บ / ประมวลผลด้วยค่าที่น้อยลง ค่าที่น้อยลงอาจยังคงทำงานได้ดีขึ้นหากลดจำนวนแคชที่หายไป

คำจำกัดความของประเภทบนแพลตฟอร์มทั่วไปจำนวนมากดูเหมือนจะไม่ได้รับความคิด โดยเฉพาะอย่างยิ่งแพลตฟอร์ม 64- บิตที่ทันสมัยมีแนวโน้มที่จะได้รับการสนับสนุนที่ดีสำหรับจำนวนเต็ม 32- บิต แต่ประเภท "เร็ว" มักจะไม่จำเป็น 64 บิตบนแพลตฟอร์มเหล่านี้

นอกจากนี้ชนิดใน C กลายเป็นส่วนหนึ่งของ ABI ของแพลตฟอร์ม ดังนั้นแม้ว่าผู้ขายแพลตฟอร์มจะค้นพบว่าพวกเขาเลือกโง่มันก็ยากที่จะเปลี่ยนตัวเลือกโง่ ๆ เหล่านั้นในภายหลัง

ละเว้นประเภท "เร็ว" หากคุณกังวลเกี่ยวกับประสิทธิภาพของจำนวนเต็มเกณฑ์มาตรฐานรหัสของคุณด้วยขนาดที่มีอยู่ทั้งหมด


7

ประเภทที่รวดเร็วไม่เร็วกว่าประเภทจำนวนเต็มอื่น ๆ - พวกเขาในความเป็นจริงเหมือนกับประเภทจำนวนเต็ม "ปกติ" (พวกเขาเป็นเพียงนามแฝงสำหรับประเภทนั้น) - ประเภทใดที่เกิดขึ้นจะเร็วที่สุดสำหรับการถือค่า อย่างน้อยก็หลายบิต

มันก็ขึ้นอยู่กับแพลตฟอร์มซึ่งจำนวนเต็มพิมพ์แต่ละประเภทได้อย่างรวดเร็วเป็นนามแฝงสำหรับ

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