การใช้มาโคร "น่าจะเป็น" และ "ไม่น่า" เท่าไหร่มีมากเกินไป?


12

มาโครที่รู้จักกันในชื่อlikelyและunlikelyมาโครช่วยให้คอมไพเลอร์ทราบว่าifจะป้อนหรือข้าม การใช้มันจะส่งผลในการปรับปรุงประสิทธิภาพ (ค่อนข้างเล็กน้อย)

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

mem = malloc(size);
if (unlikely(mem == NULL))
  goto exit_no_mem;

ดูเหมือนว่าจะใช้ได้ แต่การตรวจสอบข้อผิดพลาดifเกิดขึ้นบ่อยครั้งดังนั้นจึงใช้มาโครดังกล่าว

คำถามของฉันคือมันมีมากเกินไปlikelyและunlikelyแมโครในทุกการตรวจสอบข้อผิดพลาดif?

ในขณะที่เราอยู่ที่นี่พวกเขามักจะใช้ที่อื่นที่ไหน?


ในการใช้งานปัจจุบันของฉันมันอยู่ในไลบรารีที่ทำให้เกิดนามธรรมจากระบบย่อยเรียลไทม์ดังนั้นโปรแกรมจะกลายเป็นแบบพกพาระหว่าง RTAI, QNX และอื่น ๆ ที่กล่าวว่าฟังก์ชั่นส่วนใหญ่ค่อนข้างเล็กและเรียกฟังก์ชั่นอื่น ๆ หนึ่งหรือสองโดยตรง หลายคนมีstatic inlineฟังก์ชั่น

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

ประการที่สองมันคล้ายกับ "ฉันรู้ว่ามันไม่น่าเป็นไปได้ฉันก็จะบอกให้คอมไพเลอร์" ifฉันไม่แข็งขันพยายามที่จะเพิ่มประสิทธิภาพ


7
รีทวีตของไมโครปรับให้เหมาะกับฉัน ...
ratchet freak

2
สำหรับรหัสแอปพลิเคชันฉันจะเพิ่มพวกเขาก็ต่อเมื่อการทำโปรไฟล์แสดงให้เห็นว่ารหัสนี้ใช้ในเส้นทางที่ร้อนแรง
CodesInChaos


@ เจมส์ที่เพิ่งพูดlikelyและunlikelyมีอยู่และสิ่งที่พวกเขาทำ ฉันไม่พบสิ่งใดที่จะแนะนำให้ใช้เมื่อไรและที่ไหนดีที่สุด
Shahbaz

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

คำตอบ:


12

คุณต้องการประสิทธิภาพที่ไม่ดีที่คุณยินดีที่จะทำให้รหัสของคุณสกปรกหรือไม่? เป็นการเพิ่มประสิทธิภาพเล็กน้อย

  • รหัสทำงานเป็นวงวนหรือไม่?
  • แอปพลิเคชันของคุณมีปัญหาด้านประสิทธิภาพหรือไม่
  • คุณทำโปรไฟล์แอปพลิเคชันของคุณและพิจารณาว่าลูปนี้โดยเฉพาะใช้เวลา CPU นานหรือไม่

ถ้าคุณไม่สามารถตอบคำถามyesทั้งหมดข้างต้นได้อย่ากังวลกับเรื่องแบบนี้

แก้ไข: เพื่อตอบสนองต่อการแก้ไข แม้ว่าคุณจะไม่สามารถทำโปรไฟล์ได้ แต่โดยปกติคุณสามารถประมาณฮอตสปอตได้ ฟังก์ชั่นการจัดสรรหน่วยความจำที่ทุกคนเรียกว่าเป็นตัวเลือกที่ดีโดยเฉพาะอย่างยิ่งเนื่องจากมันต้องการเพียงการใช้มาโครเพียงครั้งเดียวในการทำงานกับไลบรารีทั้งหมด


1
เพื่อความชัดเจนฉันไม่ได้ลงคะแนนให้คุณ อย่างไรก็ตามคำตอบของคุณไม่ได้ตอบคำถามของฉัน คุณพยายามที่จะบอกว่า(un)likelyแมโครนั้นไม่ค่อยได้ใช้และมีเพียงโค้ดที่มีประสิทธิภาพสูงมากเท่านั้น? มันเป็น "การปฏิบัติที่ไม่ดี" ที่จะใช้บ่อยหรือเพียงแค่ "ไม่จำเป็น" หรือไม่?
Shahbaz

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

3
@Peter: ในขณะที่มันเลวร้ายเกินไปไวยากรณ์ไม่ใช่ nicer ข้อความที่เป็นไปได้หรือไม่น่าจะให้ข้อมูลที่เป็นประโยชน์กับมนุษย์ที่กำลังอ่านรหัส ตัวอย่างเช่นบางคนที่เห็นif (likely(x==2 || x==3)) doOneThing(); else switch(x) { ... }อาจตัดสินว่าการใช้โปรแกรมเมอร์ifสำหรับค่า 2 และ 3 นั้นไม่เพียง แต่เป็นผลมาจากโปรแกรมเมอร์ไม่ทราบว่า C สามารถเชื่อมโยงสองcaseป้ายผนึกกับตัวจัดการเดียว
supercat

ไม่มีใครพูดถึงสิ่งที่ฉันรู้สึกว่าเป็นจุดวิกฤติ ไม่ใช่เพียงแค่เส้นทางที่ "ไม่น่าจะเกิดขึ้น" น้อยกว่ามันอาจเป็นไปได้ว่าสภาพของเส้นทางนั้นเกิดขึ้นคุณไม่สนใจความเร็วเลย ตัวอย่างเช่นอุปกรณ์ต่อพ่วงไม่ตอบสนองดังนั้นคุณต้องรีเซ็ตและเข้าสู่โหมดสลีป
Benjamin Lindqvist

2

หากคุณเขียนสำหรับ x86 / x64 (และไม่ได้ใช้ซีพียูอายุ 20 ปี) ประสิทธิภาพที่เพิ่มขึ้นจากการใช้ __builtin_expect () จะเล็กน้อยถ้ามี เหตุผลก็คือว่าซีพียูรุ่นปัจจุบัน x86 / x64 (ไม่แน่ใจ 100% เกี่ยวกับ Atom แม้ว่า) จะมีการคาดคะเนสาขาแบบไดนามิกดังนั้นโดยหลักแล้วซีพียู "เรียนรู้" เกี่ยวกับสาขาที่ใช้บ่อยกว่า แน่นอนว่าข้อมูลนี้สามารถจัดเก็บได้สำหรับสาขาที่ จำกัด เท่านั้นอย่างไรก็ตามมีเพียงสองกรณีเท่านั้นที่เป็นไปได้ หาก (a) เป็นสาขา "ที่ใช้บ่อย" โปรแกรมของคุณจะได้รับประโยชน์จากการทำนายสาขาแบบไดนามิกนั้นและหาก (b) เป็นสาขา "หายาก" คุณจะไม่เห็นประสิทธิภาพที่เหมือนจริงใด ๆ เนื่องจากการคาดการณ์ผิด กิ่งก้านที่หายากเช่นนี้ (รอบ 20 ซีพียูของการคาดเดาผิดสาขาจะไม่เลวเกินไปถ้ามันเกิดขึ้นครั้งเดียวในดวงจันทร์สีน้ำเงิน)

หมายเหตุ: นี่ไม่ได้หมายความว่าในปัจจุบัน x86 / x64 ความสำคัญของการคาดคะเนของสาขาลดลง: สาขาใดก็ตามที่มีโอกาส 50-50 ของการกระโดดข้าม nojump จะยังคงได้รับโทษ (IIRC 10-20 รอบ CPU) ดังนั้นในสาขาวงในอาจ ยังคงต้องหลีกเลี่ยง เป็นสิ่งสำคัญเพียง __builtin_expect () บน x86 / x64 ซึ่งลดลง (IIRC ประมาณ 10-15 ปีก่อนหรือมากกว่านั้น) ส่วนใหญ่เป็นเพราะการทำนายสาขาแบบไดนามิก

NB2: สำหรับแพลตฟอร์มอื่น ๆ ที่เกิน x86 / x64, YMMV


คอมไพเลอร์รู้ดีว่าซีพียูแบบใดที่คาดว่าจะมีโอกาสน้อยลง และมันสามารถจัดการให้มันเป็นสิ่งที่ไม่น่าเป็นไปได้ แต่คอมไพเลอร์อาจรู้รูปแบบนั้นอยู่แล้วโดยไม่มีunlikely-notation
Deduplicator

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