วิธีเพิ่มความเร็วโค้ดของคุณโดยใช้แคช CPU

แคชของ CPU ช่วยลดเวลาแฝงของหน่วยความจำเมื่อมีการเข้าถึงข้อมูลจากหน่วยความจำระบบหลัก นักพัฒนาสามารถและควรใช้ประโยชน์จากแคชของ CPU เพื่อปรับปรุงประสิทธิภาพของแอปพลิเคชัน

วิธีการทำงานของแคช CPU

โดยทั่วไปแล้วซีพียูสมัยใหม่จะมีแคชสามระดับชื่อ L1, L2 และ L3 ซึ่งแสดงถึงลำดับที่ CPU ตรวจสอบ ซีพียูมักจะมีแคชข้อมูลแคชคำสั่ง (สำหรับรหัส) และแคชแบบรวม (สำหรับอะไรก็ได้) การเข้าถึงแคชเหล่านี้เร็วกว่าการเข้าถึง RAM มาก: โดยปกติแคช L1 จะเร็วกว่า RAM สำหรับการเข้าถึงข้อมูลประมาณ 100 เท่าและแคช L2 เร็วกว่า RAM 25 เท่าสำหรับการเข้าถึงข้อมูล

เมื่อซอฟต์แวร์ของคุณทำงานและจำเป็นต้องดึงข้อมูลหรือคำแนะนำแคชของ CPU จะถูกตรวจสอบก่อนจากนั้น RAM ของระบบที่ช้าลงและในที่สุดดิสก์ไดรฟ์ที่ช้าลงมาก นั่นเป็นเหตุผลที่คุณต้องการเพิ่มประสิทธิภาพโค้ดของคุณเพื่อค้นหาสิ่งที่น่าจะจำเป็นจากแคชของ CPU ก่อน

รหัสของคุณไม่สามารถระบุว่าคำแนะนำข้อมูลและข้อมูลอยู่ที่ใด - ฮาร์ดแวร์ของคอมพิวเตอร์ทำเช่นนั้นคุณจึงไม่สามารถบังคับองค์ประกอบบางอย่างในแคชของ CPU ได้ แต่คุณสามารถเพิ่มประสิทธิภาพโค้ดของคุณเพื่อดึงขนาดของแคช L1, L2 หรือ L3 ในระบบของคุณโดยใช้ Windows Management Instrumentation (WMI) เพื่อเพิ่มประสิทธิภาพเมื่อแอปพลิเคชันของคุณเข้าถึงแคชและทำให้ประสิทธิภาพของมัน

ซีพียูไม่เคยเข้าถึงแคชไบต์ไบต์ แต่จะอ่านหน่วยความจำในบรรทัดแคชซึ่งเป็นหน่วยความจำโดยทั่วไปมีขนาด 32, 64 หรือ 128 ไบต์

รายการรหัสต่อไปนี้แสดงให้เห็นว่าคุณสามารถดึงขนาดแคช L2 หรือ L3 CPU ในระบบของคุณได้อย่างไร:

uint แบบคงที่สาธารณะ GetCPUCacheSize (string cacheType) {ลองใช้ (ManagementObject managementObject = new ManagementObject ("Win32_Processor.DeviceID = 'CPU0')) {return (uint) (managementObject [cacheType]); }} จับ {กลับ 0; }} โมฆะคงที่ Main (สตริง [] args) {uint L2CacheSize = GetCPUCacheSize ("L2CacheSize"); uint L3CacheSize = GetCPUCacheSize ("L3CacheSize"); Console.WriteLine ("L2CacheSize:" + L2CacheSize ToString ()); Console.WriteLine ("L3CacheSize:" + L3CacheSize ToString ()); Console.Read (); }

Microsoft มีเอกสารเพิ่มเติมเกี่ยวกับคลาส Win32_Processor WMI

การเขียนโปรแกรมเพื่อประสิทธิภาพ: โค้ดตัวอย่าง

เมื่อคุณมีวัตถุในสแต็กจะไม่มีค่าใช้จ่ายในการรวบรวมขยะ หากคุณใช้อ็อบเจ็กต์ที่ใช้ฮีปจะมีค่าใช้จ่ายที่เกี่ยวข้องกับการรวบรวมขยะในรุ่นสำหรับการรวบรวมหรือเคลื่อนย้ายวัตถุในฮีปหรือการบีบอัดหน่วยความจำฮีป วิธีที่ดีในการหลีกเลี่ยงค่าใช้จ่ายในการรวบรวมขยะคือการใช้โครงสร้างแทนคลาส

แคชจะทำงานได้ดีที่สุดหากคุณใช้โครงสร้างข้อมูลตามลำดับเช่นอาร์เรย์ การจัดลำดับตามลำดับช่วยให้ CPU สามารถอ่านล่วงหน้าและอ่านล่วงหน้าโดยคาดเดาได้ว่าจะมีการร้องขออะไรต่อไป ดังนั้นอัลกอริทึมที่เข้าถึงหน่วยความจำตามลำดับจึงรวดเร็วเสมอ

หากคุณเข้าถึงหน่วยความจำแบบสุ่มซีพียูจำเป็นต้องมีบรรทัดแคชใหม่ทุกครั้งที่คุณเข้าถึงหน่วยความจำ ที่ช่วยลดประสิทธิภาพ

ข้อมูลโค้ดต่อไปนี้ใช้โปรแกรมง่ายๆที่แสดงให้เห็นถึงประโยชน์ของการใช้โครงสร้างบนคลาส:

 โครงสร้าง RectangleStruct {int สาธารณะกว้าง; ความสูง int สาธารณะ } คลาส RectangleClass {public int กว้าง; ความสูง int สาธารณะ }

โค้ดต่อไปนี้กำหนดโปรไฟล์ประสิทธิภาพของการใช้อาร์เรย์ของโครงสร้างกับอาร์เรย์ของคลาส เพื่อจุดประสงค์ในการอธิบายฉันใช้วัตถุเป็นล้านชิ้นสำหรับทั้งสองอย่าง แต่โดยทั่วไปแล้วคุณไม่ต้องการวัตถุจำนวนมากในแอปพลิเคชัน

โมฆะคงหลัก (สตริง [] args) {const int size = 1000000; var structs = RectangleStruct ใหม่ [ขนาด]; var คลาส = RectangleClass ใหม่ [ขนาด]; var sw = นาฬิกาจับเวลาใหม่ (); สว. เริ่ม (); สำหรับ (var i = 0; i <size; ++ i) {structs [i] = RectangleStruct ใหม่ (); โครงสร้าง [i] .breadth = 0 โครงสร้าง [i] .height = 0; } var structTime = sw.ElapsedMilliseconds; สว. รีเซ็ต (); สว. เริ่ม (); สำหรับ (var i = 0; i <size; ++ i) {คลาส [i] = RectangleClass ใหม่ (); คลาส [i] .breadth = 0; ชั้นเรียน [i] .height = 0; } var classTime = sw.ElapsedMilliseconds; สว. หยุด (); Console.WriteLine ("เวลาที่ใช้โดยอาร์เรย์ของคลาส:" + classTimetoString () + "มิลลิวินาที"); Console.WriteLine ("เวลาที่ใช้โดยอาร์เรย์ของโครงสร้าง:" + structTime ToString () + "มิลลิวินาที"); Console.Read (); }

โปรแกรมนี้ง่ายมาก: สร้างโครงสร้างวัตถุ 1 ล้านชิ้นและเก็บไว้ในอาร์เรย์ นอกจากนี้ยังสร้างวัตถุ 1 ล้านชิ้นของคลาสและเก็บไว้ในอาร์เรย์อื่น ความกว้างและความสูงของคุณสมบัติถูกกำหนดค่าเป็นศูนย์สำหรับแต่ละอินสแตนซ์

อย่างที่คุณเห็นการใช้โครงสร้างที่เป็นมิตรกับแคชจะให้ประสิทธิภาพที่เพิ่มขึ้นอย่างมาก

กฎง่ายๆสำหรับการใช้แคช CPU ที่ดีขึ้น

แล้วคุณจะเขียนโค้ดที่ใช้แคช CPU ได้ดีที่สุดอย่างไร? น่าเสียดายที่ไม่มีสูตรวิเศษ แต่มีกฎง่ายๆ:

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