“ IF” แพงไหม


103

ตลอดชีวิตของฉันจำสิ่งที่ครูของเราพูดในวันนั้นไม่ได้และฉันหวังว่าคุณคงจะรู้

โมดูลนี้คือ "โครงสร้างข้อมูลและอัลกอริทึม" และเขาบอกเราบางอย่างตามบรรทัดของ:

ifคำสั่งมีราคาแพงที่สุด [บางสิ่งบางอย่าง] [บางอย่าง] ลงทะเบียน [บางอย่าง]

ใช่ฉันมีความทรงจำที่น่ากลัวและฉันขอโทษจริงๆ แต่ฉันใช้ googling มาหลายชั่วโมงแล้วและไม่มีอะไรเกิดขึ้น ความคิดใด ๆ ?


30
ขอให้ครูเป็นตัวเลือกหรือไม่?
Michael Myers

7
ทำไมคุณไม่ส่งอีเมลถึงครูของคุณ ไม่น่ามีใครรู้ว่าครูของคุณพูดอะไรเว้นแต่พวกเขาจะอยู่ที่นั่นในเวลานั้น (หรือครูของคุณอ่าน SO)
Bill Karwin

11
และแน่นอนลิงค์ไปยังคำตอบทางรถไฟ
bobobobo

หากคำสั่งหรือโดยเฉพาะอย่างยิ่ง "?:" นิพจน์ในภาษาวงเล็บปีกกาที่ได้รับอิทธิพล C สามารถใช้งานได้โดยคำสั่งการดำเนินการตามเงื่อนไขพิเศษเช่น x86 และโปรเซสเซอร์แขน นี่คือคำแนะนำที่ทำหรือไม่ดำเนินการบางอย่างตามการทดสอบก่อนหน้านี้ การใช้คำแนะนำที่ยอดเยี่ยมเหล่านี้จะช่วยหลีกเลี่ยงความจำเป็นในการกระโดดตามเงื่อนไข / กิ่ง / คำสั่ง 'goto' โดยสิ้นเชิง การปรับปรุงประสิทธิภาพครั้งใหญ่ในบางสถานการณ์โดยการทำให้โปรแกรมไหลอย่างคาดเดาได้อย่างสมบูรณ์เพราะมันแค่ไถไปตรงๆโดยไม่มี (อาจคาดเดาไม่ได้) กระโดดไปรอบ ๆ จุดต่างๆในโค้ด
Cecil Ward

บางครั้งคอมไพเลอร์ที่ดีอาจต้องการแรงผลักไปในทิศทางที่ถูกต้องเล็กน้อยเพื่อให้ใช้คำสั่งแบบมีเงื่อนไขแทนที่จะเป็นใบ้และใช้การกระโดดตามเงื่อนไขโดยการจัดระเบียบรหัสใหม่และอาจใช้เลขคณิตที่ชาญฉลาดในนิพจน์หรือ a? : การแสดงออก อย่าเล่นกับสิ่งนี้เว้นแต่คุณจะรู้จัก asm ของคุณจริงๆและได้อ่านเช่นคู่มือการเพิ่มประสิทธิภาพของ Agner Fog บางครั้งคอมไพเลอร์ทำให้ถูกต้องไม่ว่าจะเป็นคำสั่งหรือ? : ใช้นิพจน์
Cecil Ward

คำตอบ:


190

ในระดับต่ำสุด (ในฮาร์ดแวร์) ใช่ถ้า s มีราคาแพง เพื่อให้เข้าใจว่าทำไมคุณต้องเข้าใจว่าท่อทำงานอย่างไร

คำสั่งปัจจุบันที่จะดำเนินการจะถูกเก็บไว้ในสิ่งที่มักเรียกว่าตัวชี้คำสั่ง (IP) หรือตัวนับโปรแกรม (PC) คำเหล่านี้มีความหมายเหมือนกัน แต่ใช้คำต่างกันกับสถาปัตยกรรมที่แตกต่างกัน สำหรับคำแนะนำส่วนใหญ่พีซีของคำสั่งถัดไปเป็นเพียงพีซีปัจจุบันบวกกับความยาวของคำสั่งปัจจุบัน สำหรับสถาปัตยกรรม RISC ส่วนใหญ่คำแนะนำทั้งหมดจะมีความยาวคงที่ดังนั้นพีซีจึงสามารถเพิ่มขึ้นได้ด้วยจำนวนคงที่ สำหรับสถาปัตยกรรม CISC เช่น x86 คำสั่งอาจมีความยาวผันแปรได้ดังนั้นตรรกะที่ถอดรหัสคำสั่งจะต้องกำหนดระยะเวลาที่คำสั่งปัจจุบันจะค้นหาตำแหน่งของคำสั่งถัดไป

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

เงื่อนไขกับไม่มีเงื่อนไขเป็นเรื่องง่ายที่จะเข้าใจ - สาขาเงื่อนไขจะถูกนำมาใช้ก็ต่อเมื่อเงื่อนไขบางอย่างมีอยู่ (เช่นจำนวนหนึ่งเท่ากับอีกตัวหนึ่งหรือไม่) ถ้าสาขาไม่ได้รับการควบคุมจะดำเนินการตามคำสั่งถัดไปหลังจากสาขาเหมือนปกติ สำหรับสาขาที่ไม่มีเงื่อนไขจะใช้กิ่งก้านเสมอ สาขาที่มีเงื่อนไขแสดงในifงบและการทดสอบการควบคุมของforและwhileลูป สาขาที่ไม่มีเงื่อนไขจะแสดงในลูปที่ไม่มีที่สิ้นสุดการเรียกใช้ฟังก์ชันการส่งคืนฟังก์ชันbreakและcontinueคำสั่งคำสั่งที่น่าอับอายgotoและอื่น ๆ อีกมากมาย (รายการเหล่านี้ยังห่างไกลจากข้อมูลที่ครบถ้วนสมบูรณ์)

เป้าหมายของสาขาเป็นอีกเรื่องที่สำคัญ สาขาส่วนใหญ่มีเป้าหมายสาขาคงที่ - ไปยังตำแหน่งเฉพาะในรหัสที่กำหนดไว้ในเวลาคอมไพล์ ซึ่งรวมถึงifคำสั่งการวนซ้ำทุกประเภทการเรียกใช้ฟังก์ชันปกติและอื่น ๆ อีกมากมาย คำนวณสาขาคำนวณกำหนดเป้าหมายของสาขาที่รันไทม์ ซึ่งรวมถึงswitchคำสั่ง (บางครั้ง) การส่งคืนจากฟังก์ชันการเรียกฟังก์ชันเสมือนและการเรียกใช้ตัวชี้ฟังก์ชัน

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

ดังนั้นเหตุผลที่ว่าทำไมถ้างบมีราคาแพงเป็นเพราะสาขา mispredictions นี่เป็นเพียงระดับต่ำสุด หากคุณกำลังเขียนโค้ดระดับสูงคุณไม่จำเป็นต้องกังวลเกี่ยวกับรายละเอียดเหล่านี้เลย คุณควรสนใจเรื่องนี้ก็ต่อเมื่อคุณกำลังเขียนโค้ดที่มีความสำคัญอย่างยิ่งต่อประสิทธิภาพใน C หรือแอสเซมบลี ในกรณีนี้การเขียนโค้ดแบบไม่แยกสาขามักจะดีกว่าโค้ดที่แตกกิ่งก้านแม้ว่าจะต้องมีคำสั่งเพิ่มเติมอีกหลายคำก็ตาม มีบางเทคนิคเด็ดบิต twiddling คุณสามารถทำได้เพื่อคำนวณสิ่งต่างๆเช่นมีabs(), min()และmax()โดยไม่ต้องแยกทาง


20
ไม่ใช่แค่การคาดเดาผิดสาขาเท่านั้น แบรนช์ยังยับยั้งการเรียงลำดับคำสั่งใหม่ในระดับคอมไพเลอร์และระดับ CPU ในระดับหนึ่งด้วย (แน่นอนสำหรับ CPU ที่ไม่ได้รับคำสั่ง) คำตอบที่ละเอียดดีแม้ว่า
jalf

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

19

"แพง" เป็นคำที่สัมพันธ์กันโดยเฉพาะอย่างยิ่งกับความสัมพันธ์กับ "ifคำสั่ง "" เนื่องจากคุณต้องคำนึงถึงต้นทุนของเงื่อนไขด้วย ซึ่งอาจมีตั้งแต่คำสั่ง cpu สั้น ๆ ไม่กี่คำไปจนถึงการทดสอบผลลัพธ์ของฟังก์ชันที่เรียกไปยังฐานข้อมูลระยะไกล

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


2
ญาติแน่นอน ... cmp / cond jmp ยังเร็วกว่ามัลในโปรเซสเซอร์หลายตัว
Brian Knoblauch

4
ใช่ฉันยอมรับว่าฉันไม่ควรกังวลเกี่ยวกับเรื่องนี้ ฉันไม่ได้พยายามเพิ่มประสิทธิภาพอะไรที่นี่ ฉันแค่พยายามค้นหาและเรียนรู้ ;)
pek

15

สาขาโดยเฉพาะอย่างยิ่งในไมโครโปรเซสเซอร์สถาปัตยกรรม RISC เป็นคำแนะนำที่แพงที่สุด เนื่องจากในหลาย ๆ สถาปัตยกรรมคอมไพลเลอร์คาดการณ์ว่าเส้นทางของการดำเนินการใดจะถูกนำไปใช้มากที่สุดและวางคำสั่งเหล่านั้นไว้ในไฟล์ปฏิบัติการดังนั้นคำสั่งเหล่านั้นจะอยู่ในแคชของ CPU แล้วเมื่อสาขาเกิดขึ้น ถ้าสาขาไปอีกทางก็ต้องกลับไปที่หน่วยความจำหลักแล้วดึงคำแนะนำใหม่ซึ่งค่อนข้างแพง ในสถาปัตยกรรม RISC จำนวนมากคำแนะนำทั้งหมดเป็นหนึ่งรอบยกเว้นสาขา (ซึ่งมักจะเป็น 2 รอบ) เราไม่ได้พูดถึงต้นทุนหลักที่นี่ดังนั้นอย่ากังวลไป นอกจากนี้คอมไพเลอร์จะปรับให้เหมาะสมดีกว่าที่คุณทำ 99% ของเวลา: ) หนึ่งในสิ่งที่ยอดเยี่ยมจริงๆเกี่ยวกับสถาปัตยกรรม EPIC (ตัวอย่าง Itanium) คือแคช (และเริ่มประมวลผล) คำสั่งจากทั้งสองด้านของสาขาจากนั้นทิ้งชุดที่ไม่ต้องการเมื่อผลลัพธ์ของสาขาเป็น เป็นที่รู้จัก ซึ่งจะช่วยประหยัดการเข้าถึงหน่วยความจำเพิ่มเติมของสถาปัตยกรรมทั่วไปในกรณีที่แยกไปตามเส้นทางที่ไม่ได้คาดการณ์


13

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

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

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


แน่นอน! นอกจากนี้เรายังอาจเพิ่มว่าเมื่อเขียนโค้ดในภาษาที่กระตุ้นการโทร (โดยทั่วไปสิ่งอื่นนอกเหนือจากแอสเซมเบลอร์หรือ C ที่ไม่มี stdlib) การรบกวนไปป์ไลน์จากเทคนิคการเขียนโปรแกรมปกติจะทำให้เกิดคำถามเกี่ยวกับการแตกแขนงตามเงื่อนไข
Ross Patterson

10

ifในตัวเองไม่ช้า ความช้าเป็นสิ่งที่เกี่ยวข้องเสมอฉันเดิมพันด้วยชีวิตของฉันโดยที่คุณไม่เคยรู้สึกถึง "ค่าใช้จ่าย" ของ if-statement หากคุณกำลังจะสร้างโค้ดที่มีประสิทธิภาพสูงคุณก็ต้องการหลีกเลี่ยงสาขาอยู่ดี สิ่งที่ทำให้ifช้าคือโปรเซสเซอร์กำลังโหลดโค้ดล่วงหน้าจากหลังการifอ้างอิงตามฮิวริสติกบางอย่างและอะไรไม่ได้ นอกจากนี้ยังจะหยุดไปป์ไลน์จากการรันโค้ดโดยตรงหลังจากifคำสั่ง branch ในโค้ดเครื่องเนื่องจากโปรเซสเซอร์ยังไม่รู้ว่าจะใช้พา ธ อะไร (ในโปรเซสเซอร์แบบไพพ์ไลน์จะมีการแทรกและดำเนินการหลายคำสั่ง) รหัสที่เรียกใช้อาจต้องดำเนินการในทางกลับกัน (หากใช้สาขาอื่นจะเรียกว่าbranch misprediction) หรือnoopกรอกข้อมูลที่ตำแหน่งเหล่านั้นเพื่อไม่ให้สิ่งนี้เกิดขึ้น

ถ้าifเป็นความชั่วร้ายนั้นswitchเป็นความชั่วร้ายเกินไปและ&&, ||เกินไป อย่าเพิ่งกังวลไป


7

ในระดับต่ำสุดที่เป็นไปได้ifประกอบด้วย (หลังจากคำนวณข้อกำหนดเบื้องต้นเฉพาะแอปทั้งหมดสำหรับเฉพาะif):

  • คำแนะนำในการทดสอบบางอย่าง
  • ข้ามไปยังตำแหน่งใดตำแหน่งหนึ่งในรหัสหากการทดสอบสำเร็จให้ดำเนินการต่อไปมิฉะนั้น

ค่าใช้จ่ายที่เกี่ยวข้อง:

  • การเปรียบเทียบระดับต่ำ - โดยปกติจะใช้ CPU 1 ตัวราคาถูกสุด ๆ
  • การกระโดดที่อาจเกิดขึ้นซึ่งอาจมีราคาแพง

เสียงสะท้อนว่าทำไมการกระโดดถึงมีราคาแพง:

  • คุณสามารถข้ามไปที่รหัส arbirary ที่อยู่ที่ใดก็ได้ในหน่วยความจำหากปรากฎว่า cpu ไม่ได้แคชไว้ - เรามีปัญหาเพราะเราจำเป็นต้องเข้าถึงหน่วยความจำหลักซึ่งช้ากว่า
  • ซีพียูสมัยใหม่ทำหน้าที่กำหนดสาขา พวกเขาพยายามเดาว่าจะสำเร็จหรือไม่และรันโค้ดล่วงหน้าในไปป์ไลน์เพื่อเร่งความเร็ว หากการคาดการณ์ล้มเหลวในการคำนวณทั้งหมดที่ดำเนินการล่วงหน้าโดยไปป์ไลน์จะต้องถูกยกเลิก นั่นเป็นการดำเนินการที่มีราคาแพง

เพื่อสรุป:

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

นำไปสู่ระดับถัดไป: สิ่งที่เกี่ยวกับคำสั่งซ้อนและ / หรือสารประกอบ if? ค่าใช้จ่ายสามารถเห็นได้ชัดเจนอย่างรวดเร็วหากมีคนเขียนงบ if จำนวนมากเช่นนี้ และเนื่องจากสำหรับนักพัฒนาส่วนใหญ่หากข้อความดูเหมือนเป็นการดำเนินการขั้นพื้นฐานเช่นนั้นการหลีกเลี่ยงการแตกกิ่งก้านตามเงื่อนไขที่ซับซ้อนมักจะถูกลดทอนความกังวลเกี่ยวกับโวหาร ความกังวลเกี่ยวกับโวหารยังคงมีความสำคัญ แต่บ่อยครั้งในช่วงเวลาที่ร้อนแรงพวกเขาอาจเป็นความกังวลแรกที่ถูกละเลย
jaydel

7

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

ฉันคิดว่ามันเป็นรถไฟบรรทุกสินค้ายาว สามารถบรรทุกสินค้าจำนวนมากได้อย่างรวดเร็วเป็นเส้นตรง แต่มุมไม่ดี

Pentium 4 (Prescott) มีท่อส่งยาว 31 ขั้นตอนที่มีชื่อเสียง

เพิ่มเติมเกี่ยวกับWikipedia


6

บางทีการแยกสาขาอาจฆ่าการดึงคำสั่ง CPU ล่วงหน้า?


จาก ... "การวิจัย" ของฉันฉันได้เรียนรู้เกี่ยวกับตารางการกระโดดและการแตกแขนงสำหรับคำสั่ง switch แต่ไม่มีอะไรเกี่ยวกับคำสั่ง if คุณช่วยอธิบายเพิ่มเติมเล็กน้อยได้ไหม
pek

IIRC ซีพียูมักจะดึงคำสั่งไว้ล่วงหน้าตามเส้นทางการดำเนินการที่น่าจะเป็นไปได้เพียงครั้งเดียว แต่คำสั่ง 'if' ที่ทำให้กิ่งก้านจากเส้นทางการดำเนินการที่คาดการณ์ไว้มันจะทำให้คำสั่งที่กำหนดไว้ล่วงหน้าเป็นโมฆะและการ preteching จะต้องเริ่มต้นใหม่
activout.se

โปรเซสเซอร์ที่เหมาะสมใด ๆ ควรมีความสามารถในการทำนายสาขาซึ่งจะพยายามเดาว่าสาขาจะถูกยึดหรือไม่และดึงคำสั่งล่วงหน้าตามการคาดการณ์ (ซึ่งโดยทั่วไปค่อนข้างดี) GCC ยังมีนามสกุล C ที่ช่วยให้โปรแกรมเมอร์สามารถให้คำแนะนำสำหรับตัวทำนายสาขาได้
mipadi

2
ยิ่งไปกว่านั้นซีพียูมักจะตั้งหน้าตั้งตาดำเนินการตามคำสั่งที่กำลังจะมีขึ้นก่อน (ไม่ใช่แค่ดึงข้อมูลล่วงหน้า) และคอมไพเลอร์จะพยายามเรียงลำดับคำสั่งใหม่และนั่นจะกลายเป็นอันตรายข้ามสาขาดังนั้นคุณจึงสามารถฆ่าการตั้งเวลาคำสั่งที่มีสาขามากเกินไปได้ ซึ่งทำร้ายประสิทธิภาพ
jalf

6

โปรดทราบว่าภายในวงไม่ได้จำเป็นต้องมีราคาแพงมาก

ซีพียูสมัยใหม่จะถือว่าเมื่อเข้ามาครั้งแรกของ if-statement ว่าจะต้องใช้ "if-body" (หรือกล่าวอีกนัยหนึ่ง: มันยังถือว่า loop-body ที่จะต้องดำเนินการหลายครั้ง) (*) ในการเยี่ยมชมครั้งที่สองและครั้งต่อไป (CPU) อาจตรวจสอบตารางประวัติสาขาและดูว่าเงื่อนไขเป็นอย่างไรในครั้งที่แล้ว (จริงหรือไม่เป็นเท็จ?) หากครั้งที่แล้วเป็นเท็จการดำเนินการเก็งกำไรจะดำเนินการต่อไปยัง "else" ของ if หรือเกินจากลูป

(*) จริงๆแล้วกฎคือ " ไม่ได้ใช้สาขาไปข้างหน้า, ใช้สาขาย้อนหลัง " ใน if-statement จะมีการกระโดด [ไปข้างหน้า] เท่านั้น (ไปยังจุดหลัง if-body ) หากเงื่อนไขประเมินว่าเป็นเท็จ (โปรดจำไว้ว่า: CPU ยังถือว่าไม่ใช้ branch / jump) แต่ในลูป อาจมีสาขาไปข้างหน้าไปยังตำแหน่งหลังลูป (ไม่ต้องดำเนินการ) และสาขาย้อนกลับเมื่อทำซ้ำ (ที่จะถ่าย)

นี่เป็นสาเหตุหนึ่งที่ทำให้การเรียกใช้ฟังก์ชันเสมือนหรือฟังก์ชันพอยน์เตอร์โทรไม่แย่ลงอย่างที่หลายคนคิด ( http://phresnel.org/blog/ )


5

ตามที่หลาย ๆ คนชี้ให้เห็นแล้วกิ่งไม้ที่มีเงื่อนไขอาจทำงานช้ามากในคอมพิวเตอร์สมัยใหม่

ดังที่กล่าวมามีสาขาเงื่อนไขจำนวนมากที่ไม่ได้อยู่ในคำสั่ง if คุณไม่สามารถบอกได้เสมอว่าคอมไพเลอร์จะเกิดอะไรขึ้นและการกังวลว่าข้อความพื้นฐานจะใช้เวลานานแค่ไหนนั้นเป็นสิ่งที่ผิดเสมอ ทำ. (หากคุณสามารถบอกได้ว่าคอมไพลเลอร์จะสร้างอะไรได้อย่างน่าเชื่อถือคุณอาจไม่มีคอมไพเลอร์ที่ปรับให้เหมาะสมได้ดี)


4

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

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

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


ฉันได้ยินมาว่าคำแนะนำแบบมีเงื่อนไขของ ARM ยับยั้ง ILP ดังนั้นพวกเขาอาจผลักปัญหาไปรอบ ๆ
JD

3

ซีพียูเป็นท่อลึก คำสั่งสาขาใด ๆ (if / for / while / switch / etc) หมายความว่า CPU ไม่รู้จริงๆว่าจะโหลดและรันคำสั่งใดต่อไป

ซีพียูอาจหยุดทำงานในขณะที่รอเพื่อที่จะรู้ว่าต้องทำอะไรหรือ CPU จะเดา ในกรณีของซีพียูรุ่นเก่าหรือหากเดาไม่ถูกต้องคุณจะต้องประสบปัญหาท่อตันในขณะที่ทำงานและโหลดคำสั่งที่ถูกต้อง ขึ้นอยู่กับซีพียูซึ่งอาจสูงถึง 10-20 คำแนะนำที่คุ้มค่ากับการหยุดชะงัก

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

ขอให้โชคดีในชั้นเรียน

นอกจากนี้หากคุณต้องกังวลเกี่ยวกับเรื่องนี้ในชีวิตจริงคุณอาจกำลังออกแบบระบบปฏิบัติการกราฟิกเรียลไทม์คอมพิวเตอร์ทางวิทยาศาสตร์หรือสิ่งที่เกี่ยวข้องกับ CPU โปรไฟล์ก่อนกังวล.


2

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


1

CPU บางตัว (เช่น X86) ให้การทำนายสาขาไปยังระดับการเขียนโปรแกรมเพื่อหลีกเลี่ยงเวลาแฝงของการทำนายสาขา

คอมไพเลอร์บางตัวเปิดเผย (เช่น GCC) สิ่งเหล่านี้เป็นส่วนขยายของภาษาโปรแกรมระดับสูงกว่า (เช่น C / C ++)

อ้างถึงมาโครที่เป็นไปได้ () / ไม่น่าเป็นไปได้ () ในเคอร์เนล Linux - มันทำงานอย่างไร? ประโยชน์ของพวกเขาคืออะไร? .


0

ฉันเคยทะเลาะกับเพื่อนคนหนึ่งของฉันครั้งหนึ่ง เขาใช้อัลกอริทึมวงกลมที่ไร้เดียงสามาก แต่อ้างว่าเขาเร็วกว่าของฉัน (แบบที่คำนวณเฉพาะ 1/8 ของวงกลม) เพราะฉันใช้ if ในท้ายที่สุดคำสั่ง if ถูกแทนที่ด้วย sqrt และเร็วกว่านั้น อาจเป็นเพราะ FPU มี sqrt ในตัว?


-1

แพงที่สุดในแง่ของการใช้งาน ALU? ใช้การลงทะเบียน CPU เพื่อเก็บค่าที่จะเปรียบเทียบและใช้เวลาในการดึงและเปรียบเทียบค่าทุกครั้งที่รันคำสั่ง if

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

เพียงแค่พยายามตีความคำที่ขาดหายไปของคุณ

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