ทำไมการแสดงการคำนวณในฐานะการคูณเมทริกซ์ทำให้พวกเขาเร็วขึ้น?


18

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

ถ้าเราเขียนมันออกมาเป็นสมการเราจะได้:

สมการสเกลาร์

เราสามารถ "vectorize" ขั้นตอนนี้โดยเปลี่ยนเป็นการคูณเมทริกซ์และการบวกเวกเตอร์ สิ่งนี้มีประโยชน์สำหรับประสิทธิภาพการคำนวณ (เป็นวิธีคิดที่มีประโยชน์ด้วย)

สมการเวกเตอร์

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

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

คำตอบ:


19

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

  • ใช้หลายกระทู้ แทบไม่มีซีพียูสมัยใหม่ที่ไม่มีคอร์หลายคอร์หลายตัวมีมากถึง 8 และเครื่องพิเศษสำหรับการคำนวณประสิทธิภาพสูงสามารถมี 64 ผ่านซ็อกเก็ตได้หลายตัว การเขียนโค้ดด้วยวิธีที่ชัดเจนในภาษาการเขียนโปรแกรมปกติใช้เพียงหนึ่งในนั้น กล่าวอีกนัยหนึ่งก็อาจใช้ทรัพยากรการคำนวณที่มีอยู่ของเครื่องที่ใช้งานอยู่น้อยกว่า 2%
  • การใช้คำสั่ง SIMD (อย่างสับสนนี้เรียกอีกอย่างว่า "vectorization" แต่ในแง่ที่แตกต่างจากคำพูดของคำถามในคำถาม) ในสาระสำคัญแทนที่จะเป็น 4 หรือ 8 หรือมากกว่านั้นคำแนะนำเกี่ยวกับคณิตศาสตร์สเกลาร์ให้คำสั่ง CPU หนึ่งที่ดำเนินการทางคณิตศาสตร์ใน 4 หรือ 8 หรือดังนั้นการลงทะเบียนในแบบคู่ขนาน นี่สามารถทำการคำนวณได้อย่างแท้จริง (เมื่ออิสระอย่างสมบูรณ์และเหมาะสมกับชุดคำสั่ง) เร็วกว่า 4 หรือ 8 เท่า
  • ทำอย่างชาญฉลาดใช้แคช การเข้าถึงหน่วยความจำจะเร็วขึ้นหากมีการเชื่อมโยงทางโลกและเชิงพื้นที่นั่นคือการเข้าถึงอย่างต่อเนื่องเป็นไปยังที่อยู่ใกล้เคียงและเมื่อเข้าถึงที่อยู่สองครั้งคุณจะเข้าถึงสองครั้งอย่างต่อเนื่องแทนที่จะหยุดชั่วคราว
  • การใช้ส่วนช่วยดำเนินการเช่น GPU อุปกรณ์เหล่านี้เป็นสัตว์ที่แตกต่างจากซีพียูมากและการตั้งโปรแกรมให้มีประสิทธิภาพนั้นเป็นรูปแบบศิลปะทั้งหมดของมันเอง ตัวอย่างเช่นพวกเขามีหลายร้อยคอร์ซึ่งถูกจัดกลุ่มเป็นกลุ่มของคอร์ไม่กี่โหลและกลุ่มเหล่านี้ใช้ทรัพยากรร่วมกัน - พวกเขาแบ่งปันหน่วยความจำไม่กี่ KiB ที่เร็วกว่าหน่วยความจำปกติมากและเมื่อแกนกลางของกลุ่มดำเนินการifแถลงการณ์คนอื่น ๆ ทั้งหมดในกลุ่มนั้นต้องรอ
  • แจกจ่ายงานผ่านหลาย ๆ เครื่อง (สำคัญมากในซูเปอร์คอมพิวเตอร์!) ซึ่งนำเสนอชุดใหม่ของอาการปวดหัวใหม่ แต่แน่นอนสามารถให้การเข้าถึงทรัพยากรการประมวลผลที่ยิ่งใหญ่กว่าเดิมมากมาย
  • อัลกอริทึมที่ชาญฉลาด สำหรับการคูณเมทริกซ์อัลกอริธึม O (n ^ 3) แบบง่าย ๆ ซึ่งได้รับการปรับให้เหมาะสมกับเทคนิคข้างต้นมักจะเร็วกว่าsub-cubic ลูกบาศก์สำหรับขนาดเมทริกซ์ที่สมเหตุสมผล แต่บางครั้งพวกเขาก็ชนะ สำหรับกรณีพิเศษเช่นเมทริกซ์กระจัดกระจายคุณสามารถเขียนอัลกอริทึมพิเศษ

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

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


4

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

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

ในตัวอย่างของคุณการดำเนินการจะเป็นดังนี้

  1. ตั้งค่ากริดของโปรเซสเซอร์แต่ละตัวที่ถือ Wx, y ตามพิกัดในกริด

  2. เผยแพร่เวกเตอร์แหล่งที่มาตามแต่ละคอลัมน์ (ราคาO(log height))

  3. มีโปรเซสเซอร์แต่ละตัวเพื่อการคูณในเครื่อง (ราคาO(width of submatrix * heightof submatrix))

  4. ยุบผลลัพธ์ไปตามแต่ละแถวโดยใช้ผลรวม (ราคาO(log width))

การดำเนินการล่าสุดนี้ถูกต้องเนื่องจากผลรวมมีความสัมพันธ์

สิ่งนี้ยังช่วยในการสร้างความซ้ำซ้อนและช่วยให้คุณไม่ต้องใส่ข้อมูลทั้งหมดไว้ในเครื่องเดียว

สำหรับเมทริกซ์ 4x4 ขนาดเล็กอย่างที่คุณเห็นในกราฟิกเป็นเพราะ CPU มีคำสั่งพิเศษและลงทะเบียนเพื่อจัดการกับการดำเนินการเหล่านั้น


-1

สิ่งที่ให้คำแนะนำมากที่สุดคือการเปรียบเทียบประสิทธิภาพของรหัสของคุณกับประสิทธิภาพของการคูณเมทริกซ์ที่ดำเนินการโดย alredy

มีการเพิ่มประสิทธิภาพระดับต่ำกว่าเสมอซึ่งคุณไม่ได้คิดไว้ที่นี่คุณสามารถดูตัวอย่างได้:

https://simulationcorner.net/index.php?page=fastmatrixvector

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