ขณะที่คนอื่น ๆ x[i][j]
ได้กล่าวว่าปัญหาคือการจัดเก็บไปยังตำแหน่งที่หน่วยความจำในอาร์เรย์: นี่เป็นข้อมูลเชิงลึกว่าทำไม:
คุณมีอาเรย์ 2 มิติ แต่หน่วยความจำในคอมพิวเตอร์นั้นมี 1 มิติโดยกำเนิด ดังนั้นในขณะที่คุณจินตนาการอาเรย์ของคุณเช่นนี้:
0,0 | 0,1 | 0,2 | 0,3
----+-----+-----+----
1,0 | 1,1 | 1,2 | 1,3
----+-----+-----+----
2,0 | 2,1 | 2,2 | 2,3
คอมพิวเตอร์ของคุณเก็บไว้ในหน่วยความจำในบรรทัดเดียว:
0,0 | 0,1 | 0,2 | 0,3 | 1,0 | 1,1 | 1,2 | 1,3 | 2,0 | 2,1 | 2,2 | 2,3
ในตัวอย่างที่ 2 คุณสามารถเข้าถึงอาร์เรย์ได้โดยวนลูปที่ 2 ก่อนเช่น:
x[0][0]
x[0][1]
x[0][2]
x[0][3]
x[1][0] etc...
หมายความว่าคุณกำลังตีพวกเขาทั้งหมดตามลำดับ ตอนนี้ดูรุ่นที่ 1 คุณกำลังทำ:
x[0][0]
x[1][0]
x[2][0]
x[0][1]
x[1][1] etc...
เนื่องจากวิธีที่ C วางอาร์เรย์ 2 มิติในหน่วยความจำคุณจึงขอให้มันกระโดดข้ามสถานที่นั้น แต่ตอนนี้สำหรับนักเตะ: ทำไมถึงเป็นเช่นนี้ การเข้าถึงหน่วยความจำทั้งหมดเหมือนกันใช่ไหม
ไม่: เพราะแคช ข้อมูลจากหน่วยความจำของคุณจะถูกส่งไปยัง CPU ด้วยชิ้นส่วนเล็ก ๆ (เรียกว่า 'แคชไลน์') โดยทั่วไปแล้ว 64 ไบต์ หากคุณมีจำนวนเต็ม 4 ไบต์นั่นหมายความว่าคุณได้จำนวนเต็มติดต่อกัน 16 ครั้งในชุดเล็ก ๆ ที่เรียบร้อย จริงๆแล้วมันค่อนข้างช้าในการดึงชิ้นส่วนของหน่วยความจำเหล่านี้ CPU ของคุณสามารถทำงานได้มากในเวลาที่โหลดแคชบรรทัดเดียว
ตอนนี้มองย้อนกลับไปที่คำสั่งของการเข้าถึง: ตัวอย่างที่สองคือ (1) คว้าอัน 16 ตัว (2) แก้ไขทั้งหมดของพวกเขา (3) ทำซ้ำ 4000 * 4000/16 ครั้ง มันดีและรวดเร็วและ CPU มักจะมีบางอย่างที่ต้องทำ
ตัวอย่างแรกคือ (1) คว้าอัน 16 ตัว (2) แก้ไขเพียงอันเดียวเท่านั้น (3) ทำซ้ำ 4000 * 4000 ครั้ง นั่นจะต้องใช้จำนวน 16 ครั้งของ "fetches" จากหน่วยความจำ CPU ของคุณจะต้องใช้เวลานั่งรอรอให้หน่วยความจำปรากฏขึ้นและในขณะที่กำลังนั่งอยู่คุณจะเสียเวลาอันมีค่าไป
โน๊ตสำคัญ:
ตอนนี้คุณมีคำตอบแล้วนี่เป็นบันทึกที่น่าสนใจ: ไม่มีเหตุผลโดยธรรมชาติที่ตัวอย่างที่สองของคุณต้องรวดเร็ว ตัวอย่างเช่นใน Fortran ตัวอย่างแรกจะเร็วและอันที่สองจะช้า นั่นเป็นเพราะแทนที่จะขยายสิ่งต่าง ๆ ออกเป็น "แถว" แนวความคิดเช่นเดียวกับ C Fortran จึงขยายเป็น "คอลัมน์" เช่น:
0,0 | 1,0 | 2,0 | 0,1 | 1,1 | 2,1 | 0,2 | 1,2 | 2,2 | 0,3 | 1,3 | 2,3
เลย์เอาต์ของ C เรียกว่า 'row-major' และ Fortran เรียกว่า 'column-major' อย่างที่คุณเห็นสิ่งสำคัญคือต้องรู้ว่าภาษาการเขียนโปรแกรมของคุณเป็นแถวหลักหรือคอลัมน์ใหญ่! นี่คือลิงค์สำหรับข้อมูลเพิ่มเติม: http://en.wikipedia.org/wiki/Row-major_order