เธรดเดี่ยวทำงานบนหลายคอร์ได้อย่างไร


61

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

จากการอ่านHyper-threadingของฉันดูเหมือนว่าระบบปฏิบัติการจะจัดการคำแนะนำของเธรดทั้งหมดในลักษณะที่พวกเขาไม่ได้รอซึ่งกันและกัน จากนั้น Front-end ของ CPU จะจัดระเบียบคำแนะนำเหล่านั้นเพิ่มเติมโดยกระจายเธรดหนึ่งเธรดไปยังแต่ละคอร์และกระจายคำสั่งที่เป็นอิสระจากแต่ละเธรดในทุกรอบที่เปิด

ดังนั้นหากมีเพียงเธรดเดียวดังนั้นระบบปฏิบัติการจะไม่ทำการเพิ่มประสิทธิภาพใด ๆ อย่างไรก็ตามส่วนหน้าของ CPU จะแจกจ่ายชุดคำสั่งที่เป็นอิสระในแต่ละคอร์

ตามhttps://stackoverflow.com/a/15936270ภาษาการเขียนโปรแกรมเฉพาะอาจสร้างเธรดมากขึ้นหรือน้อยลง แต่ไม่เกี่ยวข้องเมื่อพิจารณาว่าจะทำอย่างไรกับเธรดเหล่านั้น ระบบปฏิบัติการและ CPU จัดการสิ่งนี้ดังนั้นจึงเกิดขึ้นโดยไม่คำนึงถึงภาษาการเขียนโปรแกรมที่ใช้

ป้อนคำอธิบายรูปภาพที่นี่

เพียงเพื่อชี้แจงฉันถามเกี่ยวกับเธรดเดียวที่รันในหลายคอร์ไม่ใช่เกี่ยวกับการรันหลายเธรดบนแกนเดียว

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


6
ชุดคำสั่งสำหรับเธรดซอฟต์แวร์เดียวอาจทำงานในหลายคอร์ แต่ไม่พร้อมกัน
Kroltan

1
คุณกำลังผสมเธรดซอฟต์แวร์ (ซึ่งเกี่ยวข้องกับตัวกำหนดตารางเวลาระบบปฏิบัติการ) และเธรดฮาร์ดแวร์หรือ HyperThreading (คุณลักษณะ CPU ที่ทำให้หนึ่งคอร์ทำงานเหมือนกับสอง)
ugoren

2
ฉันมีคนขับ 20 คนและรถบรรทุก 4 คัน เป็นไปได้อย่างไรที่คนขับรถคนหนึ่งสามารถส่งมอบพัสดุด้วยรถบรรทุกสองคัน เป็นไปได้อย่างไรที่รถบรรทุกคันเดียวสามารถมีคนขับได้หลายคน? คำตอบของคำถามทั้งสองนั้นเหมือนกัน ผลัดกัน.
Eric Lippert

คำตอบ:


84

ระบบปฏิบัติการเสนอการแบ่งเวลาของ CPU ให้กับเธรดที่มีสิทธิ์เรียกใช้

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

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

หากมีหลายคอร์ N ระบบปฏิบัติการจะกำหนดตารางเวลาเธรด N ที่มีสิทธิ์มากที่สุดให้รันบนคอร์

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

อย่างไรก็ตามระบบปฏิบัติการมีอิสระที่จะเสนอการแบ่งเวลาหนึ่งเธรดบน CPU ที่แตกต่างกันและมันสามารถหมุนผ่าน CPU ทั้งหมดในการแบ่งส่วนเวลาที่แตกต่างกัน อย่างไรก็ตามไม่สามารถพูดได้อย่างที่@ gnasher729เรียกใช้หนึ่งเธรดบน CPU หลายตัวพร้อมกัน

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

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


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


3
"ดังนั้นการรันเธรดเดียวกันบนตัวประมวลผลเดียวกันในการแบ่งเวลาเป็นจำนวนมากจึงเป็นข้อได้เปรียบด้านประสิทธิภาพ" มันจะไม่ได้เป็นชิ้นเวลาที่ต่อเนื่องกัน ? มิฉะนั้นแคชจะถูกลบโดยเธรดอื่น ๆ ไม่ใช่หรือ? +1 สำหรับคำอธิบายที่ดี
jpmc26

2
@ Luaan: HT มักจะดี แต่สถานการณ์ไม่ง่ายอย่างที่คุณอธิบาย แบนด์วิดท์ปัญหา front-end (4 uops ต่อนาฬิกาบน Intel, 6 บน Ryzen) มีการแชร์กันอย่างเท่าเทียมกันระหว่างเธรด (ยกเว้นว่าจะหยุดทำงาน) ถ้านั่นคือคอขวดนั่นก็เหมือนที่ฉันบอกว่า HT จะไม่ช่วยอะไรเลย ไม่ใช่เรื่องแปลกที่ Skylake จะเข้ามาใกล้กับวงนั้นถ้ามีการโหลดมากมาย ALU และร้านค้า ... ทรานซิสเตอร์มีราคาถูก (และไม่สามารถเปลี่ยนได้ในคราวเดียวหรือ CPU จะละลาย) ดังนั้นซีพียู x86 ที่ทันสมัยจึงมีพอร์ตการดำเนินการมากกว่า Front-end ที่สามารถฟีดได้ (โดยมีหน่วยการประมวลผลจำนวนมากที่ถูกเรพลิเคต ...
Peter Cordes

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

2
@Luaan: นอกจากนี้ใน CPU ของ Intel จำนวนเต็มและ FP / เวกเตอร์หน่วยปฏิบัติส่วนใหญ่มีการดำเนินการเดียวกันพอร์ต ตัวอย่างเช่นหน่วย FP FMA / mul / เพิ่มอยู่ในพอร์ต 0/1 แต่ตัวคูณจำนวนเต็มก็อยู่ในพอร์ต 1 และตัวเลือกจำนวนเต็มแบบง่ายสามารถเรียกใช้บนพอร์ตการดำเนินการ 4 พอร์ตใด ๆ (ไดอะแกรมในคำตอบของฉัน) เธรดที่สองที่ใช้แบนด์วิดปัญหาสูงจะทำให้ทั้งคู่ช้าลงแม้ว่าพวกเขาจะไม่ได้แข่งขันกันสำหรับหน่วยการดำเนินการ แต่บ่อยครั้งที่จะมีปริมาณงานสุทธิที่ได้มาหากพวกเขาไม่ได้แข่งขันแคชที่แย่เกินไป แม้แต่โค้ดทรูพุตความเร็วสูงที่ได้รับการปรับแต่งอย่างดีเช่น x264 / x265 (ตัวเข้ารหัสวิดีโอ) ได้รับประโยชน์ประมาณ 15% สำหรับ Skylake จาก HT
ปีเตอร์กอร์เดส

3
@ luaan นอกเหนือจากสิ่งที่ปีเตอร์กล่าวอ้างของคุณว่า"นั่นคือเหตุผลเดิมที่อยู่เบื้องหลัง HT"ไม่ถูกต้อง เหตุผลเดิมที่อยู่เบื้องหลัง HT คือการที่สถาปัตยกรรม NetBurst ได้ยาวท่อไปเช่นขอบเขตมาก (สำหรับวัตถุประสงค์ของการขับรถขึ้นความเร็วนาฬิกา) ที่ mispredictions สาขาและฟองอากาศท่ออื่น ๆ อย่างฆ่าประสิทธิภาพ HT เป็นหนึ่งในโซลูชั่นของ Intel เพื่อลดระยะเวลาที่หน่วยดำเนินการของชิปขนาดใหญ่ราคาแพงใช้งานเพราะฟองสบู่ในท่อ: รหัสจากเธรดอื่นสามารถแทรกและทำงานในรูเหล่านั้นได้
โคดี้เกรย์

24

ไม่มีสิ่งเช่นเธรดเดียวที่ทำงานบนหลายคอร์พร้อมกัน

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

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

รายการวิกิพีเดียที่เกี่ยวข้อง: การเรียนการสอน pipelining , ออกจากคำสั่งที่


3
ไม่สามารถทำงานพร้อมกันได้ แต่สามารถทำงานแบบขนานได้หรือไม่ สิ่งเหล่านี้ไม่เหมือนกันหรือไม่
Evorlor

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

3
@Evorlor: CPU ที่ล้าสมัยสามารถค้นหาและใช้ประโยชน์จากความเท่าเทียมในระดับคำสั่งภายในสตรีมคำสั่งของเธรดเดี่ยว เช่นบ่อยครั้งที่คำแนะนำในการอัพเดตตัวนับลูปเป็นอิสระจากงานอื่น ๆ ที่ลูปทำ หรือa[i] = b[i] + c[i]วนซ้ำแต่ละรอบมีความเป็นอิสระดังนั้นโหลดเพิ่มและเก็บจากการวนซ้ำที่แตกต่างกันสามารถบินได้ในครั้งเดียว จะต้องรักษาภาพลวงตาว่าคำสั่งที่ดำเนินการตามคำสั่งของโปรแกรม แต่ตัวอย่างเช่นร้านค้าที่ขาดหายไปในแคชจะไม่หน่วงเวลาเธรด (จนกว่าจะหมดพื้นที่ในบัฟเฟอร์ของร้านค้า)
Peter Cordes

3
@ user1937198: วลี "การวิเคราะห์แบบไดนามิก" จะเหมาะกับคอมไพเลอร์ JIT มากกว่า ซีพียูที่ล้าสมัยนั้นไม่ได้วิเคราะห์อย่างแท้จริง มันเป็นเหมือนอัลกอริทึมโลภที่รันคำสั่งใด ๆ ที่ได้รับการถอดรหัสและออกและมีอินพุตพร้อม (หน้าต่างเรียงลำดับใหม่ที่ไม่ถูกต้องนั้นถูก จำกัด ด้วยทรัพยากรไมโครสถาปัตยกรรมจำนวนน้อยตัวอย่างเช่น Intel Sandybridge มีขนาดบัฟเฟอร์ ReOrder ที่ 168 uops ดูที่การวัดขนาด ROB ด้วยการทดลอง ) ทั้งหมดนำมาใช้กับฮาร์ดแวร์สถานะเครื่องเพื่อจัดการ 4 uops ต่อนาฬิกา
Peter Cordes

3
@ Luaan ใช่มันเป็นความคิดที่น่าสนใจ แต่คอมไพเลอร์ AOT ยังคงไม่ฉลาดพอที่จะใช้ประโยชน์จากมันได้อย่างเต็มที่ นอกจากนี้ Linus Torvalds (และคนอื่น ๆ ) ได้แย้งว่าการเปิดเผยว่าส่วนใหญ่ของท่อภายในเป็นข้อ จำกัด อย่างมากต่อการออกแบบในอนาคต เช่นคุณไม่สามารถเพิ่มความกว้างของไปป์ไลน์ได้โดยไม่ต้องเปลี่ยน ISA หรือคุณสร้าง CPU ที่ติดตามการพึ่งพาวิธีปกติและอาจออกกลุ่ม VLIW สองกลุ่มในแบบคู่ขนาน แต่จากนั้นคุณได้สูญเสียข้อดีของ CPU-complex ของ EPIC แต่ยังมีข้อเสีย (แบนด์วิดท์ปัญหาที่หายไปเมื่อคอมไพเลอร์ไม่สามารถเติมได้ คำ).
ปีเตอร์คอร์เดส

22

สรุป: การค้นหาและการใช้ประโยชน์จากความเท่าเทียม (ระดับคำสั่ง)ในโปรแกรมแบบเธรดเดียวนั้นทำในฮาร์ดแวร์ล้วนๆโดยซีพียูหลักที่ใช้งานอยู่ และมีเพียงคำแนะนำสองสามร้อยคำเท่านั้นที่ไม่ได้เรียงลำดับใหม่จำนวนมาก

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


ระบบปฏิบัติการจัดระเบียบคำแนะนำของกระทู้ทั้งหมดในลักษณะที่พวกเขาไม่ได้รอซึ่งกันและกัน

ระบบปฏิบัติการไม่ได้ดูด้านในสตรีมคำแนะนำของเธรด เพียงกำหนดตารางเวลาเธรดให้กับแกน

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

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

จากนั้น Front-end ของ CPU จะจัดระเบียบคำแนะนำเหล่านั้นเพิ่มเติมโดยกระจายเธรดหนึ่งเธรดไปยังแต่ละคอร์และกระจายคำสั่งที่เป็นอิสระจากแต่ละเธรดในทุกรอบที่เปิด

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

ด้วย HyperThreading หรือการออกแบบ SMT อื่น ๆ แกนประมวลผลทางกายภาพจะทำหน้าที่เหมือนแกน "ตรรกะ" หลายตัว ความแตกต่างเพียงอย่างเดียวจากมุมมองของระบบปฏิบัติการระหว่าง CPU แบบ quad-core-with-hyperthreading (4c8t) และเครื่อง 8-core ธรรมดา (8c8t) คือระบบปฏิบัติการ HT-aware จะพยายามกำหนดเวลาเธรดเพื่อแยกคอร์ทางกายภาพดังนั้น ไม่แข่งขันกัน ระบบปฏิบัติการที่ไม่ทราบเกี่ยวกับการทำไฮเปอร์เธรดจะเห็น 8 คอร์ (ยกเว้นว่าคุณปิดใช้งาน HT ในไบออสจากนั้นจะตรวจจับ 4 เท่านั้น)


คำว่า " front-end" หมายถึงส่วนหนึ่งของ CPU หลักที่เรียกรหัสเครื่องถอดรหัสคำแนะนำและปัญหาพวกเขาเป็นส่วนหนึ่งออกจากคำสั่งของแกน แต่ละคอร์มีส่วนหน้าของตัวเองและเป็นส่วนหนึ่งของแกนโดยรวม คำแนะนำในการดึงข้อมูลเป็นสิ่งที่ CPU กำลังทำงานอยู่

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

หากคุณแทนที่ "core" ด้วย "execution unit" ในความคิดของคุณคุณก็ใกล้จะถูกต้องแล้ว ใช่ซีพียูแจกจ่ายคำสั่ง / uops อิสระไปยังหน่วยดำเนินการแบบคู่ขนาน (แต่มีคำศัพท์ที่ผสมกันเนื่องจากคุณพูดว่า "front-end" เมื่อจริง ๆ แล้วมันเป็นตัวกำหนดเวลาการเรียนรู้ของ CPU หรือที่รู้จักว่าสถานีจองจองที่เลือกคำสั่งพร้อมที่จะดำเนินการ)

การดำเนินการที่ไม่เป็นไปตามคำสั่งสามารถค้นหา ILP ได้ในระดับท้องถิ่นมากเพียงสองสามร้อยคำสั่งไม่ใช่ระหว่างสองลูปอิสระ (เว้นแต่ว่าสั้น)


ตัวอย่างเช่น asm ที่เทียบเท่ากับสิ่งนี้

int i=0,j=0;
do {
    i++;
    j++;
} while(42);

จะทำงานเร็วเท่ากับลูปเดียวกันการเพิ่มเพียงหนึ่งตัวนับบน Intel Haswell i++ขึ้นอยู่กับค่าก่อนหน้าของเท่านั้นiในขณะที่j++ขึ้นอยู่กับค่าก่อนหน้าของjดังนั้นโซ่การพึ่งพาทั้งสองสามารถทำงานในแบบคู่ขนานโดยไม่ทำลายภาพลวงตาของทุกสิ่งที่ถูกดำเนินการตามลำดับของโปรแกรม

ใน x86 ลูปจะมีลักษณะดังนี้:

top_of_loop:
    inc eax
    inc edx
    jmp .loop

Haswell มีพอร์ตการดำเนินการจำนวนเต็ม 4 พอร์ตและทั้งหมดมีหน่วยบวกดังนั้นมันจึงสามารถรักษาปริมาณงานได้มากถึง 4 incคำสั่งต่อนาฬิกาหากเป็นอิสระ (ด้วยความหน่วง = 1 ดังนั้นคุณต้องการเพียง 4 รีจิสเตอร์เพื่อให้ได้ปริมาณงานสูงสุดโดยเก็บ 4 incคำแนะนำในการบินตัดกันด้วย vector-FP MUL หรือ FMA: ความหน่วง = 5 ปริมาณ = 0.5 ต้องการตัวสะสมเวกเตอร์ 10 ตัวเพื่อให้ 10 FMA เพื่อให้ได้ปริมาณงานสูงสุดและเวกเตอร์แต่ละอันมีขนาด 256b โดยถือ 8 ความแม่นยำเดี่ยวลอย)

สาขาที่นำมาเป็นคอขวดด้วย: ลูปจะใช้เวลาอย่างน้อยหนึ่งตลอดทั้งนาฬิกาต่อการวนซ้ำเนื่องจากทรูพุตของสาขาที่ จำกัด จะถูก จำกัด ที่ 1 ต่อนาฬิกา ฉันสามารถเพิ่มคำแนะนำอีกหนึ่งอย่างในลูปโดยไม่ลดประสิทธิภาพเว้นแต่ว่ามันจะอ่าน / เขียนeaxหรือedxในกรณีนี้มันจะทำให้โซ่การพึ่งพานั้นยาวขึ้น การใส่คำสั่งเพิ่มเติมอีก 2 คำในลูป (หรือคำสั่งมัลติ - uop ที่ซับซ้อนหนึ่งอัน) จะสร้างคอขวดบน front-end เนื่องจากมันสามารถออก 4 uops ต่อนาฬิกาในคอร์ที่ล้าสมัยเท่านั้น (ดูคำถามและคำตอบ SO นี้สำหรับรายละเอียดบางอย่างเกี่ยวกับสิ่งที่เกิดขึ้นกับลูปที่ไม่ได้มีหลาย 4 uops: loop-buffer และ uop cache ทำให้สิ่งต่าง ๆ น่าสนใจ)


ในกรณีที่ซับซ้อนมากขึ้นการค้นหาความเท่าเทียมต้องดูที่หน้าต่างคำแนะนำที่กว้างขึ้น (เช่นอาจมีลำดับ 10 คำสั่งซึ่งทั้งหมดขึ้นอยู่กับแต่ละอื่น ๆ แล้วบางคนเป็นอิสระ)

ความจุบัฟเฟอร์สั่งซื้อใหม่เป็นหนึ่งในปัจจัยที่ จำกัด ขนาดหน้าต่างที่ไม่ได้ตามคำสั่ง บน Intel Haswell มี 192 uops (และคุณสามารถวัดได้ด้วยการทดลองพร้อมกับความสามารถในการเปลี่ยนชื่อการลงทะเบียน (ขนาดไฟล์ลงทะเบียน)) แกน CPU ที่ใช้พลังงานต่ำเช่น ARM มีขนาด ROB ที่เล็กกว่ามากหากพวกมันทำการประมวลผลที่ไม่เป็นระเบียบเลย

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

หากคุณต้องการอ่านเพิ่มเติมเกี่ยวกับ CPU internals มีลิงก์บางส่วนใน Stackoverflow x86 tag wikiรวมถึงคู่มือ microarch ของ Agner Fogและรายละเอียดการเขียนของ David Kanter พร้อมไดอะแกรมของ Intel และ AMD CPU จากการเขียนไมโครสถาปัตยกรรม Intel Haswellของเขานี่เป็นไดอะแกรมสุดท้ายของท่อทั้งหมดของแกน Haswell (ไม่ใช่ชิปทั้งหมด)

นี้เป็นบล็อกไดอะแกรมของเดี่ยว CPU หลัก ซีพียูแบบ quad-core มี 4 สิ่งเหล่านี้บนชิปแต่ละตัวมีแคช L1 / L2 ของตัวเอง (การแชร์แคช L3, ตัวควบคุมหน่วยความจำและการเชื่อมต่อ PCIe กับอุปกรณ์ระบบ)

แฮสไปป์ไลน์เต็ม

ฉันรู้ว่านี่ซับซ้อนอย่างท่วมท้น บทความของ Kanter ยังแสดงบางส่วนของสิ่งนี้เพื่อพูดคุยเกี่ยวกับส่วนหน้าแยกจากหน่วยปฏิบัติงานหรือแคชตัวอย่างเช่น


2
"การค้นหาและการใช้ประโยชน์จากความเท่าเทียม (คำสั่ง - ระดับ) ในโปรแกรมแบบเธรดเดี่ยวนั้นทำด้วยฮาร์ดแวร์ล้วนๆ" โปรดทราบว่าสิ่งนี้ใช้ได้กับ ISAs ทั่วไปไม่ใช่ VLIWs ซึ่ง ILP ถูกกำหนดโดยคอมไพเลอร์หรือโปรแกรมเมอร์หรือร่วมมือกันระหว่างฮาร์ดแวร์ และซอฟต์แวร์
Hadi Brais

1
@ user7813604: ใช่ การทำไฮเปอร์เธรดไม่สามารถทำให้เธรดเดียวขนานได้ มันจะย้อนกลับ: มันรันหลายเธรดบนแกนเดียวลดประสิทธิภาพต่อเธรด แต่เพิ่มปริมาณงานโดยรวม
Peter Cordes

1
@ user7813604: จุดทั้งหมดของ ILP คือการค้นหาว่าคำสั่งใดที่สามารถทำงานแบบขนานได้ในขณะที่ยังคงรักษาภาพลวงตาที่คำสั่งแต่ละคำสั่งทำงานตามลำดับแต่ละอันจบก่อนที่จะเริ่มต้นถัดไป ซีพียูไปป์ไลน์แบบสเกลาร์อาจจำเป็นต้องหยุดทำงานบางครั้งเพื่อการพึ่งพาหากเวลาแฝงสูงกว่า 1 แต่มันเป็นข้อตกลงที่ยิ่งใหญ่กว่าสำหรับซีพียูที่มีความเร็วสูงกว่า
Peter Cordes

1
@ user7813604: ใช่คำตอบของฉันใช้อักษรนั้นเป็นตัวอย่าง ตัวอย่างเช่น Haswell สามารถดำเนินการได้ถึง 4 incคำสั่งในรอบสัญญาณนาฬิกาเดียวกันกับหน่วยดำเนินการ ALU จำนวนเต็ม 4 ตัว
Peter Cordes

1
@ user7813604: ใช่ ILP คือจำนวนเงินที่สามารถดำเนินการแบบขนาน ซีพียูตัวจริงจะมีความสามารถ จำกัด ในการค้นหาและใช้ประโยชน์จาก ILP โดยการใช้งานมันแบบขนานภายในแกนเดียวเช่นสูงสุดถึง 4 ระดับกว้างกว่าใน Intel คำตอบนี้พยายามอธิบายด้วยตัวอย่าง
Peter Cordes
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.