ประสิทธิภาพของรหัส ADT ที่มุ่งเน้นการกำหนดเดียวบน CPU ที่ทันสมัย


32

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

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

ฉันหวังว่าจะมีใครซักคนที่จะเข้าใจว่าเรื่องนี้เกิดขึ้นจริงได้อย่างไร (หรือถ้าไม่ใช่)

ในความคิดเห็นในโพสต์อื่นถูกกล่าวถึงว่าAbstract Data Types (ADT's) เกี่ยวข้องกับสิ่งนี้ซึ่งทำให้ฉันอยากรู้เพิ่มเติมว่า ADT มีผลเฉพาะวิธีที่ CPU ใช้กับหน่วยความจำอย่างไร อย่างไรก็ตามนี่เป็นสิ่งที่แยกกันส่วนใหญ่ฉันแค่สนใจว่าความบริสุทธิ์ของภาษานั้นมีผลต่อประสิทธิภาพของ CPU และแคช ฯลฯ อย่างไร


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

@ ratchetfreak ฉันได้รับจากจุดยืนการเขียนโปรแกรมที่รหัสของคุณได้รับความปลอดภัยมากขึ้น แต่อยากรู้อยากเห็นของฉันเป็นเรื่องเกี่ยวกับตัวควบคุมหน่วยความจำบน CPU และพฤติกรรมนี้มีความสำคัญกับมัน (หรือถ้ามันไม่) ตามที่ฉันได้ยินอ้าง bandied เกี่ยวกับมือที่เต็มไปด้วยเวลาที่บอกว่ามันมีประสิทธิภาพมากขึ้นสำหรับตัวควบคุมหน่วยความจำและฉันไม่ทราบรายละเอียดในระดับต่ำพอที่จะบอกได้ว่ามันจะเป็นจริงหรือไม่
Jimmy Hoffa

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

1
ฉันต้องการจะชี้ให้เห็นว่าประสิทธิภาพหน่วยความจำไม่จำเป็นต้องขึ้นอยู่กับการเพิ่มประสิทธิภาพของคอมไพเลอร์เมื่อใช้โครงสร้างที่ไม่เปลี่ยนรูป ในตัวอย่างนี้let a = [1,2,3] in let b = 0:a in (a, b, (-1):c)ร่วมกันลดความต้องการหน่วยความจำ แต่ขึ้นอยู่กับนิยามของ(:)และ[]ไม่คอมไพเลอร์ ฉันคิด? ไม่แน่ใจเกี่ยวกับอันนี้

คำตอบ:


28

CPU (ตัวควบคุมหน่วยความจำโดยเฉพาะ) สามารถใช้ประโยชน์จากความจริงที่ว่าหน่วยความจำไม่ได้กลายพันธุ์

ข้อได้เปรียบคือข้อเท็จจริงนี้ช่วยประหยัดคอมไพเลอร์จากการใช้คำแนะนำmembarเมื่อมีการเข้าถึงข้อมูล

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

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


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

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

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

ค่อนข้างง่ายดูหมายเหตุด้านล่างนี่คือสิ่งที่เกิดขึ้นที่ตัวประมวลผลแบบมัลติคอร์สำหรับ membar:

  1. แกนทั้งหมดหยุดการประมวลผล - เพื่อหลีกเลี่ยงการเขียนแคช
  2. การอัปเดตทั้งหมดที่ทำกับแคชในเครื่องนั้นจะถูกเขียนกลับไปเป็นโกลบอลแคช - เพื่อให้แน่ใจว่าแคชสากลมีข้อมูลล่าสุด ใช้เวลาพอสมควร
  3. ข้อมูลที่อัปเดตจะถูกเขียนจากแคชสากลไปยังโลคัลแคช - เพื่อให้แน่ใจว่าแคชโลคัลมีข้อมูลล่าสุด ใช้เวลาพอสมควร
  4. แกนประมวลผลทั้งหมดดำเนินการต่อ

คุณจะเห็นแกนทั้งหมดที่มีการทำอะไรในขณะที่ข้อมูลจะถูกคัดลอกไปมาระหว่างแคชโลกและท้องถิ่น นี่เป็นสิ่งจำเป็นเพื่อให้แน่ใจว่าข้อมูลที่ไม่แน่นอนถูกซิงโครไนซ์อย่างเหมาะสม (ปลอดภัยของเธรด) หากมี 4 คอร์ทั้ง 4 หยุดและรอในขณะที่แคชถูกซิงค์ หากมี 8 ทั้งหมด 8 หยุด หากมี 16 ... ทีนี้คุณมี 15 คอร์ที่ไม่ได้ทำอะไรเลยในขณะที่รอสิ่งที่ต้องทำที่หนึ่งในนั้น

ทีนี้มาดูกันว่าเกิดอะไรขึ้นเมื่อข้อมูลไม่เปลี่ยนรูป? ไม่ว่าเธรดจะเข้าถึงสิ่งใดก็ตามจะรับประกันว่าเหมือนกัน สำหรับโปรแกรมเมอร์นี่หมายถึงไม่จำเป็นต้องแทรกโครงสร้างการซิงโครไนซ์เมื่อเข้าถึงข้อมูล (อ่าน) ในเธรดเฉพาะ

สำหรับคอมไพเลอร์สิ่งนี้ก็ไม่จำเป็นต้องใช้ที่จะแทรกคำแนะนำ membar

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


หมายเหตุค่อนข้างลดความซับซ้อนของสาเหตุดังกล่าวลดลงผลกระทบเชิงลบบางอย่างที่มีความซับซ้อนมากขึ้นของข้อมูลที่ถูกไม่แน่นอนเช่นในpipelining เพื่อรับประกันการสั่งซื้อที่ต้องการ CPU จะต้องยกเลิกการใช้งาน pilelines ที่ได้รับผลกระทบจากการเปลี่ยนแปลงข้อมูล หากสิ่งนี้ถูกนำมาใช้โดยตรงไปตรงมา (และเชื่อถือได้ :) การทำให้เป็นโมฆะของท่อทั้งหมดแล้วผลกระทบเชิงลบจะถูกขยายเพิ่มเติม



โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.