ประการแรกการเข้าถึงหน่วยความจำหลักมีราคาแพงมาก ปัจจุบันซีพียู 2GHz (ช้าที่สุดหนึ่งครั้ง) มี 2G ticks (รอบ) ต่อวินาที CPU (คอร์เสมือนในปัจจุบัน) สามารถดึงค่าจากการลงทะเบียนหนึ่งครั้งต่อหนึ่งขีด เนื่องจากแกนประมวลผลเสมือนประกอบด้วยหน่วยประมวลผลหลายหน่วย (ALU - หน่วยคำนวณทางคณิตศาสตร์, FPU ฯลฯ ) จึงสามารถประมวลผลคำสั่งบางอย่างพร้อมกันได้ถ้าเป็นไปได้
การเข้าถึงหน่วยความจำหลักมีค่าใช้จ่ายประมาณ 70ns ถึง 100ns (DDR4 เร็วกว่าเล็กน้อย) เวลานี้โดยทั่วไปแล้วมองหาแคช L1, L2 และ L3 และกว่ากดหน่วยความจำ (ส่งคำสั่งไปยังตัวควบคุมหน่วยความจำซึ่งส่งไปยังหน่วยความจำธนาคาร) รอการตอบสนองและทำ
100ns หมายถึงประมาณ 200 เห็บ ดังนั้นโดยทั่วไปหากโปรแกรมมักจะพลาดแคชที่แต่ละหน่วยความจำเข้าถึง CPU จะใช้เวลาประมาณ 99,5% ของเวลา (หากเป็นเพียงการอ่านหน่วยความจำเท่านั้น) ว่างเพื่อรอหน่วยความจำ
เพื่อเร่งความเร็วสิ่งต่าง ๆ นั่นคือ L1, L2, L3 แคช พวกเขาใช้หน่วยความจำวางโดยตรงบนชิปและใช้วงจรทรานซิสเตอร์ชนิดอื่นเพื่อเก็บบิตที่กำหนด ใช้พลังงานมากขึ้นและมีราคาแพงกว่าหน่วยความจำหลักเนื่องจาก CPU มักจะผลิตโดยใช้เทคโนโลยีขั้นสูงและความล้มเหลวในการผลิตในหน่วยความจำ L1, L2, L3 จึงมีโอกาสทำให้ CPU ไร้ค่า (ข้อบกพร่อง) ดังนั้น L1 ขนาดใหญ่, L2, L3 แคชเพิ่มอัตราความผิดพลาดซึ่งจะลดผลตอบแทนที่ลดลง ROI โดยตรง ดังนั้นจึงมีการแลกเปลี่ยนขนาดใหญ่เมื่อมันมาถึงขนาดแคชที่มีอยู่
(ปัจจุบันมีการสร้างแคช L1, L2 และ L3 มากขึ้นเพื่อให้สามารถปิดการใช้งานบางส่วนเพื่อลดโอกาสที่ข้อบกพร่องในการผลิตจริงคือพื้นที่หน่วยความจำแคชทำให้หน่วยความจำแคชแสดงผลข้อบกพร่องทั้งหมด)
เพื่อให้แนวคิดเกี่ยวกับเวลา (แหล่งที่มา: ต้นทุนในการเข้าถึงแคชและหน่วยความจำ )
- L1 cache: 1ns ถึง 2ns (2-4 รอบ)
- L2 Cache: 3ns ถึง 5ns (6-10 รอบ)
- L3 cache: 12ns ถึง 20ns (24-40 รอบ)
- RAM: 60ns (120 รอบ)
เนื่องจากเราผสมประเภท CPU ที่แตกต่างกันสิ่งเหล่านี้เป็นเพียงการประมาณ แต่ให้ความคิดที่ดีว่าเกิดอะไรขึ้นเมื่อค่าหน่วยความจำถูกดึงออกมาและเราอาจได้รับผลกระทบหรือพลาดในชั้นแคชบางอย่าง
โดยทั่วไปแคชจะเพิ่มความเร็วในการเข้าถึงหน่วยความจำอย่างมาก (60ns เทียบกับ 1ns)
การดึงค่ามาเก็บไว้ในแคชเพื่อโอกาสในการอ่านซ้ำนั้นดีสำหรับตัวแปรที่เข้าถึงได้บ่อย แต่สำหรับการดำเนินการคัดลอกหน่วยความจำมันจะยังคงช้าเนื่องจากมีคนอ่านค่าเขียนค่าที่อื่นและไม่เคยอ่านค่า อีกครั้ง ... ไม่พบแคช, ช้าตาย (นอกจากนี้อาจเกิดขึ้นพร้อมกันเนื่องจากเราไม่ได้ดำเนินการตามคำสั่ง)
การคัดลอกหน่วยความจำนี้สำคัญมากที่จะมีวิธีการที่แตกต่างกันในการเพิ่มความเร็ว ในหน่วยความจำวันแรกมักจะสามารถคัดลอกหน่วยความจำนอก CPU มันถูกจัดการโดยตัวควบคุมหน่วยความจำโดยตรงดังนั้นการดำเนินการคัดลอกหน่วยความจำจึงไม่ก่อให้เกิดมลพิษกับแคช
แต่นอกเหนือจากการคัดลอกหน่วยความจำธรรมดาการเข้าถึงหน่วยความจำแบบอนุกรมเป็นเรื่องปกติ ตัวอย่างคือการวิเคราะห์ชุดข้อมูล การมีอาร์เรย์ของจำนวนเต็มและผลรวมของการคำนวณค่าเฉลี่ยค่าเฉลี่ยหรือแม้แต่การค้นหาค่าที่แน่นอน (ตัวกรอง / การค้นหา) เป็นอีกระดับหนึ่งที่สำคัญมากของอัลกอริทึมที่ทำงานทุกครั้งบน CPU ที่มีวัตถุประสงค์ทั่วไป
ดังนั้นจากการวิเคราะห์รูปแบบการเข้าถึงหน่วยความจำจึงเห็นได้ชัดว่าข้อมูลอ่านตามลำดับบ่อยมาก มีความน่าจะเป็นสูงที่หากโปรแกรมอ่านค่าที่ดัชนีฉันว่าโปรแกรมจะอ่านค่า i + 1 ด้วย ความน่าจะเป็นนี้สูงกว่าความน่าจะเป็นที่โปรแกรมเดียวกันจะอ่านค่า i + 2 และอื่น ๆ
ดังนั้นเมื่อกำหนดที่อยู่หน่วยความจำแล้ว (และยังคงเป็น) เป็นความคิดที่ดีที่จะอ่านล่วงหน้าและดึงค่าเพิ่มเติม นี่คือเหตุผลว่าทำไมมีโหมดเพิ่ม
การเข้าถึงหน่วยความจำในโหมดเพิ่มประสิทธิภาพหมายถึงว่าที่อยู่นั้นถูกส่งและมีหลายค่าที่ส่งต่อเนื่องกัน แต่ละค่าเพิ่มเติมที่ส่งจะใช้เวลาประมาณ 10ns เพิ่มเติม (หรือต่ำกว่า)
ปัญหาอื่นคือที่อยู่ การส่งที่อยู่ต้องใช้เวลา เพื่อส่งหน่วยความจำส่วนใหญ่จะต้องส่งที่อยู่ขนาดใหญ่ ในวันแรกมันหมายความว่าที่อยู่บัสไม่ใหญ่พอที่จะส่งที่อยู่ในรอบเดียว (ติ๊ก) และมากกว่าหนึ่งรอบจะต้องส่งที่อยู่เพิ่มล่าช้ามากขึ้น
อินไลน์แคชขนาด 64 ไบต์หมายความว่าหน่วยความจำจะถูกแบ่งออกเป็นบล็อกขนาดต่าง ๆ (ไม่ทับซ้อนกัน) ของหน่วยความจำที่มีขนาด 64 ไบต์ 64bytes หมายถึงที่อยู่เริ่มต้นของแต่ละบล็อกมีบิตที่อยู่หกที่ต่ำที่สุดที่จะเป็นศูนย์เสมอ ดังนั้นการส่งบิตหกศูนย์เหล่านี้ในแต่ละครั้งจึงไม่จำเป็นต้องเพิ่มพื้นที่ที่อยู่ 64 เท่าสำหรับความกว้างของบัสแอดเดรสใด ๆ (เอฟเฟกต์ต้อนรับ)
ปัญหาอีกประการหนึ่งที่บรรทัดแคชจะแก้ไข (ข้างการอ่านล่วงหน้าและการบันทึก / เพิ่มหกบิตบนบัสแอดเดรส) คือวิธีการจัดระเบียบแคช ตัวอย่างเช่นหากแคชจะแบ่งออกเป็น 8 ไบต์ (64 บิต) บล็อก (เซลล์) หนึ่งต้องเก็บที่อยู่ของเซลล์หน่วยความจำเซลล์แคชนี้เก็บค่าไว้พร้อมกับมัน หากที่อยู่จะเป็น 64 บิตนั่นหมายความว่าครึ่งหนึ่งของขนาดแคชจะถูกใช้โดยที่อยู่ซึ่งทำให้เกิดค่าใช้จ่าย 100%
เนื่องจากบรรทัดแคชคือ 64bytes และ CPU อาจใช้ 64 บิต - 6 บิต = 58 บิต (ไม่จำเป็นต้องเก็บบิตศูนย์ให้ถูกต้องเกินไป) หมายความว่าเราสามารถแคช 64 ไบต์หรือ 512 บิตด้วยค่าใช้จ่าย 58 บิต (11% ค่าใช้จ่าย) ในความเป็นจริงที่อยู่ที่เก็บไว้มีขนาดเล็กกว่านี้ แต่มีข้อมูลสถานะ (เช่นเป็นบรรทัดแคชที่ถูกต้องและถูกต้องสกปรกและจำเป็นต้องเขียนกลับในหน่วยความจำ ฯลฯ )
อีกแง่มุมหนึ่งคือเรามีแคชแบบเชื่อมโยงไว้ ไม่ใช่ทุกเซลล์แคชสามารถจัดเก็บที่อยู่ที่แน่นอน แต่เป็นชุดย่อยของที่อยู่เหล่านั้นเท่านั้น สิ่งนี้ทำให้บิตแอดเดรสที่เก็บไว้ที่จำเป็นมีขนาดเล็กลงทำให้สามารถเข้าถึงแคชแบบขนานได้ (แต่ละเซ็ตย่อยสามารถเข้าถึงได้ครั้งเดียว แต่เป็นอิสระจากเซ็ตย่อยอื่น ๆ )
โดยเฉพาะอย่างยิ่งเมื่อมีการซิงโครไนซ์การเข้าถึงแคช / หน่วยความจำระหว่างคอร์เสมือนที่แตกต่างกันหน่วยประมวลผลหลายหน่วยที่เป็นอิสระต่อหนึ่งคอร์และในที่สุดโปรเซสเซอร์หลายตัวบนเมนบอร์ดหนึ่งตัว
นี่เป็นแนวคิดพื้นฐานที่ว่าทำไมเราถึงมีแคช ประโยชน์จากการอ่านล่วงหน้าสูงมากและกรณีที่เลวร้ายที่สุดในการอ่านไบต์เดียวจากแคชไลน์และไม่เคยอ่านส่วนที่เหลืออีกเลยจะบางมากเนื่องจากความน่าจะเป็นนั้นแคบมาก
ขนาดของแคชไลน์ (64) คือการแลกเปลี่ยนที่เลือกอย่างชาญฉลาดระหว่างแคชไลน์ขนาดใหญ่ทำให้ไม่สามารถอ่านไบต์สุดท้ายของมันได้ในอนาคตอันใกล้ระยะเวลาที่ใช้ในการดึงแคชไลน์ที่สมบูรณ์ จากหน่วยความจำ (และเพื่อเขียนกลับ) และค่าใช้จ่ายในองค์กรแคชและการขนานของการเข้าถึงแคชและหน่วยความจำ