3 คะแนน โดย GN⁺ 2024-07-29 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • SMT คือเทคนิคที่ให้คอร์ CPU หนึ่งคอร์ออกคำสั่งจากหลายเธรดในรอบสัญญาณเดียวกัน เพื่อเติมทรัพยากรการประมวลผลที่ว่างอยู่ให้มากขึ้น เมื่อการทำ parallelism ระดับคำสั่งอย่างเดียวไม่เพียงพอ
  • Hyper-Threading ของ Intel เป็นการใช้งานแบบสองเธรดต่อคอร์ โดยทำสำเนาสถานะสถาปัตยกรรม ทำให้ระบบปฏิบัติการมองเห็นคอร์กายภาพหนึ่งคอร์เหมือนเป็น logical processor สองตัว
  • การใช้งานจริงไม่ได้เพิ่มทรัพยากรทุกอย่างเป็นสองเท่าอย่างง่าย ๆ แต่ทำสำเนา instruction pointer, ITLB, RAT แชร์ trace cache และ TLB และ แบ่งเท่า ๆ กัน สำหรับ uop queue, physical register และ reorder buffer
  • ประโยชน์ด้านประสิทธิภาพขึ้นอยู่กับ workload หากสองเธรดแย่งใช้แคชกันอาจช้าลงได้ ส่วนเธรดที่ร่วมมือกันและส่งข้อมูลให้กันอาจเร็วขึ้นได้เพราะมี shared cache
  • ทรัพยากรที่แชร์กันและ speculative execution อาจนำไปสู่ช่องโหว่ด้านความปลอดภัยได้ ดังนั้นในสภาพแวดล้อมที่อ่อนไหวด้านความปลอดภัย หรือ workload ที่ต้องการประสิทธิภาพสูงสุดและ latency ต่ำสุด การ ปิดใช้งาน SMT จึงเป็นทางเลือกที่ใช้งานได้จริง

เหตุผลที่ต้องมี SMT

  • โปรเซสเซอร์สมัยใหม่มีรีจิสเตอร์หลายร้อยตัว, load/store unit หลายตัว และ arithmetic unit หลายตัว และใช้เทคนิค parallelism ระดับคำสั่ง เช่น pipelining, โครงสร้าง superscalar และการประมวลผลแบบ out-of-order เพื่อใช้ทรัพยากรเหล่านี้
  • pipeline แบ่งการประมวลผลคำสั่งออกเป็นหลายขั้น และส่งคำสั่งไปยังขั้นถัดไปในแต่ละรอบสัญญาณ โดยใน pipeline ลึก 5 ขั้น หลังจากรอบสัญญาณที่ 5 เป็นต้นไป อาจมีคำสั่งกำลังดำเนินอยู่พร้อมกันได้สูงสุด 5 คำสั่ง
  • โปรเซสเซอร์แบบ superscalar สามารถออกคำสั่งได้หลายคำสั่งในหนึ่งรอบสัญญาณ และโปรเซสเซอร์ Intel Core i7 รุ่นใหม่ ๆ สามารถออกคำสั่งได้ 4 คำสั่งต่อรอบสัญญาณ
  • ในโปรแกรมจริงมักหาคำสั่งที่เป็นอิสระต่อกันมากพอได้ยาก จึงเกิดช่วงเวลาที่ทรัพยากรการประมวลผลว่างอยู่
    • การสูญเปล่าแนวนอน เกิดขึ้นเมื่อภายในเธรดเดียวหาคำสั่งที่เป็นอิสระต่อกันได้ไม่พอที่จะเติม issue width ให้เต็ม
    • การสูญเปล่าแนวตั้ง เกิดขึ้นเมื่อคำสั่งถัด ๆ ไปขึ้นกับคำสั่งที่กำลังรันอยู่ ทำให้ในหนึ่งรอบสัญญาณไม่สามารถออกคำสั่งใดได้เลย
  • multithreading แบบดั้งเดิมออกคำสั่งจากเธรดเดียวต่อรอบสัญญาณ แล้วสลับไปยังเธรดอื่นในรอบถัดไป จึงลดการสูญเปล่าแนวตั้งได้ แต่ยังคงมีการสูญเปล่าแนวนอนและ overhead จากการสลับ context
  • SMT ออกคำสั่งจากหลายเธรดในรอบสัญญาณเดียวกันโดยไม่ต้องสลับ context ทำให้เติมทรัพยากรการประมวลผลได้ในสัดส่วนที่สูงขึ้น
  • Hyper-Threading ซึ่งเป็นการใช้งาน SMT ของ Intel ถูกจำกัดไว้ที่สองเธรดต่อคอร์

โครงสร้างพื้นฐานของ SMT แบบ Intel

  • โปรเซสเซอร์ทั่วไปที่ไม่ใช่ SMT สามารถรันคำสั่งของเธรดเดียวได้ในแต่ละครั้ง
  • แต่ละเธรดมี สถานะสถาปัตยกรรม ซึ่งรวมถึงค่ารีจิสเตอร์, program counter, control register ฯลฯ
  • หากต้องการรันคำสั่งของสองเธรดพร้อมกัน ต้องสามารถแทนสถานะของสองเธรดได้พร้อมกัน ดังนั้นการใช้งาน SMT จึงทำสำเนา สถานะสถาปัตยกรรม ของโปรเซสเซอร์
  • ด้วยการทำสำเนานี้ โปรเซสเซอร์กายภาพหนึ่งตัวจึงปรากฏต่อระบบปฏิบัติการเป็น logical processor สองตัว และระบบปฏิบัติการสามารถ schedule เธรดไปยังแต่ละตัวได้
  • buffer และทรัพยากรประมวลผลระดับ microarchitecture จะถูกทำสำเนา แชร์ หรือแบ่งกัน ตามปัจจัยอย่างต้นทุน พลังงาน และพื้นที่ชิป
  • ประเด็นที่พูดถึงส่วนใหญ่คือการใช้งาน SMT ของ Intel และอิงจาก white paper ของ Intel ปี 2002

สามส่วนของ CPU microarchitecture

  • โปรเซสเซอร์ให้ ISA เป็นอินเทอร์เฟซสาธารณะแก่นักโปรแกรม โดย ISA รวมถึงชุดคำสั่งและรีจิสเตอร์ที่คำสั่งสามารถใช้ได้
  • microarchitecture คือการใช้งานภายในที่อาจแตกต่างกันได้แม้ระหว่างโปรเซสเซอร์รุ่นที่รองรับ ISA เดียวกัน
  • microarchitecture ของโปรเซสเซอร์สมัยใหม่แบ่งได้กว้าง ๆ เป็นสามส่วน
    • frontend: รวม instruction control unit ที่ดึงและถอดรหัสคำสั่งของโปรแกรมที่จะรันถัดไป
    • backend: รวมทรัพยากรประมวลผล เช่น physical register, arithmetic unit, load/store unit และจัดสรรทรัพยากรให้คำสั่งที่ถอดรหัสแล้วเพื่อ schedule การประมวลผล
    • retirement unit: นำผลลัพธ์ของคำสั่งที่รันแล้วไปสะท้อนในสถานะสถาปัตยกรรมของโปรเซสเซอร์ในขั้นสุดท้าย

SMT ใน frontend

  • instruction pointer ติดตามที่อยู่ของคำสั่งที่จะดึงถัดไป
    • โปรเซสเซอร์ที่รองรับ SMT มี instruction pointer สองชุดเพื่อติดตามคำสั่งถัดไปของสองโปรแกรมอย่างอิสระ
  • trace cache เก็บ trace ของคำสั่งที่เพิ่งถอดรหัสไว้ เพื่อลดต้นทุนการถอดรหัสและ latency ของการรันคำสั่งที่ถูกเรียกซ้ำ
    • logical processor สองตัวแชร์กันแบบไดนามิกตามความจำเป็น
    • หากเธรดหนึ่งรันคำสั่งมากกว่า ก็อาจครอบครอง entry ใน trace cache มากกว่า
    • แต่ละ entry ถูก tag ด้วยข้อมูลเธรดเพื่อแยกคำสั่งของสองเธรด
    • การเข้าถึง trace cache จะถูก arbitrate ระหว่าง logical processor สองตัวในทุกรอบสัญญาณ
  • เมื่อเกิด trace cache miss frontend จะค้นหาคำสั่งที่ที่อยู่นั้นใน L1 instruction cache และหากเกิด L1 instruction cache miss ก็ต้องดึงจากแคชระดับถัดไปหรือหน่วยความจำหลัก
  • L1 instruction cache แคชข้อมูลด้วย virtual address แต่การเข้าถึงหน่วยความจำหลักต้องใช้ physical address
  • ITLB เก็บ virtual address ที่เพิ่งแปลงแล้ว เพื่อแปลง virtual address เป็น physical address
    • ในโปรเซสเซอร์ที่รองรับ SMT แต่ละ logical processor มี ITLB cache ของตัวเอง
    • logic สำหรับดึงคำสั่งจากหน่วยความจำหลักทำงานแบบ first come first served แต่จะจอง request slot อย่างน้อยหนึ่งช่องให้แต่ละ logical processor เพื่อให้ทั้งสองตัวเดินหน้าต่อได้
    • คำสั่งที่มาจากหน่วยความจำหลักจะถูกเก็บไว้ใน streaming buffer ขนาดเล็กก่อนการถอดรหัส และในโปรเซสเซอร์ที่รองรับ SMT buffer นี้ก็ถูกทำสำเนาแยกตาม logical processor ด้วย
  • หลังจากดึงมาแล้ว คำสั่งจะถูกถอดรหัสเป็น uop ที่เล็กและง่ายกว่า
    • uop จะเข้าไปยัง uop queue ซึ่งทำหน้าที่เป็นขอบเขตระหว่าง frontend และ backend ของ CPU
    • uop queue ถูกแชร์อย่างเท่าเทียมระหว่าง logical processor สองตัว และการแบ่งแบบคงที่นี้ทำให้ logical processor ทั้งสองเดินหน้าได้อย่างอิสระ

SMT ใน backend

  • backend นำ micro-instruction จาก uop queue มารัน แต่ไม่ได้ยึดติดกับลำดับเดิมของโปรแกรมเท่านั้น และทำ out-of-order execution
  • คำสั่งของโปรแกรมที่อยู่ใกล้กันมักขึ้นต่อกัน และหากมีงานที่ latency สูงอย่างการอ่านหน่วยความจำหลัก คำสั่งที่ขึ้นต่อกันก็ต้องรอด้วย
  • out-of-order execution engine รันคำสั่งที่อยู่ด้านหลังให้เร็วกว่าลำดับเดิม เพื่อลดการสูญเปล่าของทรัพยากร
  • allocator ระบุทรัพยากรที่ micro-instruction ต้องใช้และจัดสรรตามความพร้อมใช้งาน
    • ในหนึ่งรอบสัญญาณจะจัดสรรทรัพยากรให้ micro-instruction ของ logical processor หนึ่งตัว และในรอบถัดไปจะสลับไปยัง logical processor อีกตัว
    • หากใน uop queue มี micro-instruction ของ logical processor เพียงตัวเดียว หรือ logical processor ตัวหนึ่งใช้ทรัพยากรในส่วนของตัวเองหมดแล้ว allocator จะใช้ทุกรอบสัญญาณให้ logical processor อีกตัว
  • ทรัพยากรหลักของ backend เป็นส่วนผสมของการทำสำเนา การแชร์ และการแบ่ง
    • X86-64 ในระดับ ISA มี general-purpose integer register เพียง 16 ตัว แต่ในระดับ microarchitecture มี physical integer register หลายร้อยตัว และ floating-point register ในจำนวนใกล้เคียงกัน
    • ในโปรเซสเซอร์ที่รองรับ SMT physical register จะถูกแบ่งเท่า ๆ กันให้ logical processor สองตัว
    • load buffer และ store buffer ที่ใช้กับงานอ่าน/เขียนหน่วยความจำก็ถูกแบ่งเท่า ๆ กันให้ logical processor สองตัวเช่นกัน

Register renaming, scheduling และ commit

  • เพื่อ out-of-order execution backend จะทำ register renaming
    • เนื่องจากในระดับ ISA มี architectural register จำนวนน้อย คำสั่งของโปรแกรมจึงนำรีจิสเตอร์เดียวกันกลับมาใช้ซ้ำในคำสั่งอิสระหลายคำสั่ง
    • out-of-order execution engine เปลี่ยน logical register เดิมให้เป็นหนึ่งใน physical register เพื่อให้รันขนานกับการรันก่อนหน้าได้
    • mapping นี้ถูกเก็บไว้ใน register alias table หรือ RAT
    • logical processor สองตัวมีชุด architectural register ของตัวเอง ดังนั้น RAT ก็มีสำเนาของตัวเองเช่นกัน
  • คำสั่งที่ผ่านขั้นตอน register renaming และ allocator จะเข้าไปใน ready queue
    • queue หนึ่งสำหรับคำสั่งอ่าน/เขียนหน่วยความจำ และอีก queue สำหรับคำสั่งทั่วไป
    • ในคอร์ที่รองรับ SMT queue เหล่านี้จะถูกแบ่งเท่า ๆ กันให้ logical processor สองตัว
  • โปรเซสเซอร์มี instruction scheduler หลายตัวทำงานขนานกัน
    • ในแต่ละรอบสัญญาณ คำสั่งบางส่วนใน ready queue จะถูกส่งไปยัง scheduler
    • queue จะส่งคำสั่งของ logical processor หนึ่งตัวในรอบสัญญาณหนึ่ง และสลับไปยัง logical processor อีกตัวในรอบถัดไป
    • scheduler ไม่สนใจ logical processor และส่ง micro-instruction ที่ operand และ execution unit ที่จำเป็นพร้อมแล้วไปประมวลผลทันที
    • เพื่อความเป็นธรรม จะมีข้อจำกัดจำนวน active entry ที่ logical processor หนึ่งตัวสามารถมีได้ใน scheduler queue
  • ผลลัพธ์ของคำสั่งที่รันเสร็จจะเข้าไปยัง reorder buffer
    • แม้คำสั่งจะถูกรันแบบ out-of-order แต่ต้อง commit เข้าสู่สถานะสถาปัตยกรรมของโปรเซสเซอร์ตามลำดับเดิมของโปรแกรม
    • ในคอร์ที่รองรับ SMT reorder buffer จะถูกแบ่งเท่า ๆ กันให้ logical processor สองตัว
  • retirement unit ติดตามว่าคำสั่งพร้อม commit เข้าสู่สถานะสถาปัตยกรรมแล้วหรือยัง และ retire ตามลำดับโปรแกรมที่ถูกต้อง
    • ในคอร์ที่รองรับ SMT จะสลับประมวลผลระหว่าง micro-instruction ของแต่ละ logical processor
    • หาก logical processor ตัวหนึ่งไม่มี micro-instruction ให้ retire ก็จะใช้ bandwidth ทั้งหมดให้ logical processor อีกตัว
    • หลัง retire คำสั่งแล้ว อาจต้องเขียนไปยัง L1 cache และ logic สำหรับเลือกการเขียนนี้ก็สลับระหว่าง logical processor สองตัวในทุกรอบสัญญาณเช่นกัน

ผลของ memory subsystem และ cache

  • TLB ที่แปลง virtual address ของคำขอข้อมูลเป็น physical address จะถูกแชร์แบบไดนามิกตามความจำเป็นโดย logical processor สองตัว
  • entry ของ TLB ถูก tag ด้วย logical processor id เพื่อแยกรายการของ logical processor สองตัว
  • CPU แต่ละคอร์มี private L1 cache ของตัวเอง
  • L2 cache อาจเป็น private หรือแชร์ระหว่างคอร์ ขึ้นอยู่กับ microarchitecture
  • หากมี L3 cache จะถูกแชร์ระหว่างคอร์
  • cache ไม่รับรู้ถึงการมีอยู่ของ logical processor
  • เนื่องจาก L1 cache และในบางกรณี L2 cache เป็น private ต่อคอร์ จึงเก็บข้อมูลของ logical processor สองตัวไว้ร่วมกันตามความจำเป็น
    • หากสองเธรดใช้แคชอย่างหนัก จะเกิด data collision และ eviction ทำให้ประสิทธิภาพลดลงได้
    • หากสองเธรดทำงานกับชุดข้อมูลเดียวกัน shared cache อาจเพิ่มประสิทธิภาพได้

เกณฑ์การเลือกด้านประสิทธิภาพและความปลอดภัย

  • แม้จะรันเพียงเธรดเดียวบนคอร์ที่รองรับ SMT buffer และทรัพยากรประมวลผลจำนวนมากก็ยังคงอยู่ในสภาพที่แชร์หรือถูกแบ่งระหว่าง logical processor สองตัว ทำให้อาจลดศักยภาพประสิทธิภาพของเธรดเดี่ยวลง
  • บน logical processor ที่ไม่ได้ใช้งาน ระบบปฏิบัติการจะรัน idle loop และ loop นี้ก็อาจใช้ทรัพยากรที่ logical processor อีกตัวสามารถใช้เพื่อให้ได้ประสิทธิภาพสูงสุด
  • ในโปรเซสเซอร์ Intel Core เมื่อมีเพียงเธรดเดียวรันบนคอร์ ดูเหมือนว่าจะไม่มีการแชร์หรือแบ่งทรัพยากร และ Intel ถือว่าสิ่งนี้เป็นการปรับปรุงที่นำมาใช้ในเจเนอเรชันนั้น
  • เมื่อสองเธรดรันบน logical processor สองตัวของคอร์ที่รองรับ SMT รูปแบบการเข้าถึงแคช จะเป็นตัวกำหนดประสิทธิภาพ
    • หากสองเธรดแข่งขันกันใช้แคช ก็จะ evict ข้อมูลของกันและกัน ทำให้ประสิทธิภาพลดลง
    • หากเป็นแบบร่วมมือกัน เช่น ข้อมูลที่เธรดหนึ่งผลิตถูกอีกเธรดหนึ่งบริโภค การแชร์ข้อมูลในแคชจะช่วยปรับปรุงประสิทธิภาพ
    • หากสองเธรดไม่ได้แย่งใช้แคชกัน ก็สามารถเพิ่มอัตราการใช้ทรัพยากรของคอร์ CPU ได้โดยไม่ลดประสิทธิภาพของกันและกัน
  • ผู้เชี่ยวชาญจำนวนมากมองว่า สำหรับโปรแกรมที่ต้องการประสิทธิภาพสูงสุดแบบสัมบูรณ์ ควรปิด SMT เพื่อให้เธรดเดียวใช้ทรัพยากรทั้งหมดได้
  • SMT ยังมาพร้อม ปัญหาด้านความปลอดภัย ด้วย
    • ทรัพยากรที่แชร์กันและ speculative execution อาจเปิดโอกาสให้ข้อมูลที่อ่อนไหวรั่วไหลไปยังผู้โจมตี
    • เอกสารของ Oracle Linux และ Red Hat เชื่อมโยงไปยังตัวอย่างประเด็นความปลอดภัยที่เกี่ยวกับ SMT
    • คำแนะนำทั่วไปคือให้ปิดใช้งาน SMT บนระบบ
    • ยังมีข่าวลือว่า Intel อาจถอด Hyper-Threading ออกจากโปรเซสเซอร์รุ่นถัดไปอย่าง Arrow Lake

เอกสารอ้างอิง

1 ความคิดเห็น

 
GN⁺ 2024-07-29
ความคิดเห็นจาก Hacker News
  • ถ้าเข้าใจ SMT แบบง่ายมาก ๆ สิ่งที่เห็นภาพคือ มันช่วยให้ ALU อันมีค่ายังคงถูกใช้งานต่อไปได้ในขณะที่เธรดหยุดรอเพราะ cache miss
    LPDDR ในโน้ตบุ๊กรุ่นเก่า ๆ ช้ากว่านี้ และจำนวนคอร์ก็ยังน้อย จึงน่าจะมีคุณค่ามากกว่า แต่ทุกวันนี้บ่อยครั้งมีคอร์มากกว่างานที่สเกลได้ เลยรู้สึกถึงคุณค่าน้อยลง
    บางครั้งก็หลีกเลี่ยง cache contention ด้วยการไม่จัดงานไปไว้บนคอร์เดียวกับเธรดสำคัญ เพราะรู้ว่าคอขวดอยู่ที่ประสิทธิภาพแบบเธรดเดียว
    ก่อนหน้านี้เคยทดสอบคอร์ Efficient/Performance กับคอร์ SMT ในการเรนเดอร์แบบมัลติเธรดของ DirectX 12 และบน i7-12700K เวลาเรนเดอร์ฉากซับซ้อนแทบไม่ต่างกันระหว่างใช้เฉพาะ P-core, ใช้ P+SMT และใช้ P+E+SMT อย่างไรก็ตามบน Xbox Series X การทดสอบเดียวกันเร็วขึ้นเล็กน้อยเมื่อจัดงานลง SMT ด้วย

    • งานเรนเดอร์เป็นหนึ่งในสถานการณ์ที่ SMT เท่ากันหรือช้ากว่ามาตั้งแต่แรกอยู่แล้ว เพราะมีการคำนวณทางคณิตศาสตร์มากจน FPU ยุ่งตลอดเวลา โดยเฉพาะตัวหารซึ่งเป็นการดำเนินการที่แพงที่สุดในโปรเซสเซอร์
      SMT จะเด่นเมื่อรอ I/O หรือทำงานจำนวนเต็มง่าย ๆ ถ้าทั้งสองเธรดสามารถทำให้ FPU เต็มได้ทั้งคู่ โดยทั่วไป SMT จะช้าลงเพราะต้องมีการแท็กเพิ่มเติมเพื่อระบุความเป็นเจ้าของข้อมูลภายใน CPU
    • Hyper-Threading ของ Intel โดยแท้จริงแล้วค่อนข้างเหมือนการแฮ็ก write pipeline
      ประเด็นหลักไม่ได้อยู่ที่ cache miss เท่าไร แต่อยู่ที่การปล่อยให้คอร์ไปทำอย่างอื่นระหว่างรอให้การเขียนเสร็จ
      ดังนั้นโค้ดบางแบบจึงสเกลไม่ดี ส่วนบางแบบก็ได้ความเร็วเพิ่มขึ้นเกือบเป็นเชิงเส้น
    • ทุกวันนี้ โดยเฉพาะเมื่อคำนึงถึง การจ่ายไฟจากด้านหลัง ด้วย ผมสงสัยว่าการหยุดนิ่งของแคชในโปรเซสเซอร์หนึ่งตัวช่วยลด thermal throttling ของโปรเซสเซอร์นั้นและโปรเซสเซอร์ข้างเคียงได้มากแค่ไหน
      บางทีการปล่อยให้โปรเซสเซอร์พวกนี้งีบสั้น ๆ อาจดีกว่าก็ได้
    • เกี่ยวกับประเด็นที่ว่า LPDDR ในอดีตช้ากว่า น่าแปลกที่ latency แทบไม่ได้ดีขึ้นมากนัก CAS latency ของ DDR2/3/4/5 โดยทั่วไปอยู่ราว 5~10ns
      ความกว้างบัส จำนวนการส่งต่อวินาที การจัดคิว และพลังงานต่อการส่ง/จัดเก็บบิตดีขึ้น แต่ถ้าโปรแกรมต้องการข้อมูลที่ไม่มีอยู่ในแคชและการทำนายก็พลาด สุดท้าย RAM latency ก็ยังเป็นปัญหา
    • สงสัยว่าจะเป็นไปได้ไหมที่จะปิด ALU/FPU ที่ไม่ได้ใช้งานชั่วคราวระหว่างรอบางอย่างในส่วนหน้าของ pipeline แทน SMT โดยมุ่งลดความร้อนและการใช้พลังงานมากกว่าการเพิ่มอัตราการใช้งานให้สูงสุด
  • ว่ากันว่า CPU Arrow Lake รุ่นถัดไปของ Intel จะถอด Hyper-Threading หรือ SMT ออกไปทั้งหมด
    ผลลัพธ์ด้านประสิทธิภาพขึ้นกับแอปพลิเคชันมากมาโดยตลอด ดังนั้นการทำให้เรียบง่ายลงอาจดีกว่า
    มีการถกเถียงล่าสุดเรื่องมันมีความหมายเมื่อไรและที่ไหนอยู่ที่นี่: https://news.ycombinator.com/item?id=39097124

    • โปรแกรมส่วนใหญ่จะมีขีดจำกัดของจำนวนเธรดที่ใช้ได้อย่างสมเหตุสมผล เมื่อจำนวนคอร์น้อยกว่านั้นมาก SMT ก็มีความหมายเพื่อใช้ทรัพยากร CPU ให้ดีขึ้น แต่เมื่อมีคอร์เพียงพอแล้ว SMT อาจไม่สมเหตุสมผลอีกต่อไป
      ยังไม่มั่นใจว่าเรามาถึงจุดนั้นแล้วจริง ๆ แต่คอร์ P/E ของ Intel เป็นทางเลือกที่มุ่งสู่เป้าหมายคล้ายกัน และค่อนข้างสมเหตุสมผลบนเดสก์ท็อปที่มีงานแบบเธรดเดียว/เธรดน้อยจำนวนมาก ดูเหมือนจะมีคุณค่าตรงที่ไม่ต้องจัดการความแตกต่างระหว่าง SMT กับ E-core ในการปรับแต่งแอปพลิเคชันด้วย
      ในทางกลับกัน AMD วางแผนจะรักษาคอร์ที่โดยรวมเป็นเนื้อเดียวกันไว้ต่อไปสักระยะและใช้ SMT ต่อไป กลยุทธ์ไหนดีกว่าจริง ๆ คงตัดสินแบบง่าย ๆ ได้ยาก เพราะขึ้นกับแต่ละแอปพลิเคชันอย่างมาก
    • ในกรณีใช้งานส่วนตัวที่กำลังทำเกมและเอนจินอยู่ การภาวนาต่อเทพแห่งการจัดวางเธรดของ CPU ให้แต่ละเธรดได้ใช้คอร์ของตัวเองเร็วกว่าการใช้ Hyper-Threading
      ดังนั้นจึงตัดสินใจจำกัดจำนวนเธรดไว้ที่ std::thread::hardware_concurrency() / 2 - 1 หรือก็คือ จำนวนคอร์ - 1 กำลังจัดการกับ std::vector อยู่
    • ตามเกณฑ์ benchmark ที่พบได้ทั่วไปในอุตสาหกรรม Intel Hyper-Threading ช้ากว่าการปิดอย่างน้อยแทบจะเว้นเจเนอเรชันละครั้ง
      แม้ตอนที่ทำงานได้ดี การปรับปรุงก็มีแค่ระดับเปอร์เซ็นต์สองหลัก และยังมีช่วงที่แย่ลงในหลายเจเนอเรชันต่อเนื่องด้วย เลยไม่เข้าใจว่าทำไมยังพยายามต่อไป
    • ในชิ้นส่วนสำหรับเซิร์ฟเวอร์ก็เป็นแบบนั้นด้วยหรือเปล่า?
  • ทุกครั้งที่อ่านว่า ฟีเจอร์ระดับล่างของ CPU แบบนี้ทำงานอย่างไร ก็รู้สึกทึ่ง
    สมัยมหาวิทยาลัยเคยเรียนวิชาประมาณ “พื้นฐานฮาร์ดแวร์คอมพิวเตอร์” แต่จริง ๆ น่าจะเรียกว่า “พื้นฐานการออกแบบ CPU” มากกว่า เราสร้าง adder, latch, flip-flop ฯลฯ จาก logic gate และพอจบเทอมก็สามารถออกแบบโปรเซสเซอร์พื้นฐานมาก ๆ ในระดับ gate ได้
    แต่จินตนาการไม่ค่อยออกว่าจะคิดค้นสิ่งอย่าง register renaming หรือ out-of-order execution ขึ้นมาได้อย่างไร สิ่งเหล่านี้ก็ออกแบบในระดับ gate ด้วยหรือเปล่า? หรือมีภาษาและ “compiler” ที่ช่วยจัดวาง gate/ทรานซิสเตอร์ให้ใช้อยู่?

    • ผมเรียนวิชาขั้นถัดไป และได้เรียน SMT กับอย่างอื่นเพิ่มอีกหลายอย่าง
      งานทั้งหมดทำด้วยภาษาอธิบายฮาร์ดแวร์ชื่อ Verilog ซึ่งช่วยให้เขียนโดย抽象องค์ประกอบหลาย ๆ อย่างได้
  • ความเข้าใจผิดใหญ่ ๆ อย่างหนึ่งที่ผู้ใช้มักมีเกี่ยวกับ SMT คือ โมเดลทางความคิด ที่จินตนาการว่ามี “คอร์จริง” หนึ่งคอร์กับคอร์อีกหนึ่งที่ด้อยกว่า
    ในทุกแง่มุมที่สังเกตได้ ทั้งสองเธรดเท่าเทียมกัน

    • ความเข้าใจแบบนั้นน่าจะมาจากเรื่องประสิทธิภาพ ทั้งสองเธรดสามารถทำงานเดียวกันได้ก็จริง แต่ไม่ได้ให้ ประสิทธิภาพ 2 เท่า เหมือนมีเธรดที่สองแบบ “จริง ๆ” หรือก็คือมีคอร์ที่สอง
      สุดท้ายถ้ามองเฉพาะประสิทธิภาพ ในเชิงแนวคิดมันใกล้เคียงกับการมีคอร์แบบเธรดเดียวสัก 1.25 คอร์ หรือมีตามสัดส่วนนั้นขึ้นกับแอปพลิเคชันมากกว่า
    • เวลาเรียกใช้งานที่ปรับแต่งมาอย่างหนักและกินการคำนวณมากอย่างการบีบอัดวิดีโอ พัดลมคอมพิวเตอร์ดังเหมือนเครื่องยนต์เจ็ต แต่ Task Manager แสดงว่า CPU usage 50% ก็เข้าใจได้ว่าทำไมถึงเกิดความคิดแบบนั้น
    • CPU ใหม่ของ Intel มีทั้งคอร์จริงที่เรียกว่า “P-core” และคอร์ที่ด้อยกว่าที่เรียกว่า “E-core” จริง ๆ
      ผมมองว่าเหตุผลหลักที่นำ E-core มาใช้ไม่ใช่เรื่องการใช้พลังงานหรือประสิทธิภาพเท่าไร แต่เป็นเรื่องความร้อนและพื้นที่ die ดังนั้นผมจึงซื้อชิปที่ไม่มี E-core เสมอ และคิดว่าทางนั้นดีกว่า
  • สงสัยว่าควรค้นหาบทความเทคนิคละเอียด ๆ แบบนี้อย่างไร
    ลองค้นด้วยหัวข้อนี้ตรง ๆ แล้ว แต่ก็เป็นไปตามคาด เพราะเป็นเทคโนโลยีสำหรับผู้ใช้ปลายทาง ผลการค้นหาจึงมีแต่ บทความสำหรับผู้ใช้ ที่แทบไม่ได้อธิบายอะไรให้ชัดเจน

    • ใช้ https://hn.algolia.com ก็ได้ โดยตั้งอยู่บนสมมติฐานว่าบทความประเภทนี้ส่วนใหญ่จะถูกโพสต์หรือถูกกล่าวถึงใน HN
    • LLM ที่เข้าถึงเว็บได้ดูค่อนข้างเหมาะกับการค้นหาแบบนี้ อย่างน้อยก็ช่วยจับทิศทางได้
      แต่ URL ที่ให้มาส่วนใหญ่เป็น hallucination
    • ไม่รู้ว่า Google ติดตามความสนใจที่พุ่งขึ้นต่อบทความนั้นเพราะโพสต์ HN นี้หรือไม่ แต่เมื่อค้นว่า “how does simultaneous multi threading work” บทความบล็อกนี้ก็ขึ้นมาแถว ๆ ผลลัพธ์ที่ 5 สำหรับผม
      ผมตรวจจากแท็บส่วนตัวใหม่ของ Firefox บนอุปกรณ์อีกเครื่อง แม้จะกันการติดตามหรือแคชได้ไม่หมด แต่คิดว่าเป็นค่าประมาณที่สมเหตุสมผลทีเดียว
  • คำอธิบายที่ว่า “บนคอร์ CPU ที่เปิด SMT บัฟเฟอร์และทรัพยากรสำหรับประมวลผลจำนวนมากต้องถูกแชร์ระหว่างโปรเซสเซอร์เชิงตรรกะสองตัว ดังนั้นแม้จะมีเธรดเดียวที่กำลังรันอยู่บนคอร์ SMT ทรัพยากรเหล่านั้นก็ไม่พร้อมให้เธรดนั้นใช้ และทำให้ประสิทธิภาพที่เป็นไปได้ลดลง” ตอนนี้ไม่เป็นความจริงแล้ว
    ในโหมด SMT จะมีการแบ่ง ROB, แบนด์วิดท์ fetch/decode ฯลฯ แต่ผมเคยเห็นคอร์ SMT หลายแบบที่เมื่อไม่ได้อยู่ใน SMT ก็เปิดให้ใช้ทั้งหมดได้

    • โปรเซสเซอร์ Phi ซีรีส์ x200 ทำงานแบบนั้นพอดี ในโหมด non-SMT จะได้ทรัพยากรต่อเธรดมากกว่าโหมด 4-way SMT อย่างมาก
  • เป้าหมายหลักของ SMT คือการเพิ่มอัตราการใช้งานของ เอนจินประมวลผลแบบ superscalar ให้สูงสุด
    เลยสงสัยว่าแนวโน้มแบบนี้หมายความว่าผู้คนคิดว่า superscalar ไม่สำคัญเท่าเมื่อก่อนแล้วหรือไม่

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

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

    • สถาปัตยกรรม PowerXX ไม่ได้กำลังถอยห่างจาก SMT
      Power10 ปัจจุบันรองรับ SMT8 ที่มี 8 เธรดต่อคอร์ได้อย่างมีประสิทธิภาพ และเมื่อดูจากความพยายามที่พัฒนาการออกแบบซึ่งเน้น SMT มาหลายปี ก็ไม่น่าคิดว่าพวกเขาจะทิ้งมัน
  • สิ่งที่ควรรู้คือ หน่วยคำนวณ ของ GPU ก็มักใช้ SMT ในระดับประมาณ 7–10 เธรดต่อ CU เช่นกัน
    วิธีนี้ช่วยซ่อน latency ได้

    • GPU ส่วนใหญ่ไม่ได้ใช้ SMT แต่ใช้ fine-grained multithreading ซึ่งเป็นบรรพบุรุษของมัน
      ในทุก clock cycle จะเลือกคำสั่งของเธรดที่ต้องการทรัพยากรซึ่งไม่ได้ยุ่งอยู่ จากหลายเธรดที่พร้อมใช้งาน แล้วเริ่มคำสั่งนั้น GPU ส่วนใหญ่ไม่ได้เริ่มหลายคำสั่งต่อหนึ่งคล็อก แม้หลายคำสั่งอาจดำเนินไปพร้อมกันได้หลังจากเริ่มแล้วก็ตาม ต่อให้เริ่มหลายคำสั่งต่อคล็อกได้ ก็อาจต้องเป็นคลาสคำสั่งแยกกันที่ใช้ทรัพยากรประมวลผลต่างกัน เช่น คำสั่ง scalar กับคำสั่ง vector
      SMT หรือ simultaneous multithreading คือวิธีที่ในทุก clock cycle จะมีคำสั่งจำนวนมากจากทุกเธรดเริ่มพร้อมกัน และคำสั่งเหล่านั้นแข่งขันกันเพื่อใช้ execution unit หลายตัวของ CPU แบบ superscalar เพื่อทำให้ execution unit ให้ได้มากที่สุดไม่ว่างงาน สำหรับแต่ละหน่วยประมวลผลแบบขนาน เช่น integer adder ทั้ง 6 ตัวของ CPU สมัยใหม่ จะมีการตัดสินใจแยกกันว่าจะรันคำสั่งใดจากคิวที่บรรจุคำสั่งของเธรดพร้อมกันทั้งหมด