แถวที่สำคัญเทียบกับรูปแบบที่สำคัญของการฝึกอบรมคอลัมน์


16

ในการเขียนโปรแกรมการคำนวณเมทริกซ์หนาแน่นมีเหตุผลใดที่จะเลือกเลย์เอาต์แถวหลักของผังเหนือคอลัมน์หลัก?

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

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


หากเราพิจารณาการคำนวณ b = A * x ด้วยเวกเตอร์คอลัมน์ x สำหรับแถวหลักเราอาจใช้ผลิตภัณฑ์ชั้นในของเวกเตอร์, A (i,:) ^ T x เพื่อรับ b (i); สำหรับคอลัมน์หลักเราอาจต้องใช้เวกเตอร์คูณสเกลาร์เท่านั้น, sum_i A (:, i) x (i) ดูเหมือนว่าคอลัมน์หลักของฉันดีกว่ามาก! คุณคิดอย่างไร?
Hui Zhang

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

คำตอบ:


18

เลย์เอาต์หลักของคอลัมน์คือรูปแบบที่ Fortran ใช้และนั่นคือสาเหตุที่มันถูกใช้ใน LAPACK และไลบรารีอื่น ๆ

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

ที่เก็บข้อมูลภายใน หน่วยเก็บข้อมูลภายในของรูปแบบหลักของคอลัมน์


11

ในสูญญากาศโดยไม่พิจารณาซอฟต์แวร์ที่มีอยู่ใด ๆ ไม่มีเหตุผลที่จะชอบคอลัมน์หลักมากกว่าแถวหลักจากมุมมองโค้ด อย่างไรก็ตามวรรณกรรมทางคณิตศาสตร์ส่วนใหญ่เขียนในลักษณะที่จัดกลุ่มเวกเตอร์เป็นเมทริกซ์โดยจัดเก็บเป็นคอลัมน์แทนที่จะเป็นแถว ตัวอย่างเช่นเมื่อคุณเขียนสมการ eigenvalue แบบเต็ม , XAX=XΛXmatrix มี eigenvector ทั้งหมดที่เขียนในคอลัมน์ คุณไม่เคยเห็นมันเขียนด้วยวิธีอื่น (แต่ฉันได้ยินว่าคนในสถิติเช่นเวกเตอร์แถว) ดังนั้นจึงเป็นเรื่องธรรมดาที่ซอฟต์แวร์แรกสุดจะสันนิษฐานรูปแบบหลักของคอลัมน์ดังนั้นหากคุณมีเมทริกซ์ซึ่งเป็นชุดของเวกเตอร์การจัดเก็บของเวกเตอร์เดียวใด ๆ จะต่อเนื่องกัน ดังนั้นฉันจินตนาการว่าประเพณีเพิ่งถูกสืบทอดมาจนถึงปัจจุบันและถ้าคุณต้องการมีปฏิสัมพันธ์กับเจ้า Olde Fortran คุณต้องการใช้คอลัมน์หลัก ดังนั้นพีชคณิตเชิงเส้นเชิงตัวเลขที่มีประสิทธิภาพสูงจะทำในคอลัมน์หลัก

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


2
ฉันคิดว่าสิ่งเหล่านี้เป็นข้อโต้แย้งที่ไม่ดี ความจริงที่ว่าดัชนีสุดท้ายใน '' 'สองเท่า [3] [2]' '' แตกต่างกันเร็วที่สุดไม่ใช่เรื่องบังเอิญ - มันเป็นการตัดสินใจที่ออกแบบอย่างมีสติในแบบเดียวกับที่มันเป็นการตัดสินใจที่ใส่ใจใน Fortran ทำอย่างอื่นเมื่อคุณมีอาร์เรย์ '' 'จริง (3,2)' ''
Wolfgang Bangerth

1
ยิ่งไปกว่านั้นมันไม่เป็นความจริงอีกต่อไปว่าพีชคณิตเชิงเส้นเชิงตัวเลขที่มีประสิทธิภาพสูงทั้งหมดนั้นเป็นคอลัมน์หลัก สิ่งนี้อาจเป็นจริงสำหรับ BLAS และ LAPACK แต่ก็ไม่เป็นความจริงเลยสำหรับห้องสมุดพีชคณิตเชิงเส้นสำคัญทุกแห่งที่ปรากฏใน 15 ปีที่ผ่านมาตัวอย่างเช่นทั้ง PETSc และ Trilinos ใช้รูปแบบการจัดเก็บเมทริกซ์แถวกระจัดกระจายหลัก
Wolfgang Bangerth

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

5
เพื่อไม่ให้เชื่อประเด็น แต่เดิม C เป็นภาษาระบบโดยยึดตามภาษาก่อนหน้า B และ BCPL ทำงานบนระบบเช่น PDP-11 ซึ่ง แต่เดิมไม่มีเลขทศนิยม การบอกว่าพวกเขาออกแบบด้วยตัวเลขในใจค่อนข้างยืด
Victor Liu

7
เคยไปที่นั่นแล้วเหตุผลของการฝึกหัดใน C ทำให้ดัชนีล่าสุดเร็วที่สุดเพราะ C ไม่มีเมทริกซ์ มันมีเวกเตอร์ของเวกเตอร์ที่สามารถนำมาใช้อย่างโปร่งใสเป็นบล็อกของแข็งของหน่วยความจำหรือเป็นอาร์เรย์ของพอยน์เตอร์ไปยังอาร์เรย์ การจัดทำดัชนีตามคำสั่งให้เข้ากันได้กับ Fortran นั้นคือ (ฉันคาดเดา) ไม่ใช่แม้แต่ในเรดาร์ของ Dennis Ritchie
Mike Dunlavey

2

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

ถ้าคุณเป็นโปรแกรมเมอร์ใน C / C ++ คุณควรใช้ไลบรารี่ระดับสูงกว่าสำหรับเมทริกซ์ (Eigen, Armadillo, ... ) พร้อมลำดับหลัก ๆ ของคอลัมน์ มีเพียงคนบ้าเท่านั้นที่จะใช้พอยน์เตอร์ C แบบดิบพร้อมลำดับแถวหลักได้แม้ว่า C / C ++ จะเสนอสิ่งที่เตือนการสร้างดัชนีเมทริกซ์

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

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

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


2

ม.×n

  • ม.ผม,Jผม×ม.+J
  • ม.ผม,JJ×n+ผม

ตอนนี้ลองนึกภาพอัลกอริทึมต่อไปนี้:

for i from 1 to m
   for j from 1 to n
      do something with m(i,j)

ผม×ม.+J

สรุป:

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

  2. กฎแห่งหัวแม่มือ: ดัชนีที่เปลี่ยนแปลงอย่างรวดเร็วควรถูกแมปไปยังตำแหน่งต่อเนื่องในหน่วยความจำ

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

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