บทที่ 9
การจัดการของ Processor (Processor Organization)
งานที่ Processor ต้องทำก็คือ
1. Fetch
Instructions : CPU จะต้องอ่านคำสั่งจากหน่วยความจำ
2. Interpret
Instructions : คำสั่งที่อ่านมาจะถูก decode หรือแปลว่าจะทำอะไร
3. Fetch
Data : อ่านข้อมูลจากหน่วยความจำ หรือ จาก I/O module เพื่อใช้ในการ execute คำสั่ง
4. Process
Data : ต้องการการทำงานของ ALU เช่น
การทำบวกลบคูณหาร หรือการเปรียบเทียบทางลอจิกต่าง ๆ
5. Write
Data : ผลจากการ execute จะต้องบันทึกไว้ที่หน่วยความจำหรือ
I/O module
พิจารณารูปของ
CPU และ System bus
เราคงจำกันได้ว่า
ส่วนประกอบหลักของ CPU คือ ALU, CU และ
Register โดย ALU
จะทำงานด้านการประมวลผล CU ทำหน้าที่ควบคุมการเคลื่อนไหวของข้อมูล
และคำสั่งทีจะเข้าหรือออก CPU นอกจากนี้ใน CPU ยังต้องการหน่วยความจำภายในสำหรับที่จะเก็บพักข้อมูลชั่วคราว จะเห็นว่า CPU
จะเชื่อมต่อกับระบบภายนอกด้วย System Bus ต่าง
ๆ และภายใน CPU เองก็จะติดต่อกันด้วย Internal CPU Bus
เช่นกัน
พิจารณารูปที่แสดงองค์ประกอบภายใน CPU เส้นทางการเคลื่อนย้ายข้อมูลและเส้นทางการควบคุมของลอจิกจะถูกกำหนดขึ้น
รวมไปถึงส่วนที่เรียกว่า Internal CPU Bus ซึ่งจำเป็นสำหรับการ
transfer ข้อมูลระหว่าง Register และ ALU
การจัดการของ Register (Register Organization)
ภายใน CPU นั้นจะมีกลุ่มของ register ที่แบ่งประเภทตามการทำงานดังนี้คือ
1. User-Visible
Registers : เป็น register ที่โปรแกรมเมอร์รับรู้
และนำไปใช้ในการเขียนโปรแกรมภาษาเครื่อง หรือภาษาแอสเซมบลี้ได้
2. Control
and Status Register : เป็น
register ที่ถูกใช้โดย CU เพื่อควบคุมการทำงานของ
CPU และกำหนดสิทธิในการครอบครอง CPU
ในที่นี้เราจะพิจารณาถึง
Control และ Status Register ซึ่งเป็น register ที่ผู้เขียนโปรแกรมทั่วไปไม่สามารถจะใช้ได้ มันจะถูกไช้
โดย คำสั่งของเครื่อง ซึ่งจะถูก execute ในขั้นตอนการทำงานของระบบปฏิบัติการเท่านั้น
อย่างไรก็ตามในเครื่องที่แตกต่างกันก็จะมีการจัดการ register ที่แตกต่างกันด้วย อย่างไรก็ดีเราสามารถแบ่งประเภทของ register ออกเป็น 4 register ที่จำเป็นสำหรับการ execute
คำสั่งดังนี้คือ
Program
Counter (PC) : เก็บ address ของคำสั่งที่จะถูก
fetch ต่อไป
Instruction
Register (IR) : เก็บคำสั่งที่ถูก fetch มา
Memory
Address Register (MAR) : เก็บตำแหน่ง หรือ address ของหน่วยความจำ
Memory
Buffer Register (MBR) : เก็บข้อมูลทีจะเชียนลงหน่วยความจำหรือข้อมูลที่อ่านมาจากหน่วยความจำ
ซึ่ง MAR จะต้องต่อโดยตรงเข้ากับ address
bus และ MBr ก็จะต้องต่อตรงเข้ากับ data
bus
นอกจากนี้ CPU ทุกตัวจะต้องมี register ที่ชื่อว่า Program Status Word (PSW) ที่เก็บสถานะของข้อมูลหรือตัวแปร
ณ ขณะนั้นเช่น
Sign : เก็บ sign bit ของผลลัพธ์ในการประมวลผลครั้งล่าสุด
Zero : จะถูก Set เมื่อผลลัพธ์ของการประมวลผลเป็น 0
Carry : จะถูก set เมื่อ operation เป็นการบวกแล้วได้ผลลัพธ์ที่ต้องทดไปบิตข้างหน้า
หรือจะถูก set เมื่อ operationเป็นการลบแล้วต้องมมีการยืมจากบิตข้างหน้ามา
Equal : จะถูก set เมื่อผลของการเปรียบเทียบระหว่างตัวแปร 2 ตัวเท่ากัน
Overflow
: ใช้ในกรณีที่มีการทำคำนวณต่าง ๆ แล้วเกิด overflow ขึ้น
Interrupt
Enable/Disable : ใช้สำหรับกำหนดว่ายอมหรือไม่ยอมให้ interrupt
Supervisor
: ระบุว่าจะให้ CPU execute คำสั่งในส่วนของผุ้ควบคุมระบบ
(supervisor) หรือ ผู้ใช้ (user) หรือเป็นการกำหนดสิทธิในการใช้
CPU นั่นเอง
The Instruction Cycle
การทำงานหลัก
ๆ ของ instruction cycle นั้นจะมีอยู่ 3 ส่วนคือ
Fetch : คืออ่านคำสั่งถัดไปจากหน่วยความจำเข้ามาใน CPU
Execute :
แปลความหมายของ op code และทำงานตาม operation
ที่กำหนด
Interrupt
: ถ้ายินยอมให้เกิดการ interrupt และเกิดการ interrupt
ขึ้น จะต้องเก็บสถานะต่าง ๆ ของ process ปัจจุบันไว้
และให้บริการการ interrupt นั้น ดังรูป
ทิศทางการไหลของข้อมูล
(Data Flow )
ในขณะวงจรการ fetch (fetch cycle) ทำงาน
คำสั่งจะถูกอ่านจากหน่วยความจำ PC จะเก็บ address ของคำสั่งถัดไปที่จะถูก fetch และ address นี้จะถูกย้ายไปที่ MAR และวางมันไปบน address
bus CU จะ request การอ่านข้อมูลกับหน่วยความจำ และหน่วยความจำจะวางข้อมูลที่ต้องการลงบน data
bus และ MBR จากนั้นมันจะถูกย้ายไปที่ IR
ซึ่งเป็นขณะเดียวกับที่ PC จะถูกเพิ่มค่าขึ้น
1 เพื่อเตรียม address ถัดไปที่จะ fetch
นั่นเอง (พิจารณารูป Data Flow , Fetch Cycle ประกอบ)
เมื่อเสร็จสิ้นกระบวนการ fetch CU จะตรวจสอบข้อมูลหรือเนื้อความที่อยู่ใน
IR ว่ามีการใช้ตัวแปรที่มีการอ้างถึงแบบได (,มี Addressing mode แบบไหน)
ถ้าหากว่ามีการอ้างถึงแบบ Indirect Addressing จะต้องมีการเรียก
Indirect Cycle มาทำงาน (พิจารณารูปภาพประกอบ) บิตขวาสุด
N บิตของ MBR ซึ่งระบุ address
ที่อ้างถึง จะถูก transfer ไปที่ MAR จากนั้น CU ก็จะ request หน่วยความจำเพื่อขอข้อมูล
และเอา address ของ operand นั้นมาไว้ที่
MBR
ถ้าเกิดกรณีของการ Interrupt ข้อมูลหรือเนื้อความที่อยู่ใน
PC ขณะนั้นจะถูกเก็บไว้ในที่ CPU สามารถจะเรียกกลับมาได้หลังเสร็จสิ้นการ
interrupt แล้ว นั่นคือมันจะถูกย้ายไปเก็บไว้ที่ MBR เพื่อที่จะเขียนลงไปในหน่วยความจำ CU จะทำหน้าที่ในการ
load หน่วยความจำส่วนที่ถูกจองไว้สำหรับการ interrupt
เช้ามาใน MAR เช่น ถ้าเป็นลักษณะของ stack pointer address ของ interrupt
routine จะถูก load เข้าไปใน PC ทำให้ instruction cycle ถัดไปจะเริ่มขึ้นด้วยการ fetch คำสั่งใน address
ที่ระบุโดยเฉพาะจากการ interrupt
Pipeline & Superscalar
เราคงเคยสงสัยว่า
ทำไมราคาและประสิทธิภาพของ CPU ต่างรุ่นกันที่ความเร็วเดียวกัน ถึงได้แตกต่างกัน เช่น ทำไม Pentium
Classic 100 MHz ถึงได้มีราคาแพงกว่า และ ประสิทธิภาพสูงว่า
เมื่อเทียบกับ 486DX4-100 MHz ทั้งๆที่ต่างก็มีความเร็วเท่าๆ
กัน คือ 100 MHz หรือ แม้แต่ Pentium II 233 MHz ทำไมถึงได้แพง และ ประสิทธิภาพสูงกว่า Pentium MMX 233 MHz ทั้งๆ ที่ต่างก็มี MMX เหมือนๆกัน ใช้ FSB เท่ากัน คือ 66 MHz และ ต่างก็มี ความเร็วเป็น 233
MHz เช่นกัน จะเป็นไปได้ไหม ถ้าสามารถทำให้ 486 ทำงานได้ที่ 500 MHz มันจะมีประสิทธิภาพเทียบเท่ากับ
Pentium III 500 MHz
นับวันๆ
ตลาดการแข่งขันของ CPU ก็รุนแรงขึ้น ซึ่งแต่ละบริษัท
แต่ละฝ่าย ต่างก็เร่งนำ CPU รุ่นใหม่ๆ ของตนออกสู่ท้องตลาด
ให้เร็วขึ้น ซึ่ง แน่นอน การที่จะออก CPU รุ่นใหม่ๆ
ออกมาได้นั้น ผู้ออกแบบ ก็ต้องคำนึงถึงความเข้ากันได้ กับ CPU รุ่นก่อนด้วย ซึ่ง CPU รุ่นใหม่ๆ
ก็ควรที่จะทำงานด้วยคำสั่ง ( Instruction ) ต่างๆ ของ CPU
รุ่นก่อนหน้านี้ได้ด้วย มิฉะนั้นแล้ว ก็เหมือนเป็นการ ฆ่าตัวตาย
เพราะ หากไม่เข้ากันกับรุ่นก่อนแล้ว การที่ผู้ซื้อจะพิจารณาซื้อ CPU รุ่นใหม่เพื่อ upgrade รุ่นเดิมของตน ก็เป็นไปได้ยาก
นับตั้งแต่ปี
1989 ที่ Intel ได้ประกาศตัว
80486 ซึ่งเป็น Processor 32 Bit ก็ได้ทำการเปิดตัว
pipeline x86 CPU ด้วย โดย Pipeline นั้น
จะทำให้สามารถทำงานได้หลายๆ คำสั่งในเวลาเดียวกันได้ ทำให้ประสิทธิภาพนั้นสูงขึ้น
ซึ่งต่อมา ในปี ก็ได้ 1993 ก็ได้เปิดตัว CPU ในยุคที่ 5 ของตน นั่นก็คือ Intel Pentium ซึ่งก็ได้นำเอา pipeline มาใส่ไว้ใน CPU ของตนด้วยกันถึง 2 pipeline ( ใน 486 มีเพียง 1 pipeline )
หลักสำคัญในการออกแบบ
Pentium เพื่อให้มีความเข้ากันได้ย้อนหลัง
และ ยังทำให้ได้ความเร็วที่สูงขึ้น ก็คือ การจับเอา CPU 2
ตัวเข้ามาไว้ในตัวเดียวกัน และ ให้ทำงานแบบขนานไปพร้อมๆกัน โดยไม่ขึ้นต่อกัน ทำให้
Pentium นั้น สามารถทำงานได้ 2
คำสั่งในเวลาเดียวกันพร้อมๆกัน ( ก็คือ 2 pipeline ) นั่นเอง
โดยใช้เรียกสถาปัตยกรรมนี้ว่า Superscalar
Pipeline
ก่อนจะอธิบายถึงเรื่อง
Pipeline ให้ลองนึกว่า ถ้ามีคน 5 คน ช่วยกันทำงาน ถ้ามีงานมา แล้วให้ทั้ง 5
คนช่วยกันทำทั้งหมดเลย กับ แบ่งงานออกเป็นส่วนย่อยๆ แล้วแต่ละคน
ก็รับงานไปทำคนละส่วน อย่างไหนน่าจะมีประสิทธิภาพมากกว่ากัน? ถ้าให้คนหนึ่งคอยรับงาน แล้วส่งต่อให้อีกคนคอยจัดการรายละเอียดของงาน
แล้วอีก 2 คนทำงานที่ได้รับ
คนสุดท้ายคอยรอผลลัพธ์มาเขียนสรุป เมื่อคนรับงานส่งต่อให้คนจัดการรายละเอียดแล้ว
ก็ว่าง และ ก็พร้อมที่จะรับงานใหม่ ในขณะที่ เมื่อคนที่สองส่งงานให้อีก 2 คนจัดการทำงานให้ ตนก็จะว่างพร้อมที่จะรับงานใหม่จากคนแรก หรือ เมื่อ 2 คนที่คอยเป็นผู้ทำงานให้ ทำงานเสร็จและส่งต่อให้คนสุดท้ายเขียนผลลัพธ์ส่ง
แล้ว ทั้งคู่ ก็จะว่าง รอรับงานต่อจากคนที่ 2 ได้ต่อไป หลักการดังกล่าว ก็เอามาใช้กับ CPU โดยการแบ่ง CPU ออกเป็นหน่วยย่อยต่างๆ
เพื่อให้ทำหน้าที่แตกต่างกัน นี่คือจุดเริ่มต้นของ Pipeline
Pipeline นั้นเดิมทีเป็นเทคนิคของสถาปัตยกรรมแบบ
RISC แต่ต่อๆ มา ก็ได้นำมาใช้กับสถาปัตยกรรมแบบ CISC ซึ่งการทำงานของมัน ก็คือ
จะสามารถรับงานใหม่ได้ในขณะที่ยังคงทำงานเก่าต่อไปได้ด้วย เพราะมีการแบ่งงานกันทำ
กล่าวคือแบ่ง CPU ออกเป็นส่วนย่อยๆ แล้วแบ่งงาน กันรับผิดชอบ
โดยจะแบ่งเป็นภาคหลักๆ คือ ภาครับคำสั่ง ภาคการถอดรหัส ภาคการรับข้อมูล
ภาคประมวลผล และ ภาคเขียนข้อมูลกลับ ซึ่งคล้ายๆกับกระบวนการผลิตในโรงงานอุตสาหกรรม
เรียกสถาปัตยกรรมนี้ว่า CPU Pipeline ซึ่ง ผู้ผลิต CPU
บางเจ้า ก็ได้แบ่งซอยช่วง ของ Pipeline ออกไปเป็นขั้นตอนย่อยๆ
ต่างๆกัน แต่โดยรวมแล้ว ก็ยังคงมีขั้นตอนหลักๆ อยู่ 5 ขั้น (
หรือจะมองให้เล็กลงเหลือเพียงแค่ 3 ขึ้น ก็ได้ ) ดังนี้
•Instruction Fetch หรือ ภาครับคำสั่ง
จะทำหน้าที่รับคำสั่งใหม่ๆ ทั้งจากหน่วยความจำหลัก หรือจากใน Instruction
Cache เข้ามา เพื่อส่งต่อให้ภาคต่อไปจัดการต่อ
•Instruction Decode หรือ ภาคการแปลคำสั่ง
คือ จะทำหน้าที่แยกแยะคำสั่งต่างๆ ของ CISC ซึ่งในตอนที่แล้ว
เราทราบแล้วว่า CISC นั้น ในแต่ละคำสั่ง
จะมีขนาดที่ไม่แน่นอน ตรงส่วนนี้ก็จะทำการซอยคำสั่งนั้นเป็นคำสั่งย่อยๆ
ให้มีความยาวเท่าๆกัน ในลักษณะเช่นเดียวกับ RISC เรียกคำสั่งย่อยๆ
นั้นว่า Micro Operation
•Get Operands หรือ ภาครับข้อมูล คือ
รับข้อมูลที่จะใช้ในการประมวลผลเข้ามาเก็บไว้ เช่นจากขั้นตอนที่ 2 เรารู้ว่าจะใช้การ "บวก" ก็ต้องรับค่าที่จะใช้ในการบวก
มาด้วยอีก 2 ค่า บางทีขั้นตอนนี้ ก็ถูกรวมเข้ากับขั้นตอนที่ 2
•Execute หรือ ภาคประมวลผล
เป็นขั้นตอนที่ทำการประมวลผลตามคำสั่งและ operand ที่ได้รับมาจากขั้นที่
2 และ 3 ซึ่ง ถ้าให้ขั้นที่ 2 เป็นการถอดรหัสว่าเป็นการบวก ขั้นที่ 3
รับค่าที่จะบวก ขั้นนี้ ( ขั้นที่ 4 ) ก็จะทำการบวกให้ได้ผลลัพธ์ออกมา
•Write Result หรือ ภาคการเขียนข้อมูลกลับ
เมื่อทำการประมวลผลเสร็จสิ้น ผลลัพธ์ที่ได้ก็จะนำไปเก็บไว้ใน register หรือ ใน Data Cache ซึ่งบางที ขั้นตอนนี้
ก็ถูกมองรวมไว้กับขั้นที่ 4
หรืออาจมีการรวบขั้นตอนทั้ง
5 ดังกล่าว ให้เหลือเพียงแค่ 3 ขั้นตอนคือ Instruction
Fetch , Instruction Decode และ Execute เท่านั้น
แต่ก็ยังคงหลักสำคัญเดิมอยู่
การทำงาน
( ทั้งทางทฤษฎี และ ทางปฏิบัติจริง ) ของ Pipeline
จะเป็นดังรูป
เมื่อภาครับคำสั่ง
รับคำสั่งมา ก็จะทำการส่งต่อให้ ภาคแปลคำสั่ง เมื่อส่งต่อให้ แล้ว
ก็ทำการรับคำสั่งถัดไปทันที และ เมื่อ ภาคแปลคำสั่งได้รับคำสั่ง ก็จะทำการแปล และ
แยกแยะคำสั่ง แล้วส่งต่อให้ภาครับข้อมูลต่อไป เป็นทอดๆ
ซึ่งทำให้สามารถทำงานได้หลายๆ คำสั่งในขณะเวลาเดียวกัน แต่ในความเป็นจริงนั้น
ช่วงเวลาบางช่วงอาจยาวเกินช่วงอื่นๆได้ โดยเฉพาะช่วงของการประมวลผล
ซึ่งอาจนานกว่าช่วงอื่นๆ เป็นเท่าตัว ทำให้เกิดช่วงของการรอ ( Wait State ) ได้
ซึ่งก็อาจทำให้การทำงานช้าลงไปเล็กน้อย
ลักษณะของคำสั่งที่ทำให้
Pipeline นั้นทำงานได้เต็มประสิทธิภาพ
ก็คือคำสั่งที่จะทำงานในแต่ละคำสั่งนั้น
ไม่ขึ้นต่อกันและไม่รอค่าของคำสั่งก่อนหน้าเพื่อมาเป็น Input ของคำสั่งที่กำลังดำเนินการ
ซึ่งลักษณะของคำสั่งที่ทำให้ได้ผลไม่เต็มประสิทธิภาพนั้นจะเป็นดังนี้
ยกตัวอย่างให้
คำสั่งที่
1 : A = 5
คำสั่งที่
2 : B = A + 3
จะเห็นได้ว่า
คำสั่งที่ 2 นั้นจะไม่สามารถทำต่อไปได้เลย
เพราะต้องรอผลลัพธ์ ( ของการกำหนดค่าให้กับ A ) เสียก่อน
ซึ่งช่วงการรอ ( Wait State ) จะอยู่ในช่วงของการรับข้อมูล (
Get Operands ) ซึ่งจะต้องรอจนกระทั่ง
คำสั่งแรกทำเสร็จสิ้นเสียก่อน จนถึงขึ้น Write Result เสียก่อน
จึงจะสามารถทำงานต่อไปได้ ดังรูป
แต่ถึงอย่างไร
ก็ตาม แม้ว่าจะทำไม่ได้เต็มประสิทธิภาพนัก แต่การทำงานแบบ Pipeline ก็ทำให้มีประสิทธิภาพสูงขึ้นและเร็วขึ้นกว่าแบบที่ไม่มี
Pipeline อยู่ดี
ต่อมา
ได้มีการพัฒนาเรื่องการส่งต่อข้อมูล หรือที่เรียกว่า Data Forwarding ขึ้น
ซึ่งลักษณะการทำงานจะช่วยลดขั้นตอนของตัวอย่างข้างต้น กล่าวคือ ในบางครั้ง
ผลลัพธ์ของคำสั่งหนึ่งๆ จะไปเป็น Operand ของคำสั่งถัดไป
การส่งต่อข้อมูลจะทำการเก็บผลลัพธ์ที่ได้จากคำสั่งนั้นๆไว้
ให้พร้อมใช้งานในคำสั่งถัดไปได้ ทำให้ประหยัดขั้นตอนในการรับข้อมูล ( Get
Operand ) ลงได้
Superscalar
คราวนี้เรามาดูในส่วนของ
Superscalar กันบ้าง ถ้า Pipeline นั้นคือการทำงานให้แต่ละคำสั่งนั้นคาบเกี่ยวกัน ( Overlap )คือสามารถรับคำสั่งถัดไปได้ ในขณะที่กำลังทำงานในคำสั่งใดๆ อยู่ Superscalar
นั้น ก็คือ จะทำงานพร้อมๆกันไปเลย หลายๆคำสั่ง ซึ่งจะนำเอา Pipeline
หลายๆ Pipeline มาทำงานขนานกันไป ดังรูป
สรุปความง่ายๆ
ก็คือ CPU ใดๆ ที่มี Pipeline มากกว่า 1 Pipeline ใน CPU นั้นๆ
จะเรียก CPU นั้นๆว่าเป็น CPU แบบ Superscalar สถาปัตยกรรมแบบ Superscalar
นั้นได้ถูกนำมาใช้บน CISC เป็นครั้งแรก กับ Intel
Pentium ( Classic ) ซึ่งมี Pipeline อยู่ 2
Pipeline กล่าวคือ สามารถทำงาน 2
คำสั่งได้พร้อมๆกัน แบบ อัตโนมัติ เมื่อรับคำสั่งจากโปรแกรมใดๆ มาแล้ว
ก็จะทำการแยกคำสั่งนั้นๆ ไปให้กับ Pipeline ทั้งคู่ (
ซึ่งเรียกว่า U-Pipeline และ V-Pipeline ) ถึงแม้ว่าจะแยกคำสั่งออกได้ไม่ทั้งหมด เพราะยังมีการรอค่า
หรือมีความเชื่อมโยงภายในของโปรแกรมอยู่
แต่มันก็จะพยายามแยกออกให้ได้มากที่สุดเท่าที่จะได้
โปรแกรมบางชนิดที่บอกว่า
Optimize for Pentium ก็คือมีการปรับแต่งคำสั่งให้ใช้ความสามารถของ
Pipeline ได้อย่างเต็มประสิทธิภาพ รวมถึงสามารถแยกการทำงาน
ออกเป็นคู่ เพื่อให้ แยกการทำงานของ U-Pipeline และ V-Pipeline
ได้อีกด้วย ซึ่งถึงแม้ว่าโปรแกรมเหล่านี้จะสามารถทำงานได้บน 486 แต่ประสิทธิภาพและความเร็วที่ได้ ก็จะด้อยกว่า ทำงานบน Pentium อยู่มาก เพราะ 486 มีเพียง Pipeline เดียว
เราอาจมีความคิดว่าถ้าเพิ่มจำนวน
Pipeline เข้าไปมากๆ
การทำงานก็จะยิ่งเร็วมากขึ้นหรือไม่ แต่จากการทดสอบแล้ว ถึงแม้ว่าจะมี Pipeline
เพิ่มขึ้นมาเป็น 3 หรือ 4 Pipeline แต่ก็ใช่ว่า จะทำให้ได้ความสามารถเป็นเท่าจากของเดิม ( ที่มี 2
Pipeline ) เนื่องจากคำสั่งแต่ละคำสั่งนั้นยังมีความเชื่อมโยงกันอยู่
ยังคงต้องรอค่าจากคำสั่งก่อนหน้าเพื่อนำมาประมวลผลในคำสั่งถัดไปอยู่
ถึงแม้จะมีหลายๆ Pipeline ก็เร็วขึ้นได้ไม่เกินเท่าตัวจากเดิมแน่ๆ
แต่ถึงอย่างไรก็ตาม CPU รุ่นใหม่ๆ ที่ออกมา ก็มีจำนวนของ Pipeline
มากกว่า 2 เพราะโปรแกรมใหม่ๆ จะ support
การทำงานนี้แทบทั้งหมด
Out-Of-Order Execution
จากเรื่องของ
Pipeline และ Superscalar ในหัวข้อที่แล้ว ทั้ง 2 วิธีนั้น
ก็ทำให้เราใช้ประสิทธิภาพของ CPU ได้สูงขึ้น
แต่ยังมีอีกวิธีหนึ่ง ซึ่งเมื่อนำมาใช้ กับทั้ง 2
กระบวนการนี้แล้ว ก็จะทำให้ยิ่งมีประสิทธิภาพมากขึ้นไปอีก จนแทบจะเรียกได้ว่า Peak
Performance ( ประสิทธิภาพขั้นสุด ) ของ CPU เลยทีเดียวละครับ
ซึ่งวิธีนั้น ก็คือ Out Of Order Execution ( OOO ) หรือ
การประมวลผลแบบไม่เรียงลำดับขั้น
การทำงานแบบ
Pipeline นั้น ถ้าใช้ OOO ควบคู่ไปด้วย ก็จะช่วยลดช่วงของการรอคอย ทั้งรอค่า และ รอ register
ในการประมวลผล ซึ่งก็ช่วยให้เข้าใกล้กับ Peak Performance เข้าไปอีก
พิจารณาตัวอย่างต่อไปนี้
A = 5
B = 4
C = A + B
D = 3
จากชุดคำสั่งดังกล่าว
ถ้าเรามามองดูในการทำงานของมัน ในแบบ Pipeline
และ การทำงานเป็นตามลำดับขั้นของมันเลย ซึ่งเรียกว่า In-Order
Execution จะได้ผลดังนี้
จะเห็นว่า
ในช่วงของ C=A+B นั้น จะต้องรอผลจากทั้ง คำสั่งที่ 1 และ 2 ให้เสร็จสิ้นเสียก่อน
จึงจะนำค่ามาทำการประมวลผลได้ ซึ่งก็จะเสียเวลาไปถึง 4
ช่วงสัญญาณนาฬิกาเลยทีเดียว โดยที่ไม่ได้ทำอะไร นอกจากรอค่าอย่างเดียว
และยังดึงให้คำสั่งที่ 4 ต้องรอตามไปด้วย เพราะคำสั่งที่ 3 ได้จองส่วนของภาครับค่าไว้แล้ว ทำให้เสียเวลาไปแบบเปล่าๆ ประโยชน์
หากว่าตรงจุดนี้
CPU สามารถแยกแยะการทำงานออก และ
สามารถทำงานในขั้นตอนที่ 4 ก่อนที่จะทำขั้นที่ 3 ดังรูป
เห็นว่า
ช่วยลดการรอคอยลงได้อีก. และในความเป็นจริง ในช่วงของการทำงาน ( Execute ) ของแต่ละคำสั่ง
ก็จะมีช่วงเวลาที่ไม่เท่ากัน ... จากตัวอย่างข้างต้น ถ้าเราแก้ไขใหม่ ให้เป็น
A = 5
B = 4
C = A + B
D = 3
และกำหนดว่า การกำหนดค่า
ใช้เวลา 1 รอบสัญญาณนาฬิกา
การบวกค่า ใช้เวลา 2 รอบสัญญาณนาฬิกา
ผลการทำงานทั้งในแบบ
In-Order และ Out-Of-Order จะเป็นดังนี้
จะเห็นได้ว่าช่วงของการรอนั้นหายไป
และสามารถใช้ประสิทธิภาพของ CPU ได้แทบจะเต็มที่ สำหรับ OOO นั้นเราก็สามารถแบ่งได้เป็น
2 แบบ ...
แบบแรกนั้น
ขณะที่ FPU กำลังทำงานวุ่นๆ อยู่ CPU ก็จะเริ่มการทำงานในชุดคำสั่ง
ถัดไปทันทีแต่หันไปใช้คำสั่งที่ไม่เกี่ยวกับการทำงานของ FPU เช่น
บวกเลขจำนวนเต็ม ( Interger Add ) เพื่อทำให้แต่ละ Unit
ของ CPU ทำงาน โดยไม่อยู่ว่างๆ ... เรียกว่า Type
I
แบบที่ 2 นั้น เมื่อผลการประมวลผลใดๆ
ต้องรอผลจากคำสั่งอื่นๆก่อน ( อย่างเช่นจากตัวอย่างข้างต้น ) CPU ก็จะตัดสินใจทำคำสั่งอื่น ก่อนเลย ... ดังนั้นจะเห็นได้จากตัวอย่างข้างต้น
... ซึ่งจะเรียกว่าเป็น Type II
การทำงานของ
OOO ใน CPU แต่ละยี่ห้อ
• OOO ใน Intel P6 ( Pentium Pro,
Pentium II, Celeron, Pentium III, Xeon )
ในสายของ
P6 ก็ได้รวมการทำงานแบบ OOO เข้าไว้ใน Pipeline ของตนด้วย
ซึ่งหลักการทำงานคร่าวๆ ก็มี ดังรูป
โดยในขั้นแรกนั้น
ชุดคำสั่งจะถูกเก็บไว้ในส่วนของ Re-Order
Buffer เพื่อทำการจัดเรียงชุดคำสั่งเสียใหม่ ซึ่งใน Buffer นี้ก็สามารถจุชุดคำสั่งได้มากถึง 40 ชุดคำสั่ง
และหลังจากนั้น คำสั่งต่างๆก็จะถูกส่งไปที่ Reservation Station หรือ เรียกอีกชื่อหนึ่งได้ว่า เป็น Scheduler ซึ่งเหมือนเป็นผู้กำหนดตารางการทำงานให้แต่ละคำสั่งอีกทีหนึ่ง
แล้วหลังจากนั้นจึงส่งต่อให้กับแต่ละ Unit การทำงานต่อไป
(
ในรูปจะเขียนไว้เพียง 3 Unit แต่จริงๆ
แล้วจะมีมากกว่านั้นก็ได้ )
แต่ละคำสั่งที่ถูกส่งมาจาก
Reservation Station นั้นจะต้องวิ่งไปทางใดทางหนึ่ง
ไม่ X ก็ Y และจัด FPU เป็น Unit การทำงานหนึ่ง ซึ่งไม่ได้รับอภิสิทธิ์พิเศษในการทำงานใดๆ ในส่วนของ OOO นั้น
จะอยู่ในช่วงของ Re-Order Buffer และ Reservation
Station โดยที่ OOO ชนิด Type I จะใช้ในส่วนของ Reservation Station และ Type
II จะใช้ ในส่วน Re-Order Buffer
• OOO ใน AMD K6, K6-2, K6-III
AMD K6 ( ซึ่งก็รวมไปถึง K6-2 และ K6-III ) ก็มี OOO ด้วย
แต่ไม่ดีเท่ากับ ในสายของ Intel P6 ซึ่งการทำงานของ OOO
ของ K6 จะเป็นดังนี้
สังเกตุจากรูป
สิ่งที่ต่างจาก ในสายของ Intel P6 ก็คือ FPU จะถูกจับแยกออกจาก Unit ที่ใช้ในการประมวลผลต่างๆ นอกจากนั้นยังไม่มีส่วนของ Re-Order
Buffer และ Reservation Station อีกด้วย
หากแต่รวมการทำงานของทั้ง 2 ส่วนนั้น
เข้าเป็นส่วนเดียวกันเลย เรียกว่าเป็น Scheduler ( ซึ่งการทำงานต่างจาก
Scheduler ของ P6
ถึงแม้จะใช้ชื่อเดียวกัน ) ซึ่งในนี้สามารถจุได้ 24 คำสั่ง
เมื่อ Scheduler ได้รับคำสั่งที่ต้องใช้งาน FPU
ก็จะทำการส่งต่อให้กับ FPU-Buffer ทันที
โดยไม่มีการจัดเรียงคำสั่งเสียใหม่ ( ไม่มีการ Re-Order ) เพราะว่า
FPU ของ K6 นั้นไม่ใช่ Pipeline
ดังนั้น OOO จึงไม่มีการใช้งานในจุดนี้
แต่จะมีการใช้งานในส่วนที่ไม่เกี่ยวกับ FPU แทน OOO นั้น
จะใช้กับคำสั่งพวก MMX , 3Dnow! และ
การจัดการเกี่ยวกับเลขจำนวนเต็ม ซึ่งใช้ OOO ชนิด Type
I เท่านั้น
• OOO ใน K7
สำหรับใน
K7 นั้น มีการใช้ OOO ในแบบ advance มากๆ เพราะนอกจากจะมีส่วนของ Re-Order
Buffer และ Reservation Station แบบ P6 แล้ว ยังเพิ่มส่วนของ Reservation Station ขึ้นมาอีก
1 ส่วน ทำให้มีส่วน Station ถึง 2
Station เลย โดยส่วนแรก ใช้สำหรับ จัดการกับคำสั่งของเลขจำนวนเต็ม
และอีกส่วนหนึ่งใช้สำหรับจัดการกับคำสั่งที่จัดการเกี่ยวกับ FPU, MMX, และ 3DNow! ซึ่งในส่วนของ Re-Order Buffer นั้น ก็สามารถจุได้ถึง 72 คำสั่งเลยทีเดียว และ Flow การทำงานของ K7 เป็นดังนี้
ในส่วนของ
FPU/MMX/3DNow! จะมี Pipeline อยู่ 3 Pipe และ สามารถเก็บคำสั่งไว้ใน Reservation
Station ( Station1 ) ได้ถึง 36 คำสั่ง
และในส่วนของเลขจำนวนเต็ม ( Integer ) ก็จะมี Pipeline
6 Pipe และ สามารถเก็บคำสั่งได้ ที่ Reservation Station (
Station2 ) อีก 15 คำสั่ง
K7 นั้นเรียกได้ว่าใช้ OOO
Execution กับทุกคำสั่งเลยก็ว่าได้ และใช้ทั้ง Type I และ Type II ด้วย ซึ่งจะเห็นได้ว่ามีการใช้งานได้ถึง
9 Pipeline และด้วย ขนาดของ L1 Cache ที่มีขนาดถึง
128K รวมกับ Branch Prediction อีก 2048
entry และยังรวมกับระบบ Bus ที่เร็วๆ อย่าง EV-6
ก็จะยิ่งทำให้ K7 Pipeline นี้
ทำงานอยู่ตลอดเวลา ซึ่งจะทำให้เข้าใกล้ Peak Performance ของ
CPU มากที่สุด
สถาปัตยกรรมคอมพิวเตอร์แบบ
SIMD
งานๆหนึ่ง ถ้าใช้คนงานช่วยกันทำ 1 คน ทำงาน ใช้เวลา 100 หน่วยเวลา แต่หากว่า ให้มีผู้ช่วย มาช่วยทำงานก็จะลดเวลาเหลือเพียง 50 หน่วยเวลา แล้วถ้ามีคนมาช่วยกันทำถึง 100 คน
เวลาที่จะทำงานให้สำเร็จนั้น ก็เหลือเพียงแค่ 1 หน่วยเวลา
... ทฤษฎีนี้ เป็นไปได้ไหม?
จะว่าเป็นไปได้ ก็ใช่ เพราะหลายๆคนช่วยกันทำงานงานก็จะสำเร็จเร็วขึ้น แต่
จะว่าเป็นไปไม่ได้ ก็ใช่เช่นกัน เพราะว่า การทำงานนั้น บางที
ก็ต้องรอผลของอีกขั้นตอนหนึ่งก่อน เพื่อจะมาใช้ในขั้นตอนที่จะทำงานต่อไป
เพราะฉะนั้น ให้ 100 คนทำ ก็อาจทำไม่สำเร็จได้ในเวลาเพียง 1 หน่วยเวลา
แนวความคิดนี้
ก็ถูกนำมาพัฒนาใช้กับการทำงานของการประมวลผลของคอมพิวเตอร์เช่นกัน ... กล่าวคือ
ถ้าหากว่า ถ้าให้ CPU ทำการประมวลผล แบบตามลำดับ คือ ทีละ 1 คำสั่ง เพราะฉะนั้น ถ้ามีข้อมูลมา 100 ชุด
ก็จะใช้เวลา 100 หน่วยเวลา แต่ถ้าหากว่า มีหลายๆ CPU มาช่วยกันทำงานล่ะ ก็น่าจะลดเวลาการทำงานให้เสร็จลงใช่ไหม?
คำตอบก็เหมือนกับการทำงานของคนข้างต้น ... ตัวอย่างเหล่านี้ คือ concept
หรือ แนวคิด ของการทำงาน หรือ การประมวลผลแบบขนาน ซึ่งในคราวนี้
เราจะมาพูดถึงกันในเรื่องของสถาปัตยกรรมแบบ SIMD ซึ่ง ก็จัดเป็นประเภทการประมวลผลแบบขนานแบบหนึ่ง
SIMD หรือ Single Instruction Multiple Data stream หรือ
กล่าวคือ เป็นการประมวลผลแบบที่มีข้อมูลเข้ามาหลายๆ ชุด โดยใช้คำสั่งในการประมวลผล
เพียงชุดคำสั่งเดียว และได้ผลลัพธ์ออกมาหลายๆผล ( เพราะมีหลายชุดข้อมูล )
พิจารณาจากรูป
ถ้าเราต้องการคูณ Matrix A ขนาด 3*3 เข้ากับ Matrix B ขนาด 3*3
เพื่อให้ได้ผลลัพธ์ คือ Matrix C
โดยค่าของ Matrix C นั้นจะได้มาจาก ผลคูณและ
ผลบวกของ Matrix A และ B ดังนี้
c11 =
( a11 * b11 ) + ( a21 * b12 ) + ( a31 * b13 )
ซึ่งก็คือ ค่าของ Matrix C ตัวแรก ( แถวที่ 1 หลักที่ 1 ) นั้น มาจาก ผลบวก ของผลคูณจากแถวที่ 1 ของ Matrix A กับ หลักที่ 1
ของ Matrix B และ ในทำนองเดียวกัน สำหรับค่าของ C ตัวที่สอง ( แถวที่ 1 หลักที่ 2 ) ก็จะมาจาก ผลบวกของผลคูณของแถวที่ 1 ของ Matrix
A กับ หลักที่ 2 ของ Matrix B ดังนี้
c21 =
( a11 * b21 ) + ( a21 * b22 ) + ( a31 * b23 )
ถ้าให้ทำการคูณ Matrix ดังกล่าว
เราจะต้องใช้เวลาในการทำงานเท่าไร ถ้าค่อยๆทำทีละ ชุดข้อมูล และ ชุดคำสั่ง ...
ดูกันง่ายๆ
สำหรับการหาค่า ของ c11 ถ้ากำหนดให้การคูณนั้นใช้เวลาในการประมวลผลคือ 4
หน่วยเวลา และ การบวกเป็น 1 หน่วยเวลา เพราะฉะนั้นการทำงานแบบปกติ หรือ
ทำตามลำดับขั้น ก็จะต้องเสียเวลาในการคูณ 3 ครั้ง ก็คือ a11*b11 และ a21*b12 และ a31*b13
ซึ่งก็จะใช้เวลา ไปทั้งสิ้น 3*4 = 12 หน่วยเวลา และ
ยังต้องเสียการบวกอีก 2 ครั้ง เพราะในการบวก ต้องบวกทีละ 2 ค่า ไม่สามารถบวกครั้งเดียวด้วยค่า 3 ค่าได้
ก็จะเสียเวลาในการบวกอีก 1*2 = 2 หน่วยเวลา เพราะฉะนั้น
ก็จะใช้เวลาในการหาค่าของ c11 ทั้งสิ้น 14 หน่วยเวลา ซึ่งสำหรับ Matrix นี้ เป็น Matrix
ที่มีขนาด 3x3 คือ จะมีสมาชิกทั้งหมด 9 ตัว เพราะฉะนั้น ก็จะใช้เวลาในการหาผลคูณทั้งหมด 9*14 = 126 หน่วยเวลาเลยทีเดียว
ทีนี้เราลองมาดูการประมวลผลของสถาปัตยกรรมแบบ SIMD กันบ้าง
สถาปัตยกรรมแบบนี้นั้น อย่างที่กล่าวมาแล้ว ก็คือ จะสามารถประมวลผล
ด้วยชุดข้อมูลหลายๆชุด ซึ่งไม่เกี่ยวข้องกัน ด้วยคำสั่งเดียวกันได้พร้อมๆกันเลย
เพราะฉะนั้น การคูณก็จะทำได้พร้อมๆกันเลยทั้ง 3 ค่า
คือสามารถหาค่าขอ a11*b11และ a12*b12
และ a31*b13 ได้ในเวลาเดียวกัน เพราะฉะนั้นเวลาที่ใช้
ในการคูณ 3 ค่านี้ ก็คือ 4
หน่วยเวลาเท่านั้น และสำหรับการบวก ก็ยังคงต้องใช้ 2 ครั้ง
เพราะไม่ว่าจะบวกยังไง ก็ไม่สามารถบวกกันทีละ 3 ค่าได้ และ
ที่สำคัญก็คือ 3 ค่านั้น แบ่งกันบวกทีละ 2 ก็ไม่ได้ เพราะฉะนั้น ก็ต้องเสียเวลาอีก 2 ครั้งคือ
1*2 = 2 หน่วยเวลา สรุปก็คือจะใช้เวลาในการหาค่าหนึ่งๆ คือ 4+2
= 6 หน่วยเวลาเท่านั้นเอง และหากเป็นการหาค่าของทั้ง Matrix ทั้ง 9 ตัว ก็สามารถใช้เวลาในการคูณค่าทั้งหมดเพียง 4 เท่านั้น แล้วก็เสียเวลาในการบวก เพียง 2 เท่านั้น
เช่นกันครับ เพราะว่าทำงานด้วยคำสั่งเดียวกัน แต่ต่างชุดข้อมูลกัน และ
ข้อมูลนั้นไม่เกี่ยวเนื่องกัน เพราะฉะนั้น ผลคูณของทั้ง Matrix ก็จะสามารถหามาได้เพียงแค่ 6 หน่วยเวลา เลยด้วยซ้ำ
แต่ในความเป็นจริงนั้น ก็่ใช่ว่าจะสามารถทำได้เช่นนี้จริงๆ เพราะ
การที่จะทำเช่นนี้ได้นั้น ( เช่นจากตัวอย่าง การคูณพร้อมๆกันทีละหลายๆ ตัว )
ก็ต้องใช้หน่วยความจำ และ Register มากๆ ซึ่งแน่นอน CPU
ไม่รองรับถึงขนาดมากๆ เช่นนั้น มันก็จะมี Limit ของมัน ทำให้ผลที่ได้ ก็ไม่ได้ดีถึงระดับตามทฤษฎี จากตัวอย่างข้างต้น
และในบางเรื่องของการทำงาน
ก็ไม่สามารถแสดงประสิทธิภาพออกมาได้อย่างเต็มที่ เช่น Loop ของการบวกค่าที่
ค่าผลลัพธ์ของ Process แรกจะไปเป็น ค่าอินพุทของ Process
ถัดไป ดังนี้
A = B + C และ
D = C + A
ซึ่งจะเห็นได้ว่า จะทำการบวกค่า ทั้งสองค่า พร้อมๆกันไม่ได้แน่ๆ
เนื่องจากว่า D นั้น จะต้องรอผลลัพธ์จาก A เสียก่อน จึงจะหาค่าของ D ได้ ตรงนี้
ก็ทำให้การประมวลผลแบบนี้ ไม่มีความหมาย หรือไม่ช่วยอะไรเลย
จะเห็นไว้ว่าสถาปัตยกรรมแบบนี้มันจะมีประสิทธิภาพมากๆ
โดยเฉพาะเรื่องของการคูณ Matrix ... ซึ่งถ้าดูๆ
ไปแล้วอาจมองไม่เห็นถึงประโยชน์ของการคูณ Matrix แต่จริงๆ
แล้ว เรื่อง Matrix นี่มีการนำมาใช้ในการ Transform รูปภาพกันมาก ทั้งการหมุนภาพ หรือ การย่อ ขยายภาพนั้น
ล้วนแล้วแต่ประยุกต์มาจากเรื่อง Matrix ทั้งนั้น
•SISD
หรือ Single Instruction Single Data stream เป็นการประมวลผลแบบพื้นฐานที่สุด
กล่าวคือ มีชุดข้อมูลเพียงชุดเดียว และ ทำงานด้วยคำสั่งเดียว
•MISD
หรือ Multiple Instruction Single Data stream วิธีนี้ ก็จะเป็นการประมวลผลของชุดข้อมูลเพียงชุดเดียว แต่ว่า ทำกับหลายๆ
คำสั่ง เช่น A+B, A*B, A-B และ A/B เป็นต้น
ซึ่งก็คงไม่มีหรือมีน้อยมากที่จะใช้การประมวลผลแบบนี้ ทำให้สถาปัตยกรรมอันนี้
ไม่มีใครพัฒนา
•MIMD
หรือ Multiple Instruction Multiple Data stream สำหรับวิธีนี้นั้น ก็ดูเหมือนจะแยกกันทำงานได้เลย คือ รับข้อมูลมาหลายๆ
ชุด แล้วก็ทำงานหลายๆ คำสั่ง ไปพร้อมๆกัน
RISC vs. CISC
RISC นั้นเป็นคำย่อ มาจากคำว่า Reduced
Instruction Set Computer ซึ่งก็คือ
เครื่องคอมพิวเตอร์ที่มีชุดคำสั่งน้อยๆ และไม่ซับซ้อน
โดยจะมีความหมายตรงกันข้ามกับ CISC หรือ Complex
Instruction Set Computer ซึ่งจะชุดคำสั่งที่ซับซ้อนมากมาย
การออกแบบสถาปัตยกรรม
Processor แบบ RISC นั้นจะเน้นการลดจำนวน
และ ความลดซับซ้อนของคำสั่งภายใน ( Instruction ) ซึ่งในความเป็นจริงแล้ว
ก็ยังมีอีกหลายอย่างที่เป็นลักษณะการออกแบบสถาปัตยกรรมแบบ RISC อันได้แก่ การจัดการเกี่ยวกับ Cache, การทำ pipeline,
superscalar และ อื่นๆ
การออกแบบสถาปัตยกรรมแบบ RISC โดยทั่วไป
จะมีกฏเกณฑ์ดังนี้
• 1 คำสั่งต่อรอบสัญญาณนาฬิกา ( One Instruction per Cycle ) นับเป็นสิ่งแรกเลยที่นึกถึงในการออกแบบสถาปัตยกรรมแบบ RISC โดย จะพยายามทำงานให้เสร็จสิ้นภายใน 1
รอบสัญญาณนาฬิกา ( 1 Clock Cycle ) ซึ่งก็มีการใช้ pipeline
มาช่วยในการทำงาน ดังนั้น ในการทำงานจริงๆ อาจไม่ใช่ทำงาน 1 คำสั่งเสร็จสิ้นใน 1 รอบสัญญาณนาฬิกา
แต่ใช้การนับเวลาในการทำงานของโปรแกรม ซึ่งแน่นอน มีการทำงานหลายๆ คำสั่ง หลายๆ
ขั้นตอน แล้วคิดเป็นเวลาเฉลี่ย ซึ่งก็จะได้ประมาณ 1
คำสั่งต่อ 1 รอบสัญญาณนาฬิกา
วิธีที่ใช้เพื่อทำให้ได้
1 คำสั่งต่อรอบสัญญาณนาฬิกา
จะทำโดยใช้คำสั่งง่ายๆ ธรรมดาๆ ไม่ใช่ เพิ่มรอบสัญญาณนาฬิกาให้นานขึ้น
• กำหนดขนาดของ Instruction ให้มีขนาดที่แน่นอน ( Fixed
Instruction Length ) ถ้าหากว่าจะทำให้มีการทำงานแต่ละคำสั่งให้เสร็จสิ้นภายใน
1 รอบสัญญาณนาฬิกาได้นั้น ก็แน่นอน ผู้ออกแบบ RISC ก็จะต้องจำกัดขนาดของคำสั่งด้วย ไม่ให้มีขนาดที่ยาวเกินไป
ซึ่งโดยปกติแล้วจะใช้ขนาด 1 Word ( จะมีขนาดไม่แน่นอน
แล้วแต่เครื่อง แต่โดยทั่วๆไป CPU แบบ RISC จะมีขนาดของ Word = 32 Bit ) โดยใน 1 Word นั้น ก็จะกำหนดทุกๆอย่างทั้งคำสั่ง, Operation , จะดึง
Operand จากที่ไหน , จะให้เก็บผลลัพธ์
( Result ) ที่ไหน และ คำสั่งถัดไปอยู่ที่ไหน
C = A + B : A และ B คือ Operand , + คือ Operation และ C คือ Result
• คำสั่งในการเข้าถึงหน่วยความจำหลัก จะใช้แค่ load ( ดึงข้อมูล
) และ store ( เก็บข้อมูล ) เท่านั้น สถาปัตยกรรมแบบ RISC
นั้น เมื่อจะทำการจัดการกับคำสั่งต่างๆ ก็จำเป็นจะต้องนำ Operand
มาเก็บไว้ใน Register ก่อน และ
ในแต่ละคำสั่งนั้น ก็ถูกจำกัดไว้ที่ 1 Word ซึ่งก็ไม่เพียงพอต่อการเก็บค่าของ
Operand ต่างๆ ดังนั้นจึงใช้การอ้างตำแหน่งในหน่วยความจำแทน
แต่ การเข้าถึงหน่วยความจำนั้นต้องเสียเวลาอยู่พอสมควร
จึงมีการกำหนดให้ใช้เพียงแค่ 2 คำสั่งเท่านั้น คือการ load
และ การ store เพื่อลด traffic ระหว่าง หน่วยประมวลผล และ หน่วยความจำ ส่วนเวลาในการ load หรือ store นั้น ก็ขึ้นอยู่กับขนาดของ Operand
• ใช้การอ้างตำแหน่งแบบตรงๆ ง่าย เพราะการอ้างแบบซับซ้อน ก็แน่นอน
ต้องใช้ช่วงเวลานานกว่า ซึ่งการอ้างตำแหน่งแบบ RISC นั้นจะจำกัดอยู่
2 แบบ คือ แบบอ้างผ่าน Register ( Register Indirect )
และ Index โดยการอ้างผ่าน Register นั้น Register จะเก็บค่าตำแหน่งไว้ แล้ว ทำการอ้าง
ตำแหน่งนั้นๆผ่าน Register และในแบบ Index จะเป็นการอ้างตำแหน่งจากค่าคงที่ที่มาในคำสั่งนั้นๆเลย
• ใช้ Operation ที่เรียบง่าย ธรรมดาๆ และ มีไม่กี่ Operation
เพื่อจะได้ใช้รอบการทำงานน้อยๆ และรวมไปถึงทรัพยากรของระบบที่ใช้
ก็จะใช้น้อยด้วย
ในส่วนของการออกแบบ
CISC นั้น
ดูเหมือนใช้หลักเกณฑ์ที่ตรงข้ามกับแบบของ RISC แทบจะทั้งหมด
เพราะ ในขณะที่ RISC จะพยายามลดคำสั่งให้มีจำนวนน้อยๆ และ
ไม่ซับซ้อน แต่ CISC จะพยายามให้มีรูปแบบของคำสั่งต่างๆ
มากมาย และ ดูจะซับซ้อนมากขึ้นเรื่อยๆ ส่วนในเรื่องของคำสั่งการทำงานของ RISC
นั้น ก็จะมีค่าเฉลี่ยเป็น 1 คำสั่งต่อ 1 สัญญาณนาฬิกา แต่ในขณะที่ CISC อาจใช้ถึง 100 สัญญาณนาฬิกา เพื่อให้ทำงานให้เสร็จ เพียง 1 คำสั่ง
CISC นั้น ก็จะมีจุดเด่น
ในเรื่องของการเขียน Program บน CISC นั้น
จะทำได้ง่ายกว่า เพราะโดยตัวของ Processor นั้นรู้จักคำสั่งต่างๆมากมาย
ทำให้สะดวกต่อการเขียนโปรแกรมใช้งาน และ Program บน CISC
นั้นก็มีขนาดเล็กกว่า บน RISC ( ด้วยเหตุผลเดียวกัน
)
ต้องอย่าลืมว่า
ต่อให้ Processor นั้นดีเพียงใด ก็ตามแต่หากว่า
ไม่มีโปรแกรมมาสนับสนุน หรือเขียนโปรแกรมมาใช้งานบน Processor นั้นๆยาก ก็คงไม่มีคนเลือกใช้ Processor นั้นๆ
เป็นแน่ หากว่า ผู้ออกแบบ CISC นั้น ออกแบบมาดี
โปรแกรมบางอย่าง อาจทำได้เร็วกว่า RISC ด้วยซ้ำ
เพราะมีการใช้คำสั่งที่น้อยกว่า ( เพราะมีการเตรียมคำสั่งต่างๆ ไว้จัดการแล้ว
) ตัวอย่างเช่น ต้องการหาผลลัพธ์ของ 7 คูณกับ 9
ถ้า RISC มีเพียงคำสั่ง บวก และ ลบ
การจะหาผลลัพธ์ของ 7 คูณ 9 ก็คือ
ต้องทำการบวก 7 เข้าด้วยกัน 9 ครั้ง
สมมุติว่าแต่ละครั้งของการบวก จะใช้เวลา 1 สัญญาณนาฬิกา
ก็จะใช้ถึง 9 สัญญาณนาฬิกา และแม้ว่า Compiler นั้นฉลาด ทำการเอา 9 มาบวกกัน 7 ครั้งแทน ก็จะใช้สัญญาณนาฬิกาที่ 7 สัญญาณนาฬิกา
ถ้าเป็น CISC ซึ่งมีคำสั่งคูณไว้ให้แล้ว และ ใช้ 5 สัญญาณนาฬิกาในการคูณแต่ละครั้ง การหาผลลัพธ์ของ 7
คูณกับ 9 ก็จะทำได้ใน 5
สัญญาณนาฬิกาเท่านั้น แต่ในบางกรณี เช่น 4 คูณกับ 3
RISC นั้น จะใช้เวลาเพียง 3 หรือ 4 สัญญาณนาฬิกา แต่ CISC กลับต้องใช้ถึง 5 สัญญาณนาฬิกา
ในการเปรียบเทียบความเร็วและประสิทธิภาพของ
RISC กับ CISC ทำได้ยาก
เพราะ ต้องแล้วแต่งานที่ใช้ในการทดสอบเปรียบเทียบ ดังจะเห็นได้จากตัวอย่างข้างต้น
เพียงแค่เปลี่ยนค่า Operand เท่านั้น ผลที่ได้ก็ต่างกันแล้ว
เพราะฉะนั้น คำตอบสำหรับคำถามนี้ ก็คงตอบได้ยาก เพราะต้องแล้วแต่งาน และ
โปรแกรมที่ใช้ และรวมไปถึงค่าต่างๆ ที่อ้างอิงถึงด้วย
ปัจจุบันนี้ Processor แบบ CISC นั้น
นับวันก็ยิ่งมีความซับซ้อนของคำสั่ง แต่ก็เป็นเรื่องแปลก ที่ในขณะเดียวกัน CISC
นั้น ก็ยิ่งมีรูปแบบออกไปทาง RISC ยิ่งขึ้น
โดยส่วนหนึ่งนั้นก็มาจากการลดปัญหาเรื่อง ความเข้ากันได้ของ Processor รุ่นใหม่ๆ กับ Processor รุ่นเก่า
ซึ่งดูเหมือนว่าการดัดแปลงคำสั่งสำหรับ Processor ตระกูล x86
( CISC ) ให้เป็นชุดคำสั่งแบบ RISC ที่เล็กๆกว่า
เร็วกว่า และ ง่ายขึ้น ผลลัพธ์ที่ได้ ก็คือ ชุดคำสั่งของ RISC สำหรับ Process ตระกูล x86 ( CISC ) ที่เรียกว่า ชุดคำสั่ง RISC86 และ ยิ่งนับวัน Processor
แบบ CISC นั้น ก็มีการทำงานแบบ Pipeline
และ แบบ Speculative Execution ( มีการคาดเดาล่วงหน้า
) ด้วย ซึ่งคุณลักษณะเหล่านี้ แต่เดิมนั้นพัฒนาอยู่บน RISC ส่วนในทางกลับกัน
Processor แบบ RISC เองนั้น
ก็เริ่มที่จะมีการใช้คำสั่งที่ซับซ้อนขึ้น และ มีหลากหลายคำสั่งมากขึ้น
ซึ่งก็เหมือนว่าจะเบนไปทาง CISC เช่นกัน
สำหรับ Processor ที่ใช้สถาปัตยกรรมแบบ RISC
นั้น ก็ได้แก่ SUN Sparc , IBM RS/6000 , Motorola 88000 ( เป็น Processor แบบ RISC ตัวแรกของ
Motorola ) ส่วน Processor ที่ใช้สถาปัตยกรรมแบบ
CISC นั้น ก็ได้แก่ Processor ตระกูล x86 ทั้งหลาย ทั้ง Intel 8088 เรื่อยมาจนถึงล่าสุด Pentium
!!! , AMD ตังแต่ Am286 เรื่อยมาถึงล่าสุด K6-III
ซึ่งถึงแม้ว่าจะมีการใช้สถาปัตยกรรมแบบ RISC เข้ามาบ้าง
แต่ แกนหลักก็ยังคงเป็น CISC เช่นเดิม
Cache คืออะไร? และ ที่มาของ Cache
Cache
นั้น ถ้าว่ากันตามหลักการ มันก็คือ หน่วยความจำชนิดหนึ่ง
ซึ่งจะมีความเร็วในการเข้าถึง และการถ่ายโอนข้อมูล ที่สูง โดยจะมีหน้าที่ในการเก็บ
พัก ข้อมูลที่มีการใช้งานบ่อยๆ เพื่อเวลาที่ CPU ต้องการใช้ข้อมูลนั้นๆ
จะได้ค้นหาได้เร็ว โดยที่ไม่จำเป็น ที่จะต้องไปค้นหาจากข้อมูลทั้งหมด
เปรียบเทียบกันง่ายๆ
ก็เหมือนกับการอ่านหนังสือ แล้วเวลาที่เจอข้อความที่น่าสนใจ
ก็ทำการจดบันทึกไว้ที่สมุด แล้วเมื่อเวลาต้องการ ข้อมูลนั้นๆ
ก็สามารถค้นหาจากในสมุดจดได้ง่ายกว่า เปิดหาจากหนังสือทั้งเล่ม แน่นอน
ข้อมูลที่จดลงในสมุดนั้น มีขนาดน้อยกว่า ในหนังสือแน่ๆ คงไม่มีใครที่จะลอกข้อมูล
ทุกบรรทัด ทุกหน้าของหนังสือ ลงในสมุดจดเป็นแน่แท้
จากที่กล่าวมาแล้วข้างต้น ในปัจจุบัน
เราจะพบการใช้งาน Cache อยู่ 2 แบบ
นั่นก็คือ Memory Cache และ Disk Cache โดยที่หลักการทำงานของทั้ง 2 ชนิดนี้ก็คล้ายๆ กัน
กล่าวคือ Disk Cache นั้น
จะเป็นการอ่านข้อมูลที่ต้องการใช้งานเข้ามาเก็บไว้ในหน่วยความจำหลัก เมื่อ CPU
มีการเรียกใช้งาน ก็จะเข้าไปค้นหาในหน่วยความจำหลักก่อน
หากว่าไม่พบจึงจะไปค้นหาใน Harddisk ต่อไป และ ในกรณีของ Memory
Cache นั้น ก็เป็นอีกลำดับขั้นหนึ่งถัดจาก Disk Cache นั่นก็คือ จะทำการดึงข้อมูลที่มีการเรียกใช้งานบ่อยๆ
เข้ามาเก็บไว้ในหน่วยความจำ ขนาดเล็ก ที่มีความไวสูงกว่าหน่วยความจำหลัก เมื่อ CPU
ต้องการใช้งาน ก็จะมองหาข้อมูลที่ต้องการที่
หน่วยความจำขนาดเล็กนั้นก่อน ก่อนที่จะเข้าไปหาในหน่วยความจำหลักที่
มีการเข้าถึงและการส่งถ่ายข้อมูลที่ช้ากว่าต่อไป และ หน่วยความจำขนาดเล็กๆ นั้น
เราก็เรียกมันว่า Cache นั่นเอง
สำหรับในบทความนี้
เราจะพูดถึงเรื่อง Memory Cache กันอย่างเดียว
เพราะฉะนั้นผมจะขอเรียกแค่สั้นๆว่า Cache ก็ขอให้เป็นอันเข้าใจตรงกัน
ว่ามันหมายถึง Memory Cache
Cache นั้น ตำแหน่งของมัน จะอยู่ระหว่าง CPU กับ
หน่วยความจำหลัก โดยมันจะทำการดึง หรือ เก็บข้อมูลที่มีการเรียกใช้งาน
บ่อยๆ
จากหน่วยความจำหลัก ซึ่งความไวในการอ่าน หรือ ส่งถ่ายข้อมูลจาก Cache ไปยัง CPU หรือ
จาก CPU ไปยัง Cache นั้น
จะทำได้เร็วกว่า จากหน่วยความจำหลักไปยัง CPU หรือจาก CPU
ไปยังหน่วยความจำหลัก มาก เพราะทำด้วย SRAM ซึ่งมีความไวสูง
และมีราคาแพงกว่าหน่วยความจำของระบบที่เป็น DRAM อยู่มาก
และก็เพราะราคาที่แพงนี้ ทำให้ขนาดของ Cache ที่ใช้ในระบบ
จึงมีขนาดน้อยกว่าหน่วยความจำหลักอยู่มากเช่นกัน
DRAM
หรือ Dynamic RAM นั้นจะทำการเก็บข้อมูลในตัวเก็บประจุ
( Capacitor ) ซึ่งจำเป็นจะต้องมีการ refresh เพื่อ
เก็บข้อมูลให้คงอยู่ โดยการ refresh นี้
ทำให้เกิดการหน่วงเวลาขึ้นในการเข้าถึงข้อมูล และก็เนื่อง จากที่มันต้อง refresh
ตัวเองอยู่ตลอดเวลานี้เอง จึงเป็นเหตุให้ได้ชื่อว่า Dynamic
RAM
ส่วน SRAM นั้นจะต่างจาก DRAM ตรงที่ว่า DRAM จะต้องทำการ refresh ข้อมูลอยู่ตลอดเวลา แต่ในขณะที่ SRAM จะเก็บข้อมูลนั้นๆ
ไว้ และจะไม่ทำการ refresh โดยอัตโนมัติ ซึ่งมันจะทำการ refresh
ก็ต่อเมื่อ สั่งให้มัน refresh เท่านั้น
ซึ่งข้อดีของมัน ก็คือความเร็ว ที่เร็วกว่า DRAM ปกติมาก
แต่ก็ด้วยราคาที่สูงกว่ามาก จึงเป็นข้อด้อยของมันเช่นกัน
จากที่กล่าวมาข้างต้น ก็ดูเหมือนว่า
Cache นั้น มีความสำคัญ
ต่อความเร็วของระบบอยู่ไม่ใช่น้อย แล้วทำไมเราถึงเพิ่งจะให้ความสำคัญกับมันล่ะ?
เพราะว่า เพิ่งมีการใช้ Cache กับ CPU รุ่นใหม่ๆ อย่างนั้นหรือ? เปล่าเลย จริงๆแล้ว
เรามีการใช้ Cache มาตั้งนานแล้ว ตั้งแต่รุ่น 80486 ซึ่งสมัยนั้นทาง Intel ก็ได้เริ่มมีการใส่ Cache
ให้กับ CPU ของตน โดยเริ่มใส่ขนาด 8KB ในรุ่น 486DX-33 และ ได้ทำการเพิ่มเป็น 16KB ในรุ่น 486DX4 เป็นต้นมา ซึ่ง Cache ที่ใส่ไปนั้น ได้ใส่เข้าไปในแกนหลักของ CPU เลย
ทำให้การติดต่อระหว่าง CPU กับ Cache นั้น
ทำได้เร็วมาก และมีการใช้ Cache อีกขั้นหนึ่ง โดยใส่ไว้ที่ Mainboard
ซึ่งจะมีขนาดที่ใหญ่กว่า แต่ช้ากว่า Cache ที่ใส่ไว้ในแกน
CPU
เมื่อ CPU ต้องการข้อมูลใดๆ ก็จะทำการค้นหาจาก Cache
ที่อยู่ภายในแกน CPU ก่อน
หากว่าพบข้อมูลที่ต้องการ ( เรียกว่า Cache Hit) ก็จะดึงข้อมูลนั้นๆ
มาใช้งานได้เลย แต่หากไม่พบ ( เรียกว่า Cache Miss ) ก็จะทำการค้นหาในส่วนของ
Cache ที่อยู่บน Mainboard ต่อไป และ
หากว่ายังไม่พบอีก ก็จะไปค้นหาในหน่วยความจำหลักต่อไปอีกขั้น
และหากว่าในหน่วยความจำหลักนั้น ก็ยังไม่มีข้อมูลที่ต้องการ ก็จะไปค้นหาต่อใน Harddisk
ต่อไป
ด้วยตำแหน่งในการเก็บ Cache ที่ต่างกัน และ
ลำดับขั้นในการเรียกใช้งานต่างกัน จึงเรียก Cache ที่อยู่ในแกนของ
CPU ว่า Internal Cache หรือ Level
1 Cache ( L1 Cache ) และ เรียก Cache ที่อยู่บน
Mainboard นั้นว่าเป็น External Cache หรือ
Level 2 Cache ( L2 Cache )
ต่อมา
ใน CPU รุ่น Pentium ของ
Intel นั้น ก็ได้ทำการแบ่ง Cache ภายใน
ออกเป็น 2 ส่วนเพื่อแยกการทำงานกัน ซึ่งก็ได้แบ่งจาก 16KB
นี้ ออกเป็น 8KB เพื่อใช้ เก็บคำสั่งต่างๆ
เรียกว่า Instruction Cache และ อีก 8KB เพื่อใช้เก็บข้อมูลต่างๆ เรียกว่า Data Cache
และต่อมา CPU ในรุ่น Pentium II ของทาง Intel นั้น
ก็ได้มีการเปลี่ยนแปลงตำแหน่งการเก็บ Cache ระดับ 2 ซึ่งจากปกติจะจัดเก็บไว้ บน Mainboard ก็ทำการย้าย
มาเก็บไว้บน Package เดียวกับ CPU ( CPU Intel
Pentium II นั้น จะมีลักษณะเป็น Cartridge แผ่นกว้างๆ
มี CPU อยู่ตรงกลางและ เก็บ Cache ไว้ข้างๆ
แล้วรวมกันเป็น Package เดียวกัน เรียกว่า Single
Edge Contact Cartridge หรือ SECC แต่ก็ยังคงเรียก
Cache ที่อยู่บน SECC ว่าเป็น External
Cache หรือ Level 2 Cache เช่นเดิม เพราะยังคง
อยู่ภายนอกตัว CPU เพียงแค่อยู่บน Package เดียวกันเท่านั้น
แต่ด้วยราคาที่สูงมากของ
CPU Pentium II ในสมัยที่เพิ่งวางตลาดนั้น
ทำให้มีผู้ที่มีอำนาจในการซื้อมาใช้งานน้อย ทาง Intel จึงได้ตัด
Cache ระดับ 2 ออก จาก Pentium
II เพื่อลดต้นทุนการผลิต และ เปลี่ยนรูปแบบ Package ให้ดูบางลง แล้วเรียก CPU ใหม่นี้ว่า Celeron
และ เรียก Package ของ Celeron ว่า Single Edge Processor Package
จากที่กล่าวมาแล้วข้างต้นมาแล้วว่า Cache นั้นมีราคาสูง เพราะฉะนั้น เมื่อตัด
Cache ระดับ 2 ออกทำให้ราคาของ Celeron
ถูกกว่า Pentium II อยู่มาก และ ทาง Intel
ก็หวังจะใช้ Celeron ที่ราคาถูกนั้น
ตีตลาดระดับกลาง และ ระดับล่าง
แต่แล้วก็ฝันสลาย
เพราะ Celeron ที่ไม่มี Cache นั้น ในด้านการเล่นเกมส์ ที่ไม่มีการเรียกใช้ Cache เท่าไร
ทำคะแนน หรือ มีความสามารถ เทียบเท่ากับ Pentium II ที่ระดับความเร็วเท่าๆ
กัน แต่ ในงานด้าน Office Application เช่น Microsoft
Word, Microsoft Excell กลับทำได้แย่มากๆ จากที่เห็นก็คือ Celeron
ที่ความเร็ว 300 MHz นั้น เมื่อใช้งานกับ Application
ดังกล่าว กลับช้ากว่า Pentium MMX 233 เสียอีก
ทำให้ Celeron รุ่นดังกล่าวไม่ได้รับความนิยมเท่าใดนัก
ทาง Intel จึงได้ผลิต Celeron รุ่นใหม่ที่ได้เติม Cache ระดับ 2 เข้าไปด้วย โดยให้มีขนาดเพียง 1/4 ของ Pentium
II แต่ให้ทำงานด้วย ความเร็วเท่ากับ ความเร็วของ CPU ( Cache
ระดับ 2 ของ Pentium II นั้นจะทำงานที่ความเร็วเพียงครึ่งหนึ่งของความเร็ว
CPU ) และเพียงแค่เพิ่ม Cache ระดับ 2 เข้าไปนี้เอง ผลคะแนนที่ได้จากการทำงานกับ Application ดังกล่าวนั้น กลับเพิ่มขึ้นมามาก ต่างจาก รุ่นเดิมที่ไม่มี Cache อย่างเห็นได้ชัด
นี่เป็นจุดหนึ่งที่ทำให้
Cache เริ่มเป็นที่สนใจ มากขึ้น
แต่ยังไม่หมดเท่านี้ อีกจุดหนึ่งที่ทำให้เรื่องของ Cache นั้น
เป็นที่กล่าวถึง กันมากขึ้นในขณะนี้ เกิดจากการประกาศตัวของ AMD K6-III
AMD K6-III มีอะไรดี ถึงทำให้เรื่องของ Cache
เป็นที่น่าสนใจนัก อันนี้คงต้องเท้าความกลับไปอีกสักนิดหนึ่งก่อน
ว่า CPU ของ AMD นั้นก็มีการใช้ Internal
Cache และ External Cache เช่นเดียวกับ CPU
ของ Intel มาโดยตลอด เมื่อ Intel เปลี่ยนสถาปัตยกรรมใหม่ เอา Cache ไปไว้บน Package
ของ CPU และไม่มีการใช้ Cache บน Mainboard อีกต่อไป แต่ทาง AMD ก็ยังคงใช้งานบน สถาปัตยกรรมเดิม คือมี Internal Cache ภายใน CPU และมี External Cache อยู่บน Mainboard เรื่อยมา จนถึงรุ่น AMD
K6-2
พอมา AMD K6-III ( หรือก็คือ AMD K6-3 แต่มีการเปลี่ยนชื่อ เพื่อให้สอดคล้องกับ Intel Pentium III ) ทาง AMD ก็ได้ทำการ เพิ่ม Cache เข้าไปที่ Package ของ CPU บ้าง
( แต่ไม่ได้รวมเข้าไปในแกนของ CPU ) และ ก็ยังคงให้มี Cache
บน Mainboard เช่นเดิม ดังนั้น จึงเกิดมีการใช้งาน
Cache ถึง 3 ระดับด้วยกัน ( เรียกว่า Tri-Level
Cache ) โดย ระดับแรกสุดนั้น ก็คือ Cache ที่อยู่ภายในแกนของ
CPU เลย ระดับถัดมา ก็อยู่บน Package ของ
CPU และ ระดับสุดท้ายอยู่บน Mainboard ซึ่งขนาดของ
Cache ก็จะมากขึ้นตามลำดับ ในขณะที่ความเร็วในการใช้งานกลับลดลงตามลำดับ
และนี่เอง
จึงทำให้เรื่องของ Cache นั้นเป็นที่น่าสนใจยิ่งนัก
ทั้งเรื่องที่ว่า ขนาดของ Cache ที่มีใน Celeron มีน้อย แต่ทำงานด้วยความเร็วสูง เท่ากับความเร็ว CPU ส่วน Pentium II มี Cache มากกว่า
Celeron แต่ทำงานด้วยความเร็วเป็นครึ่งหนึ่ง ของ CPU อย่างไหนสำคัญกว่ากัน ขนาด หรือ ความเร็ว? และ
เรื่องของ Tri-Level Cache ใน AMD K6-III นั้น จะทำให้ระบบเร็วขึ้นจริงไหม? มี Cache หลายระดับดีกว่าไหม?
เราจะมาดูกันต่อไป
ถึงรายละเอียด และ ความสำคัญของ Cache ในแต่ละระดับกันต่อไป
Cache ระดับ 1 นั้น
จะเป็นส่วนที่สำคัญที่สุด และตำแหน่งของมันก็จะอยู่ใกล้ๆ กับตัว CPU ที่สุด ทำให้ CPU สามารถเข้าถึงได้
รวดเร็วมาก
ซึ่งโดยปกติแล้วขนาดของมัน ก็จะไม่ใหญ่นัก เช่น สำหรับ CPU Intel Pentium II หรือ Intel
Celeron จะมี L1 Cache ขนาดเพียง 32 KB
และ บน AMD K6-2 จะมีขนาด 64 KB ซึ่งถึงแม้ว่าจะมีขนาดเพียง เล็กน้อย แต่ก็มีความสำคัญมาก
Level 1 cache นั้น
จะทำงานด้วยความเร็วที่เท่ากับ CPU เลย (
คงเพราะฝังอยู่ในตัว CPU ) และ สำหรับกว่าที่ว่า ยิ่งมี Cache
มากๆ ก็จะยิ่งเร็วกว่า แน่นอนว่า คำกล่าวนี้เป็นจริง
แต่ก็ไม่ใช่ทั้งหมดทุกกรณี เพราะว่ามีองค์ประกอบอื่นๆ ด้วย ดังจะเห็นได้จาก L1
cache ของ Intel Pentium II ซึ่ง มี ขนาดเพียง
32 KB แต่มีการเข้าถึงได้ 4 ทิศทาง ( 4
way associative ) ในขณะที่ AMD K6-2 จะมี L1
cache ขนาด 64 KB แต่มี การเข้าถึงได้เพียง 2 ทิศทาง ( 2 way associative ) ซึ่งในกรณีของการเข้าถึงแบบสุ่มนั้น
Intel จะทำได้เร็วกว่า AMD
ส่วนถัดมาในการค้นหาข้อมูลของ
CPU เมื่อค้นหาใน Cache ระดับ 1 ไม่พบ ก็คือ Cache ระดับ
2 ซึ่ง ขนาดของ Level 2 Cache นั้น
ก็จะต่างกัน ตามรุ่น และ ชนิดของ CPU นั้นๆ ซึ่ง ก็แน่นอน
จะมีความของความเร็วแตกต่างกันไปด้วย
จากที่กล่าวมาแล้วเมื่อตอนต้นๆ
ถึงเรื่องของ Celeron กับ Pentium II ที่ว่า Celeron นั้นมี Cache ระดับ
2 เพียง 128 KB แต่
ทำงานด้วยความเร็วเท่าๆ
กับ CPU ส่วน Pentium II จะมี Cache ระดับ 2 ถึง 512
KB แต่ทำงานด้วย ความเร็วเพียง ครึ่งหนึ่งของความเร็วของ CPU
แล้วอย่างไหน สำคัญกว่ากัน ความเร็ว หรือว่าขนาด อย่างไรก็ตาม
ขนาดของ Level 2 cache นั้น ก็ยังเป็นจุดหลักสำคัญของ Performance
เพื่อลดการ access disk โดยการอ่านข้อมูลมาเก็บไว้ที่
RAM และนำส่วนสำคัญๆ ที่ใช้บ่อยๆ มาเก็บที่ Cache นั้น ถ้า Cache มีขนาดที่ใหญ่ๆ
การที่จะต้องอ่านข้อมูลจาก RAM ซึ่งช้ากว่า Cache นั้น ก็ทำได้ดีกว่า ยิ่งกับระบบ Network-File-Server นั้น ยิ่งมี Cache มากๆ และ เร็วๆ จะยิ่งดี ดังนั้น Intel
Pentium II Xeon จึงมี L2 Cache 512K หรือมากกว่านั้น
และ ทำงานที่ความเร็วเท่าๆ กับ CPU
สำหรับ AMD K6, K6-2 นั้น ใช้ cache ซึ่งอยู่บน Mainboard ซึ่ง ความเร็วสูงสุด ก็ตาม FSB
ที่ใช้ เช่น K6-2 300 MHz นั้น Level 2
Cache ก็จะมี ความเร็ว ที่ 100 MHz ( FSB 100 MHz ) แต่ Intel Pentium II - 300 MHz นั้น จะมี Level
2 Cache ที่ความเร็ว 150 MHz และ Celeron
300A จะมี Level 2 Cache ที่มีความเร็วถึง 300
MHz ซึ่งสำหรับ AMD K6-2 กับ Pentium
II นั้น ดูไม่แตกต่างเท่าไร แต่หากว่า เป็น Pentium II 400 ล่ะ จะมี Levl 2 Cache ที่ทำงานที่ 200 MHz ในขณะที่ AMD K6-2 400 MHz ก็ยังใช้ Cache ที่ทำงานด้วยความเร็ว 100 MHz เช่นเดิม
นั่นก็เป็นส่วนสำคัญจุดหนึ่งที่ทำให้ผล Performance ในเรื่อง
Memory Performance ของ AMD ด้อยกว่า Intel
Pentium II และ Celeron
แต่ในสำหรับ
AMD K6-3 นั้น ทาง AMD ได้รวม Level 2 cache เข้ากับ Package เดียวกับ CPU เลย โดยเก็บฝังไว้บนตัวของ CPU เช่นเดียวกับ Celeron แต่มีขนาดเป็น 2 เท่า และ ทำงานที่ความเร็วเท่าๆ กับ CPU ซึ่งก็ทำให้
AMD K6-3 นั้น มี L2 cache มากกว่าถึง Celeron
2 เท่า และ มี Level 2 cache ที่ความเร็วเป็น 2 เท่าของ Pentium II ( ที่ความเร็วเท่าๆกัน )
AMD
K6-III นั้น มีจุดที่น่าสนใจมากๆ อย่างหนึ่ง นั้นก็คือ K6-III
นั้นจะมี Level 2 cache ฝังอยู่ใน chip
CPU มาด้วย แต่ในขณะเดียวกัน Mainboard ที่ใช้สำหรับ
AMD K6-III นั้น ก็มี Cache มาให้ด้วย
ทำให้ มันมอง Cache บน Mainboard นั้นๆ
เป็น Cache ระดับ 3 ( Level 3 Cache )
ถ้ากำหนดให้ เวลาที่ใช้ในการอ่านข้อมูลจากแหล่งต่างๆ เป็นดังนี้
Cache ระดับ 1 1 หน่วยเวลา (
Unit )
Cache ระดับ 2 10 หน่วยเวลา ( Unit )
Cache ระดับ 3 ขนาด 512
K 100 หน่วยเวลา ( Unit )
Cache ระดับ 3 ขนาด 1,024
K 200
หน่วยเวลา ( Unit )
Cache ระดับ 3 ขนาด 2,048
K 400
หน่วยเวลา ( Unit )
หน่วยความจำหลัก
1,000 หน่วยเวลา ( Unit )
เมื่อ CPU ต้องการข้อมูลเพื่อการประมวลผล
ก็จะมองหาข้อมูลที่ต้องการดังกล่าวเสียก่อน จากใน Cache ระดับ
1 ซึ่งถ้าหาพบ ก็จะใช้เวลาเพียง ไม่เกิน 1 หน่วย แต่ถ้าไม่พบ ก็จะไปมองหาที่ Cache ระดับ 2 ต่อไป ถ้าหาพบ ก็จะใช้เวลาไม่เกิน 11 หน่วยเวลา ( 1+10
) แต่ถ้าหาไม่พบ ก็ต้องเสียเวลา มากกว่า 11
หน่วยเวลาเพื่อไปค้นหาในหน่วยความจำหลัก หรือ ใน Cache ระดับ
3 ต่อไป
ถ้าไม่มี
Cache ระดับ 3
การหาข้อมูลนั้น เมื่อหาจากใน Cache ทั้งระดับ 1 และ ระดับ 2 ไม่พบ
ก็จะเข้าไปหาที่หน่วยความจำหลักต่อไป ซึ่งถ้าพบ ก็จะใช้เวลามากกว่า 11 (
1+10 ) หน่วยเวลา แต่ไม่เกิน 1,011 ( 1+10+1,000 ) หน่วยเวลา แต่ถ้ามี Cache ระดับ 3 ก็จะทำการเข้าไปค้นหาใน Cache ระดับ 3 ต่อไป ซึ่งเวลาที่ใช้ ก็ขึ้นอยู่กับขนาดของ Cache ระดับ
3 นั้นด้วย ซึ่งถ้าหาพบใน Cache ระดับ 3 ก็จะใช้เวลาที่มากกว่า 11 หน่วยเวลา แต่น้อยกว่า 111
( 1+10+100 ) หน่วยเวลา สำหรับ Cache ระดับ 3 ขนาด 512KB และ น้อยกว่า 211 ( 1+10+100 ) สำหรับ Cache ระดับ 3 ขนาด 1,024
KB และ น้อยกว่า 411 ( 1+10+400 ) สำหรับ Cache
ระดับ 3 ขนาด 2,048KB ซึ่งจะสังเกตุได้ว่า
ถ้าสามารถหาข้อมูลพบใน Cache ระดับ 3
นั้น เวลาที่ใช้งาน ก็น้อยกว่า การที่ไม่มี Cache ระดับ 2 อยู่มากกว่าเท่าตัว
ถ้าไม่พบข้อมูลที่ต้องการใน
Cache ระดับ 3
ก็จะเสียเวลาในการค้นหาที่มากขึ้น ก่อนที่จะไปค้นหาในหน่วยความจำหลักต่อไป
ซึ่งตรงจุดนี้เอง ก็เป็นผลทำให้ Performance ที่ได้ลดลง
แต่อย่างไรก็ตาม การที่มี Cache ระดับ 3 ขนาดใหญ่นั้น โอกาสที่จะทำให้ค้นหาข้อมูลที่ต้องการ นั้นก็มากขึ้น
สำหรับอัตราส่วนระหว่าง
Level 2 ต่อ Level 3
นั้นก็มีส่วนสำคัญ เช่นเดียวกันกับ อัตราส่วนระหว่าง Level 1/Level 2 หากว่า CPU มองหา ข้อมูลที่ต้องการใน Cache ระดับใดๆ ไม่เจอ ก็จะทำการค้นหาใน Cache ระดับถัดไป
ซึ่งจะมีความเร็วช้ากว่า แต่มีขนาดใหญ่กว่า แต่อย่างไรก็ตาม ถ้าใน Cache ระดับถัดไปนั้น ขนาดไม่ใหญ่ โอกาสที่จะหาข้อมูลที่ต้องการเจอนั้น
ก็มีน้อยกว่า ( เพราะมีเนื้อที่ น้อยกว่า ทำให้โอกาสที่จะดึงข้อมูลจาก RAM มา แล้วตรงกับที่ต้องการนั้น เป็นไปได้น้อยกว่า ) ก็ทำให้ CPU นั้น เสียเวลา ในการค้นหาไปอย่างสูญเปล่า ( ในกรณีที่หาไม่พบ )
แล้วก็จะทำให้ผล Performance นั้นช้ากว่า จากที่ควรจะเป็น
ปกติแล้ว อัตราส่วนจะเป็นระหว่าง Cache ระดับถัดมาต่อ Cache
ระดับก่อนหน้า จะเป็น 4:1 เช่น Level 2
Cache /Level 1 Cache ของ Celeron จะเป็น 128:32
( 4:1 ) และ K6-3 จะเป็น 256:64 ( 4:1
) ยกเว้นของ Pentium II ที่เป็น 512:32
( 16:1 )
ทาง AMD ก็ได้อ้างว่า ด้วย Cache 1Mb บน Mainboard นั้น จะทำให้ Performance เพิ่มขึ้น 3-4 % ( L3/L2 = 1024/256 = 4/1 ) ซึ่ง
ปัจจุบันนั้น ก็มี Mainboard ที่มี ทั้ง Cache 1M และ 512 K ให้เลือก เพราะฉะนั้น
นี่คงเป็นตัวช่วยในการพิจารณาตัวหนึ่งแล้วนะครับ สำหรับผู้ที่คิดจะใช้ AMD
K6-3 ว่าควรจะใช้ Mainboard อะไรดี สำหรับการ disable
Level 3 Cache นั้น คิดว่า เป็นไปได้ โดยผ่านทาง BIOS ซึ่งก็น่าจะมีผลช่วยในการ Overclock ให้ได้มากขึ้น
คราวนี้เราลองย้อนกลับไปดูถึงตอนแรก
ที่เปรียบเทียบเรื่อง Cache กับการจดโน๊ตย่อลงสมุดนั้น เราอาจสรุปได้ว่า สมองของเราเป็น Cache ระดับ 1 เพราะเมื่ออ่านและเห็นว่าข้อความไหน
หรือประโยคไหนที่น่าจำที่สุด สำหรับนักเรียน นิสิต นักศึกษา ก็คงอาจเล็งไว้แล้วว่า
ตรงนี้ อาจารย์ต้องเอามาออกข้อสอบแน่ๆ ก็จะอ่านแล้วท่องจำเอาไว้ และ
เมื่อเกินความสามารถที่จะท่องจำ ก็ทำการจดโน๊ตย่อไว้ในสมุดเล่มเล็กๆ นั่นก็คือ Cache
ระดับ 2 นั่นเอง และ บางทีในการอ่าน
ก็อาจมีเรื่องที่น่าสนใจมากๆ จดโน๊ตย่อไม่ไหว
ก็อาจใช้ปากกาขีดข้อความสำคัญๆหรือทำการคั่นหน้าหนังสือตรงนั้นไว้ นั่นก็คือ Cache
ระดับ 3 นั่นเอง
ก็เห็นกันแล้วว่า
ขนาดของ Cache นั้น เป็นสิ่งสำคัญ และ ความเร็วของ
Cache นั้น ก็สำคัญเช่นกัน แต่ ถ้าให้เลือก ระหว่าง Celeron
300A ซึ่งมี Level 2 cache 128 K ทำงานที่ความเร็วเท่าๆ
กับ CPU กับ Pentium II 300 ที่มี L2
cache 512 K ทำงานเป็นครึ่งหนึ่ง แต่ราคานั้นต่างกันเท่าตัว
ในขณะที่ Performance ในด้านที่ไม่เกี่ยวกับ Business
นั้น แทบไม่ต่างกัน ก็ขอเลือก Celeron จะดีกว่า
( ถูกกว่าตั้งเยอะ )
แต่หากว่าต้องใช้งานด้าน
Business แล้วละก็ คงจะต้องเลือก CPU
ที่มี Cache มากๆ ไว้ก่อน เพราะถึงแม้ว่า Cache
นั้นจะเร็ว แต่มีขนาดน้อย เปอร์เซ็นต์ในการหาข้อมูลพบใน Cache
ก็น้อยลง ถึงแม้จะถูกชดเชยด้วยความเร็ว แต่มันก็ทำให้ Cache นั้นต้องรับ ภาระที่หนักมากขึ้นไปด้วย
สรุป
โครงสร้างภายในซีพียู
หน่วยประมวลผลกลางหรือ (Central
Processing Unit ;CPU)เปรียบได้กับสมองของคอมพิวเตอร์
เป็นส่วนที่สำคัญที่สุด ทำหน้าที่เป็นศูนย์กลางการประมวลผลและควบคุมระบบต่างๆ
ของคอมพิวเตอร์ ให้ทุกหน่วยทำงานสอดคล้องสัมพันธ์กัน
โครงสร้างภายในซีพียู
ซีพียูจะทำงานตามคำสั่งที่ผู้ใช้ป้อนเข้าไป
ซึ่งคำสั่งดังกล่าวจะถูกเก็บในหน่วย ความจำหลัก
ดังนั้นซีพียูจะต้องทำงานดังต่อไปนี้
- ดึงคำสั่งเข้ามา (fetch
instruction) คือการที่ซีพียูอ่านคำสั่งมาจากหน่วยความจำหลักเข้ามาเก็บไว้ภายในตัวซีพียู
- แปลความหมายของคำสั่ง
(interpret instruction) คำสั่งจะถูกแปลความหมาย
เพื่อจะได้ทราบว่า คำสั่งนั้นต้องการ
ให้ทำงานอย่างใด
- ดึงข้อมูล (fetch
data) การประมวลผลคำสั่งเครื่องหนึ่งคำสั่ง
อาจจำเป็นต้องอ่านข้อมูลจากหน่วยความจำหลักหรืออุปกรณ์
ไอโอเข้ามาด้วย
- ประมวลผลข้อมูล (process
data) การประมวลผลคำสั่งอาจเกี่ยวข้องกับการทำงานทางคณิตศาสตร์หรือตรรกะ
- การบันทึกข้อมูล (write
data) ผลการประมวลผลข้อมูลอาจต้องการให้บันทึกผลลัพธ์ที่ได้ไว้ในหน่วยความจำหลักหรืออุปกรณ์ไอโอ