- บทความนี้กล่าวถึงอิมพลีเมนเทชันการค้นหาแบบไบนารีทั่วไปใน C++ ที่สั้นกว่าและเร็วกว่า
std::lower_bound มาตรฐานถึงสองเท่า
- อิมพลีเมนเทชันใหม่นี้เป็นแบบ "ไร้การแตกแขนง" เพราะถูกคอมไพล์เป็นคำสั่งย้ายข้อมูลแบบมีเงื่อนไขแทนการแตกแขนง/การกระโดดแบบมีเงื่อนไข
- การค้นหาแบบไบนารีทำงานโดยแบ่งรายการที่เรียงลำดับแล้วออกเป็นสองส่วนที่ตำแหน่งกึ่งกลาง และเปรียบเทียบค่ากลางกับค่าที่กำหนด จากผลการเปรียบเทียบจึงตัดสินใจว่าจะค้นหาต่อในรายการย่อยฝั่งใด
- บทความนี้ยังกล่าวถึงแนวคิดเรื่องการทำนายการแตกแขนง ซึ่งเป็นเทคนิคที่โปรเซสเซอร์ใช้รันคำสั่งแบบขนานเพื่อเพิ่มความเร็ว อย่างไรก็ตาม การค้นหาแบบไบนารีคาดเดาได้ยาก จึงไม่เหมาะกับการทำนายการแตกแขนงนัก
- ผู้เขียนแนะนำอิมพลีเมนเทชันการค้นหาแบบไบนารีใหม่ชื่อ
sb_lower_bound ที่เร็วกว่าเวอร์ชันมาตรฐานและเวอร์ชัน branchless_lower_bound เนื่องจากมีจำนวนคำสั่งภายในลูปน้อยกว่ามาก
- ผู้เขียนยังนำเสนอเวอร์ชันที่เร็วกว่าอีกแบบคือ
bb_lower_bound ซึ่งใช้วิธีแบ่งรายการค้นหาที่แตกต่างออกไป
- บทความนี้ปิดท้ายด้วยข้อเสนอแนะว่า หากส่วนที่ช้าที่สุดของโปรแกรมมีการค้นหาและ/หรือการเปรียบเทียบที่โปรเซสเซอร์คาดเดาไม่ได้ ให้ลองใช้ clang พร้อมออปชัน
-mllvm -x86-cmov-converter=false และหากต้องการการค้นหาแบบไบนารีที่เร็วขึ้น ให้ลอง sb_lower_bound
- ผู้เขียนยังให้โค้ดของอิมพลีเมนเทชันการค้นหาแบบไบนารีใหม่ และอภิปรายประสิทธิภาพของแต่ละแบบอย่างละเอียด
- บทความนี้ได้รับการอัปเดตด้วยเวอร์ชันรีแฟกเตอร์ของ
sb_lower_bound ที่ลดจำนวนคำสั่งแอสเซมบลีใน hot loop จาก 9 เหลือ 8 ส่งผลให้เร็วขึ้นเล็กน้อย
- ผู้เขียนยังกล่าวถึงแนวคิดเรื่องการพรีเฟตช์ ซึ่งเป็นการดึงหน่วยความจำบางส่วนเข้าสู่แคชล่วงหน้า เพื่อให้เมื่อจำเป็นต้องใช้ข้อมูลที่พรีเฟตช์ไว้จริง จะเกิดเพียงดีเลย์ของแคช L1/L2 เท่านั้น นอกจากนี้ยังมีเวอร์ชัน
sb_lower_bound ที่เพิ่มการพรีเฟตช์สำหรับขนาด 256KB+
- บทความนี้เขียนโดย Mihail Dumitrescu และเผยแพร่เมื่อวันที่ 24 มิถุนายน 2023
1 ความคิดเห็น
ความเห็นบน Hacker News
lowerBoundsb_lower_boundกับชนิดข้อมูลพื้นฐาน และใช้std::lower_boundในกรณีอื่น