พิจารณาโปรแกรมคอมพิวเตอร์ที่ง่ายมากต่อไปนี้:
for i = 1 to n:
y[i] = x[p[i]]
นี่คือและคืออาร์เรย์ -element ของไบต์และคืออาร์เรย์ของคำศัพท์ -element ที่นี่มีขนาดใหญ่เช่น (เพื่อให้มีเพียงเศษเสี้ยวเล็กน้อยของข้อมูลที่พอดีกับหน่วยความจำแคชทุกประเภท)
สมมติว่าประกอบด้วยตัวเลขสุ่มกระจายสม่ำเสมอระหว่างและn
จากมุมมองของฮาร์ดแวร์สมัยใหม่สิ่งนี้ควรหมายถึงสิ่งต่อไปนี้:
- การอ่านราคาถูก (การอ่านตามลำดับ)
- การอ่านมีราคาแพงมาก (การอ่านแบบสุ่ม; การอ่านเกือบทั้งหมดเป็นแคชที่หายไป; เราจะต้องดึงข้อมูลแต่ละไบต์จากหน่วยความจำหลัก)
- การเขียนนั้นถูก (การเขียนตามลำดับ)
และนี่คือสิ่งที่ฉันสังเกต โปรแกรมช้ามากเมื่อเปรียบเทียบกับโปรแกรมที่อ่านและเขียนตามลำดับเท่านั้น ยิ่งใหญ่
มาถึงคำถาม: โปรแกรมนี้ขนานกับแพลตฟอร์มมัลติคอร์ที่ทันสมัยได้อย่างไร
สมมติฐานของฉันคือว่าโปรแกรมนี้ไม่ขนานกัน ท้ายที่สุดคอขวดคือหน่วยความจำหลัก แกนเดียวเสียเวลาไปแล้วส่วนใหญ่รอข้อมูลจากหน่วยความจำหลัก
อย่างไรก็ตามนี่ไม่ใช่สิ่งที่ฉันสังเกตเห็นเมื่อฉันเริ่มทดลองกับอัลกอริธึมที่คอขวดทำงานแบบนี้!
ฉันเพียงแค่แทนที่ไร้เดียงสา for-loop ด้วย OpenMP parallel for-loop (โดยพื้นฐานแล้วมันจะแบ่งช่วงเป็นส่วนที่เล็กกว่าและเรียกใช้ส่วนเหล่านี้ในแกน CPU ที่แตกต่างกันในแบบคู่ขนาน)
สำหรับคอมพิวเตอร์ที่มีความเร็วต่ำการเพิ่มความเร็วนั้นเล็กน้อย แต่สำหรับแพลตฟอร์มระดับบนฉันรู้สึกประหลาดใจที่ฉันได้รับการเพิ่มความเร็วใกล้เชิงเส้นที่ยอดเยี่ยม ตัวอย่างที่เป็นรูปธรรมบางอย่าง (การกำหนดเวลาที่แน่นอนอาจจะค่อนข้างปิดมีการเปลี่ยนแปลงแบบสุ่มจำนวนมากซึ่งเป็นเพียงการทดลองที่รวดเร็ว)
2 x 4-core Xeon (รวม 8 แกน): ตัวคูณ 5-8 speedups เมื่อเปรียบเทียบกับเวอร์ชั่นแบบเธรดเดี่ยว
2 x 6-core Xeon (รวม 12 คอร์): ปัจจัย 8-14 speedups เมื่อเปรียบเทียบกับเวอร์ชั่นเธรดเดี่ยว
ตอนนี้มันคาดไม่ถึงเลย คำถาม:
ได้อย่างแม่นยำทำไมชนิดของ parallelise โปรแกรมนี้ให้ดี ? เกิดอะไรขึ้นกับฮาร์ดแวร์ (การคาดเดาปัจจุบันของฉันคือบางสิ่งตามบรรทัดเหล่านี้: การอ่านแบบสุ่มจากเธรดที่แตกต่างกันคือ "pipelined" และอัตราเฉลี่ยของการตอบคำถามเหล่านี้สูงกว่าในกรณีของเธรดเดี่ยวมาก)
มันเป็นความจำเป็นต้องใช้หลายกระทู้และหลายแกนที่จะได้รับ speedups ใด ๆ หากการ pipelining บางอย่างเกิดขึ้นจริงในอินเตอร์เฟสระหว่างหน่วยความจำหลักและซีพียูแอปพลิเคชันแบบเธรดเดียวไม่สามารถทำให้หน่วยความจำหลักทราบว่าอีกไม่นานมันจะต้องมี , , ... และคอมพิวเตอร์สามารถเริ่มดึงข้อมูลแคชที่เกี่ยวข้องจากหน่วยความจำหลักได้หรือไม่ หากเป็นไปได้ในหลักการฉันจะทำอย่างไรให้สำเร็จในทางปฏิบัติ
รูปแบบทางทฤษฎีที่ถูกต้องคืออะไรที่เราสามารถใช้วิเคราะห์โปรแกรมประเภทนี้ (และทำการคาดการณ์ประสิทธิภาพที่ถูกต้อง )
แก้ไข:ขณะนี้มีซอร์สโค้ดและผลลัพธ์การวัดประสิทธิภาพที่นี่: https://github.com/suomela/parallel-random-read
ตัวอย่างของตัวเลข ballpark ( ):
- ประมาณ 42 ns ต่อการวนซ้ำ (การอ่านแบบสุ่ม) ด้วยเธรดเดี่ยว
- ประมาณ 5 ns ต่อการทำซ้ำ (สุ่มอ่าน) ที่มี 12 คอร์