เป็นที่ยอมรับฉันไม่ได้รับมัน สมมติว่าคุณมีหน่วยความจำที่มีหน่วยความจำความยาว 1 ไบต์ ทำไมคุณไม่สามารถเข้าถึงตัวแปรความยาว 4 ไบต์ในการเข้าถึงหน่วยความจำเดียวในที่อยู่ที่ไม่ได้ลงนาม (เช่นไม่หารด้วย 4) เนื่องจากเป็นกรณีที่มีที่อยู่ที่จัดชิด
เป็นที่ยอมรับฉันไม่ได้รับมัน สมมติว่าคุณมีหน่วยความจำที่มีหน่วยความจำความยาว 1 ไบต์ ทำไมคุณไม่สามารถเข้าถึงตัวแปรความยาว 4 ไบต์ในการเข้าถึงหน่วยความจำเดียวในที่อยู่ที่ไม่ได้ลงนาม (เช่นไม่หารด้วย 4) เนื่องจากเป็นกรณีที่มีที่อยู่ที่จัดชิด
คำตอบ:
มันเป็นข้อ จำกัด ของโปรเซสเซอร์พื้นฐานมากมาย โดยทั่วไปแล้วจะสามารถแก้ไขได้ด้วยการทำไบต์เดี่ยว 4 ไบต์ที่ไม่มีประสิทธิภาพแทนการดึงคำศัพท์ที่มีประสิทธิภาพ แต่ตัวระบุภาษาจำนวนมากตัดสินใจว่าจะง่ายกว่าที่จะประกาศพวกเขาและบังคับให้ทุกอย่างเรียงกัน
มีข้อมูลเพิ่มเติมในลิงค์นี้ที่ OP ค้นพบ
ระบบย่อยหน่วยความจำของโปรเซสเซอร์ที่ทันสมัยนั้นถูก จำกัด ให้เข้าถึงหน่วยความจำที่มีความละเอียดและการปรับขนาดของคำ นี่เป็นกรณีด้วยเหตุผลหลายประการ
ตัวประมวลผลสมัยใหม่มีหน่วยความจำแคชหลายระดับที่ต้องดึงข้อมูล การสนับสนุนการอ่านไบต์เดียวจะทำให้การส่งผ่านระบบย่อยหน่วยความจำถูกผูกไว้อย่างแน่นหนากับปริมาณงานของการประมวลผล (aka cpu-bound) นี่เป็นการระลึกถึงวิธีที่โหมด PIO ถูกค้นพบโดย DMAด้วยเหตุผลหลายประการในฮาร์ดไดรฟ์
ซีพียูจะอ่านที่ขนาดของคำ (4 ไบต์บนตัวประมวลผลแบบ 32 บิต) เสมอดังนั้นเมื่อคุณทำการเข้าถึงที่อยู่ที่ไม่ได้ลงนาม - บนตัวประมวลผลที่รองรับ - ตัวประมวลผลจะอ่านหลายคำ CPU จะอ่านหน่วยความจำแต่ละคำตามที่อยู่ที่คุณร้องขอ สิ่งนี้ทำให้การขยายจำนวนมากถึง 2X ของจำนวนธุรกรรมหน่วยความจำที่จำเป็นในการเข้าถึงข้อมูลที่ร้องขอ
ด้วยเหตุนี้มันจึงช้ามากในการอ่านสองไบต์มากกว่าสี่ ตัวอย่างเช่นสมมติว่าคุณมีโครงสร้างในหน่วยความจำที่มีลักษณะดังนี้:
struct mystruct {
char c; // one byte
int i; // four bytes
short s; // two bytes
}
บนโปรเซสเซอร์ 32 บิตดูเหมือนว่าจะถูกจัดเรียงตามที่แสดงที่นี่:
โปรเซสเซอร์สามารถอ่านสมาชิกแต่ละคนเหล่านี้ในการทำธุรกรรมเดียว
สมมติว่าคุณมีโครงสร้างรุ่นที่รวบรวมมาอาจจะมาจากเครือข่ายที่บรรจุเพื่อประสิทธิภาพในการส่งข้อมูล มันอาจมีลักษณะเช่นนี้:
การอ่านไบต์แรกจะเหมือนกัน
เมื่อคุณขอให้ตัวประมวลผลให้ 16 บิตจาก 0x0005 มันจะต้องอ่านคำจาก 0x0004 และเลื่อนซ้าย 1 ไบต์เพื่อวางไว้ในการลงทะเบียน 16 บิต งานพิเศษบางอย่าง แต่ส่วนใหญ่สามารถจัดการในรอบเดียว
เมื่อคุณขอ 32 บิตจาก 0x0001 คุณจะได้แอมพลิฟายเออร์ 2X ตัวประมวลผลจะอ่านจาก 0x0000 ไปยังการลงทะเบียนผลลัพธ์และเลื่อนไปทางซ้าย 1 ไบต์จากนั้นอ่านอีกครั้งจาก 0x0004 ไปเป็นการลงทะเบียนชั่วคราวเลื่อนไปทางขวา 3 ไบต์จากนั้นOR
ด้วยการลงทะเบียนผลลัพธ์
สำหรับพื้นที่ที่อยู่ที่กำหนดหากสถาปัตยกรรมสามารถสันนิษฐานได้ว่า 2 LSBs นั้นเป็น 0 เสมอ (เช่นเครื่อง 32- บิต) จากนั้นจะสามารถเข้าถึงหน่วยความจำได้มากขึ้น 4 เท่า (หน่วยความจำที่บันทึกไว้ 2 บิตสามารถแทน 4 สถานะที่แตกต่างกัน) หรือจำนวนเดียวกัน ของหน่วยความจำที่มี 2 บิตสำหรับบางสิ่งบางอย่างเช่นธง การถอด 2 LSB ออกจากที่อยู่จะช่วยให้คุณจัดตำแหน่ง 4 ไบต์ เรียกอีกอย่างว่าก้าวย่างของ 4 ไบต์ ทุกครั้งที่มีการเพิ่มที่อยู่จะเป็นการเพิ่มบิต 2 อย่างมีประสิทธิภาพไม่ใช่บิต 0 เช่น 2 บิตสุดท้ายจะยังคงเป็น00
เช่นเดิม
สิ่งนี้สามารถส่งผลกระทบต่อการออกแบบทางกายภาพของระบบ หากที่อยู่บัสต้องการบิตที่น้อยกว่า 2 บิตอาจมีพินน้อยกว่าบน CPU และมีร่องรอยบนแผงวงจรน้อยกว่า 2
ซีพียูสามารถทำงานกับคำที่สอดคล้องกันของหน่วยความจำแบบอะตอมหมายความว่าไม่มีคำสั่งอื่นใดสามารถขัดจังหวะการทำงานนั้นได้ สิ่งนี้มีความสำคัญต่อการดำเนินการที่ถูกต้องของโครงสร้างข้อมูลที่ไม่ล็อคและกระบวนทัศน์การทำงานพร้อมกันอื่น ๆ
ระบบหน่วยความจำของโปรเซสเซอร์นั้นค่อนข้างซับซ้อนและเกี่ยวข้องมากกว่าที่อธิบายไว้ที่นี่ การสนทนาเกี่ยวกับวิธีที่โปรเซสเซอร์ x86 ระบุตำแหน่งหน่วยความจำจริงสามารถช่วยได้ (โปรเซสเซอร์จำนวนมากทำงานคล้ายกัน)
มีประโยชน์อื่น ๆ อีกมากมายที่จะยึดมั่นในการจัดตำแหน่งของหน่วยความจำที่คุณสามารถอ่านได้ที่บทความนี้ไอบีเอ็ม
การใช้งานหลักของคอมพิวเตอร์คือการแปลงข้อมูล สถาปัตยกรรมและเทคโนโลยีหน่วยความจำที่ทันสมัยได้รับการปรับปรุงให้ดีขึ้นกว่าทศวรรษเพื่ออำนวยความสะดวกในการรับข้อมูลมากขึ้น, เข้า, ออก, และระหว่างหน่วยปฏิบัติงานมากขึ้นและเร็วขึ้น - ในลักษณะที่เชื่อถือได้
การจัดตำแหน่งแบบใหม่สำหรับประสิทธิภาพที่ฉันพูดถึงก่อนหน้านี้คือการจัดตำแหน่งบนบรรทัดแคชซึ่ง (ตัวอย่างเช่นในบาง CPU) 64B
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการปฏิบัติงานมากสามารถได้รับจากการใช้ประโยชน์จากแคช, ดูที่แกลลอรี่ของตัวประมวลผลผลกระทบแคช ; จากคำถามนี้เกี่ยวกับขนาดแคชบรรทัด
การทำความเข้าใจกับบรรทัดแคชอาจมีความสำคัญสำหรับการเพิ่มประสิทธิภาพของโปรแกรมบางประเภท ตัวอย่างเช่นการจัดตำแหน่งของข้อมูลอาจกำหนดว่าการดำเนินการสัมผัสหนึ่งหรือสองบรรทัดแคช ดังที่เราเห็นในตัวอย่างด้านบนสิ่งนี้อาจหมายถึงว่าในกรณีที่ไม่ตรงแนวการดำเนินการจะช้าลงเป็นสองเท่า
คุณสามารถใช้โปรเซสเซอร์บางตัว ( Nehalem สามารถทำสิ่งนี้ได้ ) แต่ก่อนหน้านี้การเข้าถึงหน่วยความจำทั้งหมดถูกจัดตำแหน่งบนบรรทัด 64 บิต (หรือ 32 บิต) เนื่องจากบัสมีความกว้าง 64 บิตคุณต้องดึงข้อมูล 64 บิตในแต่ละครั้ง และมันง่ายกว่ามากในการดึงข้อมูลเหล่านี้ใน 'chunks' ที่มีขนาด 64 บิต
ดังนั้นหากคุณต้องการรับไบต์เดียวคุณจะได้รับข้อมูล 64 บิตจากนั้นปิดบังบิตที่คุณไม่ต้องการ ง่ายและรวดเร็วถ้าไบต์ของคุณอยู่ที่ปลายด้านขวา แต่ถ้าอยู่ในช่วงกลางของบิต 64 บิตคุณจะต้องปกปิดบิตที่ไม่ต้องการแล้วเลื่อนข้อมูลไปยังตำแหน่งที่ถูกต้อง ที่แย่กว่านั้นถ้าคุณต้องการตัวแปร 2 ไบต์ แต่นั่นถูกแบ่งออกเป็น 2 ชิ้นนั่นหมายความว่าการเข้าถึงหน่วยความจำที่จำเป็นต้องเพิ่มเป็นสองเท่า
ดังนั้นเมื่อทุกคนคิดว่าหน่วยความจำราคาถูกพวกเขาเพียงแค่คอมไพเลอร์จัดเรียงข้อมูลบนขนาดก้อนของโปรเซสเซอร์เพื่อให้โค้ดของคุณทำงานได้เร็วขึ้นและมีประสิทธิภาพมากขึ้นในราคาหน่วยความจำที่สูญเปล่า
โดยพื้นฐานแล้วสาเหตุคือเม็มโมรี่บัสมีความยาวบางขนาดที่เล็กกว่าขนาดหน่วยความจำมาก
ดังนั้นซีพียูจึงอ่านแคช L1 บนชิปซึ่งมักจะเป็น 32KB ในปัจจุบัน แต่หน่วยความจำบัสที่เชื่อมต่อแคช L1 กับ CPU จะมีความกว้างน้อยกว่าขนาดแคชของขนาดสายแคช นี้จะเป็นคำสั่งของ 128 บิต
ดังนั้น:
262,144 bits - size of memory
128 bits - size of bus
การเข้าถึงที่ไม่ตรงแนวจะซ้อนทับแคชสองครั้งเป็นครั้งคราวและสิ่งนี้จะต้องมีการอ่านแคชใหม่ทั้งหมดเพื่อรับข้อมูล มันอาจจะพลาดไปไกลถึง DRAM
นอกจากนี้บางส่วนของ CPU จะต้องยืนบนหัวของมันเพื่อรวบรวมวัตถุชิ้นเดียวจากสองบรรทัดแคชที่ต่างกันซึ่งแต่ละชิ้นมีข้อมูลหนึ่งชิ้น ในหนึ่งบรรทัดมันจะอยู่ในบิตการสั่งซื้อที่สูงมากและอีกบิตการสั่งซื้อที่ต่ำมาก
จะมีฮาร์ดแวร์เฉพาะที่รวมเข้ากับไปป์ไลน์ที่จัดการการเคลื่อนย้ายวัตถุที่จัดตำแหน่งไว้บนบิตที่จำเป็นของ CPU data bus แต่ฮาร์ดแวร์ดังกล่าวอาจขาดสำหรับวัตถุที่ไม่ได้แนวเนื่องจากอาจทำให้เหมาะสมกว่าที่จะใช้ทรานซิสเตอร์เหล่านั้น โปรแกรม
ไม่ว่าในกรณีใดหน่วยความจำที่สองที่อ่านซึ่งบางครั้งมีความจำเป็นจะทำให้การทำงานช้าลงไม่ว่าฮาร์ดแวร์วัตถุประสงค์พิเศษมากเพียงใด
@ Joshersry ได้ให้คำตอบที่ดีสำหรับคำถามนี้ นอกเหนือจากคำตอบของเขาแล้วฉันยังมีตัวเลขบางตัวที่แสดงเอฟเฟกต์กราฟิกที่อธิบายไว้โดยเฉพาะอย่างยิ่งแอมพลิฟายเออร์ 2X นี่คือลิงก์ไปยังสเปรดชีตของ Google ที่แสดงว่าลักษณะของการจัดเรียงคำที่ต่างกันมีลักษณะอย่างไร นอกจากนี้ยังมีลิงก์ไปยังส่วนสำคัญ Githubพร้อมรหัสสำหรับการทดสอบ รหัสทดสอบถูกดัดแปลงจากบทความที่เขียนโดย Jonathan Rentzsch ซึ่ง @joshperry อ้างอิง การทดสอบดำเนินการบน Macbook Pro พร้อมโปรเซสเซอร์ Quad-Core 2.8 GHz Intel Core i7 64 บิตและ RAM ขนาด 16GB
x
และy
พิกัดหมายความว่าอย่างไร
หากระบบที่มีหน่วยความจำที่สามารถระบุตำแหน่งไบต์มีบัสหน่วยความจำแบบ 32 บิตนั่นหมายความว่ามีระบบหน่วยความจำทั้งสี่ไบต์ที่มีสายอย่างมีประสิทธิภาพซึ่งทั้งหมดเชื่อมต่อเพื่ออ่านหรือเขียนที่อยู่เดียวกัน การอ่านแบบ 32 บิตที่มีการจัดแนวจะต้องใช้ข้อมูลที่เก็บไว้ในที่อยู่เดียวกันในระบบหน่วยความจำทั้งสี่ระบบดังนั้นระบบทั้งหมดจึงสามารถให้ข้อมูลได้พร้อมกัน การอ่านแบบ 32 บิตที่ไม่ได้แนวจะต้องใช้ระบบหน่วยความจำบางอย่างในการส่งคืนข้อมูลจากที่อยู่หนึ่งและบางระบบต้องส่งคืนข้อมูลจากที่อยู่ถัดไปที่สูงกว่า แม้ว่าจะมีระบบหน่วยความจำบางส่วนที่ปรับให้เหมาะสมเพื่อให้สามารถตอบสนองคำขอดังกล่าวได้ (นอกเหนือจากที่อยู่ของพวกเขาแล้วพวกเขายังมีสัญญาณ "บวกหนึ่ง" ซึ่งทำให้พวกเขาใช้ที่อยู่หนึ่งสูงกว่าที่ระบุ) คุณลักษณะดังกล่าว และความซับซ้อนของระบบหน่วยความจำ
หากคุณมีบัสข้อมูล 32 บิตสายที่อยู่ของบัสแอดเดรสที่เชื่อมต่อกับหน่วยความจำจะเริ่มจาก A 2ดังนั้นที่อยู่ที่จัดชิด 32 บิตเท่านั้นจึงจะสามารถเข้าถึงได้ในรอบบัสเดียว
ดังนั้นหากคำครอบคลุมขอบเขตการจัดตำแหน่งที่อยู่ - เช่น A 0สำหรับข้อมูล 16/32 บิตหรือ A 1สำหรับข้อมูล 32 บิตไม่ใช่ศูนย์จำเป็นต้องใช้สองรอบรถบัสเพื่อรับข้อมูล
ชุดสถาปัตยกรรม / คำสั่งบางชุดไม่รองรับการเข้าถึงที่ไม่ได้กำหนดและจะสร้างข้อยกเว้นสำหรับความพยายามดังกล่าวดังนั้นคอมไพเลอร์ที่สร้างรหัสการเข้าถึงที่ไม่ได้จัดแนวนั้นไม่เพียงแค่ต้องการเพิ่มรอบบัส แต่ยังมีคำแนะนำเพิ่มเติม
บน PowerPC คุณสามารถโหลดจำนวนเต็มจากที่อยู่แปลก ๆ โดยไม่มีปัญหา
Sparc และ I86 และ (ฉันคิดว่า) Itatnium ยกข้อยกเว้นฮาร์ดแวร์เมื่อคุณลองใช้
โหลด 32 บิตหนึ่งตัวเทียบกับโหลด 8 บิตสี่ตัวจะไม่สร้างความแตกต่างอย่างมากมายให้กับโปรเซสเซอร์ที่ทันสมัยที่สุด ไม่ว่าข้อมูลจะอยู่ในแคชหรือไม่จะมีผลกระทบมากขึ้น