ผมได้อ่านเรื่องราวความเป็นมาและรายละเอียดของชิป M1 ของ Apple แล้วรู้สึกทึ่ง และหมั่นไส้นิดๆ จึงอยากมาเล่าถึงความดีงามของชิป M1 (ส่วนความหมั่นไส้ไว้เล่าช่วงท้าย) ในมุมมอง software architect
จุดเด่นสุดๆ ในมุมมองผมคือ การที่ Apple ออกแบบชิป M1 ในแบบ ‘centralization‘ ซึ่งทาง Apple เรียกแนวคิดนี้ว่า ‘System on Chip (SoC)’ ที่เป็นการรวมส่วนการประมวลผลสำคัญๆ มาไว้ในชิปเดียวกัน โดยการทำงานของแต่ละส่วนการประมวลผลถูกแยกออกอย่างเป็นอิสระกันอีกที ดูได้จากรูปด้านล่าง (รูปจาก https://www.apple.com/th/mac/m1/)
ผมขออธิบายมุมมองผมออกเป็นข้อย่อยๆ ดังนี้นะครับ
- แต่ละส่วนการประมวลผลทำหน้าที่เฉพาะของตัวเองชัดเจน (high modularity & separation of concerns)
- มีการออกแบบ communication path เพื่อเชื่อมแต่ละส่วนการประมวลผล ให้แต่ละส่วนเชื่อมต่อ รับ/ส่ง ข้อมูลกันบน shared communication path เดียวกัน และเมื่อทุกส่วนอยู่บนชิปเดียวกันทำให้ระยะทางที่ข้อมูลต้องเดินทางสั้นลง เวลาหน่วง (latency) ในการเดินทางของข้อมูลจึงน้อย จึงทำให้แต่ละส่วนการประมวลผลรับ/ส่งข้อมูลระหว่างกันได้รวดเร็วกว่าสถาปัตยกรรมคอมพิวเตอร์แบบเดิมๆ ที่ฮาร์ดแวร์ส่วนต่างๆ ทั้ง CPU, RAM, GPU (การ์ดจอ) ติดตั้งแยกกันบนเมนบอร์ด การรับ/ส่งข้อมูลระหว่างกันต้องอาศัย bus บนเมนบอร์ด ทำให้เกิด dependency กับประสิทธิภาพของเมนบอร์ดแต่ละรุ่นแต่ละยี่ห้อ ซึ่งส่งผลต่อ stability หรือความเสถียรต่อการรันแอพพลิเคชั่น เช่น การเซ็ตอัพเครื่องคอมพิวเตอร์ 2 เครื่องโดยใช้ CPU, RAM, GPU สเป๊กเดียวกันเป๊ะ แต่ใช้เมนบอร์ดคนละรุ่นกัน จะไม่สามารถรับประกันได้ว่าการรันแอพพลิเคชั่นเดียวกันบน 2 เครื่องจะให้ประสิทธิภาพ เช่น ความเร็ว ได้เท่ากันเสมอไป
- นอกจากการใช้ communication path ร่วมกันแล้ว แต่ละส่วนการประมวลผลยังใช้ shared memory pool ร่วมกันอีกด้วย ทำให้แชร์ข้อมูลร่วมกันได้สะดวก ต่างจากฮาร์ดแวร์แบบเดิมๆ ที่ข้อมูลต้องวิ่งผ่าน bus บนเมนบอร์ดก่อน
- ในการประมวลผลอัลกอริธึมด้าน machine learning นั้น การแลกเปลี่ยนข้อมูลกันระหว่าง CPU กับ GPU ถือเป็นเรื่องสำคัญคอขาดบาดตายมากๆ เพราะมีผลต่อ latency มาก หาก latency สูง ก็จะเกิดคอขวด ทำให้การประมวลผลระหว่าง CPU กับ GPU จะช้าไปด้วย
- ยิ่งข้อมูลมีขนาดใหญ่ หากต้องรับ/ส่งกันผ่าน bus บนเมนบอร์ดแบบฮาร์ดแวร์แบบเดิมๆ ก็จะยิ่งช้า และหากรับ/ส่งข้อมูลไปมากันบ่อยๆ จะยิ่งใช้พลังงานมาก ส่งผลให้ใช้ไฟมากขึ้น หากเป็นโน้ตบุ๊กก็จะกินไฟจากแบตเตอรี่มากนั่นเอง
- แนวคิดของ pool คือการรวมทรัพยากรที่ใช้ร่วมกันและเข้าถึงบ่อยๆ มาเก็บไว้ที่เดียวกัน ช่วยลด latency จากการ instantiate ข้อมูลเดิมซ้ำๆ บ่อยๆ จึงช่วยเพิ่มความเร็วในการเข้าถึงข้อมูลได้ดี และยังสามารถ จองและจัดสรรปริมาณ ให้เหมาะสมกับปริมาณและความถี่ในการใช้งานโดยแต่ละส่วนการประมวลผล และยังช่วย หมุนเวียนการใช้ทรัพยากร (recycle) ภายใต้ข้อจำกัดของทรัพยากร (resource constraint) อย่างขนาดและปริมาณของฮาร์ดแวร์ที่มีได้อย่างดี
- ยกตัวอย่างเช่น การใช้ object pool ในงานซอฟต์แวร์ เช่น สมมุติระบบพีควันละ 4 ชั่วโมง มี request เข้ามาเฉลี่ย 1,000 request/วินาที ทุก request ต้องใช้อ็อบเจ็คต์ CommonAppService จะทำให้ต้อง instantiate อ็อบเจ็คต์ CommonAppService ถึง 1,000 (request) x 3,600 (วินาที) x 4 (ชั่วโมง) = 14.4 ล้านอ็อบเจ็คต์!!! แต่หากสามารถคุมอัตรา execution time ของรอบการทำงานของแต่ละ request ให้ สามารถคาดการณ์ได้ เช่นไม่เกิน 1 วินาทีแน่ๆ แบบนี้หากเปลี่ยนมาใช้ pool เพื่อเก็บอ็อบเจ็คต์ ก็จะสร้างอ็อบเจ็คต์ CommonAppService อย่างน้อยเพียง 1,000 อ็อบเจ็คต์!!! ก็พอ เพราะเมื่ออ็อบเจ็คต์ใดถูกใช้งานเสร็จก็ไม่จำเป็นต้องลบทิ้ง (ต้องเช็ก state ก่อนนะ) แค่เอาไปเก็บใน pool ต่อ ไม่ต้อง instantiate ใหม่นั่นเอง แต่สร้างแค่พันนึงมันปริ่มๆ ไป ควรสร้างเผื่อๆ ไว้หน่อย จากตัวอย่างดังกล่าว pool ช่วยลดโอเวอร์เฮดในการ instantiate อ็อบเจ็คต์ และหน่วยความจำในการจัดเก็บอ็อบเจ็คต์ได้มหาศาล ใช้ทรัพยากร (หน่วยความจำ, I/O ฯลฯ) น้อยลงมาก
- Apple ยังได้ออกแบบชิป M1 ให้แต่ละส่วนการประมวลผลใช้ memory pool ร่วมกันได้ เปรียบเทียบเช่น แต่ละห้องในบ้านมีตู้เสื้อผ้าเป็นของตัวเองเพื่อเก็บเสื้อผ้าของแต่ละคนเอง แต่ก็แชร์ตู้เย็นในห้องครัวร่วมกันได้ เช่น การแชร์ข้อมูลร่วมกันระหว่าง CPU กับ GPU ในชิป M1
- เมื่อความเร็วโดยรวมในการประมวลผลรวดเร็วปรู๊ดปร๊าดขึ้นมากๆๆๆ ข้อมูลที่วิ่งไปมาระหว่างแต่ละส่วนก็รวดเร็วมหาศาล เปรียบเสมือนน้ำป่าไหลบ่ามารวดเร็ว เพื่อไม่ให้น้ำท่วม ก็ต้องมีแก้มลิงเอาไว้พักน้ำ ไม่อย่างนั้นอาจเกิด missed rate ในการประมวลผลสูงได้ นี่จึงเป็นที่มาของการมี shared cache เพื่อให้แต่ละส่วนใช้ ‘แก้มลิง’ ร่วมกัน ไม่ต้องแยกกันมี cache (แคช) เป็นของตนเองแบบฮาร์ดแวร์แบบเดิมๆ ที่ CPU ก็มี cache เป็นของตนเอง, GPU ก็มี cache เป็นของตนเอง, RAM ก็ยังมี cache เป็นของตนเองอีก อย่างนี้ก็เปลืองสิ เปลืองทั้งการประมวลผลเพื่อจัดการ cache เปลืองทั้งการใช้พลังงาน แล้วฮาร์ดแวร์แต่ละรุ่นยังมีขนาดและความเร็วของ cache แตกต่างกันอีก การคุม latency และความเสถียรจึงยาก
- แนวคิดของ cache คือการเป็น buffer เพื่อพักข้อมูลชั่วคราว ให้นึกถึงการบวกเลข หากบวกกันแค่ 2 จำนวน เราอาจคิดในใจได้ แต่หากต้องบวกกัน 20 จำนวนอาจต้องพึ่งกระดาษทดเลข ซึ่งเจ้ากระดาษทดเลขนี้ก็คือ cache นั่นเอง
- การออกแบบแต่ละส่วนการประมวลผลให้ทำงานแยกอิสระกัน เปรียบแล้วเหมือนกับห้องต่างๆ ในบ้านหลังเดียวกัน ที่แชร์บันไดร่วมกัน แชร์ท่อประปาและไฟฟ้าร่วมกัน แชร์ห้องครัวร่วมกัน แชร์ที่จอดรถร่วมกัน แชร์สวนร่วมกัน ขณะที่แต่ละห้องสามารถตกแต่งภายในเป็นอิสระจากกันได้ การพัฒนาเพื่อเพิ่มประสิทธิภาพหรือ customize การประมวลผลแต่ละส่วนจึงเป็นอิสระกัน เพียงแค่ยึด interface เดิมที่แชร์ใช้ร่วมกันกับส่วนอื่นๆ ไว้เหมือนเดิม เป็นการคุม governance ระหว่างส่วนการประมวลผลให้ดี เปิดโอกาสให้เกิด intrinsic modification ภายในแต่ละส่วนได้
- เมื่อ Apple สามารถออกแบบชิปที่รวบการประมวลผลสำคัญๆ มาไว้ด้วยกัน จึงส่งเสริม product line architecture เพื่อช่วยให้ลดต้นทุนทั้งค่าใช้จ่ายและเวลาในการผลิตผลิตภัณฑ์หลายชิ้นที่ Apple วางแผนจะใช้ชิป M1 ได้ ทำให้ควบคุม stability + variability + compatibility หรือเรียกได้ว่า overall hardware control ได้เป็นอย่างดี แน่นอนเมื่อคุมได้เบ็ดเสร็จขนาดนี้ ในแง่ customer support, technical support, sales support ก็จะง่ายสะดวกและประหยัดขึ้น การออกแบบและผลิตผลิตภัณฑ์ใหม่ๆ ที่จะใช้ชิป M1 ก็จะใช้เวลาน้อยลง เพราะลดการพึ่งพาฮาร์ดแวร์จากผู้ผลิตรายอื่นลง นี่จึงส่งผลต่อราคาผลิตภัณฑ์ที่ใช้ชิป M1 มีราคาถูกลงไปด้วย
- Apple เพียงทุ่มเทออกแบบสถาปัตยกรรมชิป M1 กำหนดสเป๊กของแต่ละส่วนการประมวลผล แต่… Apple ไม่จำเป็นต้องเสียเวลาและงบประมาณค้นคว้าวิจัยและผลิตฮาร์ดแวร์แต่ละส่วนเองเลย เพียงแค่ซื้อสิทธิบัตรแล้วว่าจ้างผลิต แล้วเน้นคุมสเป๊ก คุมภาพรวม คุมการทำงานร่วมกัน นี่เป็นตัวอย่างที่ดีมากๆ ในด้าน agile product development โดยการมุ่งเน้นไปที่ ‘การออกแบบและคุมสถาปัตยกรรม‘
- หนึ่งในหัวใจของ architecture คือ business กับ IT ต้อง align กัน ต้องเดินไปด้วยกัน