6.2. The ndarray

ndarray คือชนิดข้อมูลที่เก็บข้อมูลตัวเลขใน numpy มันเป็นสองสิ่งในหนึ่งเดียว ได้แก่ บล็อกข้อมูลแบบ packed เดี่ยวและตัวบ่งชี้ขนาดเล็กที่อยู่ด้านหน้าบล็อกนั้นซึ่งบอกวิธีอ่านข้อมูล

6.2.1. ภายในกล่อง

บล็อกข้อมูลเก็บทุกองค์ประกอบของอาร์เรย์ต่อเนื่องกัน โดยไม่มีสิ่งพิเศษแทรกระหว่างกัน แต่ละองค์ประกอบใช้จำนวนไบต์เท่ากัน ได้แก่ หนึ่งไบต์สำหรับอาร์เรย์ค่า uint8 สองไบต์สำหรับ uint16 สี่ไบต์สำหรับ float อาร์เรย์ uint8 ที่มี 256 องค์ประกอบคือข้อมูล 256 ไบต์พอดี ในขณะที่ตัวเลข 256 ตัวเดียวกันใน Python list ใช้หนึ่งกิโลไบต์ โดยมี slot 32 บิตต่อหนึ่งองค์ประกอบโดยไม่คำนึงว่าค่านั้นต้องการกี่บิตจริงๆ

ตัวบ่งชี้บันทึกความหมายของบล็อก มีค่าห้าค่าที่เพียงพอสำหรับอธิบายอาร์เรย์สี่เหลี่ยมใดก็ได้ไม่ว่าจะมีกี่มิติ:

  • dtype -- ชนิดองค์ประกอบ กำหนดจำนวนไบต์ที่แต่ละองค์ประกอบใช้และช่วงของค่าที่รองรับ (ครอบคลุมใน Dtypes)

  • itemsize -- ความกว้างเป็นไบต์ของหนึ่งองค์ประกอบ ซึ่งได้มาจาก dtype

  • ndim -- จำนวนมิติ (1 สำหรับเวกเตอร์ 2 สำหรับเมทริกซ์ 3 สำหรับปริมาตร สูงสุด 4)

  • shape -- ขนาดตามแต่ละมิติในรูป tuple

  • strides -- วิธีก้าวผ่านบล็อกข้อมูลเพื่อเดินตามแต่ละแกน ครอบคลุมใน Shape และ stride

นั่นคือทั้งหมด ทุก fast path ใน numpy ได้แก่ การคำนวณ การลดค่า broadcasting และ slicing ทำงานโดยตรงจากค่าทั้งห้านั้นบวกตัวชี้ข้อมูล โดยไม่มีค่าใช้จ่าย Python ต่อองค์ประกอบ

6.2.2. สิ่งที่การออกแบบให้มา

คุณสมบัติสามประการเกิดขึ้นจาก "packed block + small descriptor" และกำหนดพฤติกรรมของส่วนที่เหลือ

การคำนวณแบบ element-wise ทำงานเป็นการเรียกครั้งเดียว a + b ระหว่างอาร์เรย์สองตัวที่มีรูปร่างตรงกันจะบวกบัฟเฟอร์สองตัวและเขียนตัวที่สาม ทั้งหมดภายในการเรียก library เดียว np.sin(a) ทำเช่นเดียวกันสำหรับ sine ของทุกองค์ประกอบ โอเปอเรเตอร์คำนวณ เปรียบเทียบ และ bit-wise ทั้งหมดทำงานในลักษณะเดียวกัน

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

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

6.2.3. สิ่งที่การออกแบบต้องจ่าย

ข้อจำกัดสองประการเกิดจากการออกแบบเดียวกัน

ทุกองค์ประกอบมีชนิดเดียวกัน list สามารถเก็บ int ติดกับ str ติดกับ list ของ int อีกสามตัวได้ แต่ ndarray ทำไม่ได้ dtype ถูกกำหนดตายตัวตั้งแต่เวลาสร้าง หน้า Dtypes ครอบคลุมชุดชนิดข้อมูลเล็กๆ ที่ numpy รองรับและกฎที่เกิดจากการกำหนดค่าตายตัวนั้น

การขยายอาร์เรย์ไม่ฟรี list เก็บ slot ว่างไว้ตอนท้ายและรองรับ .append อย่างถูกต้น ndarray มีขนาดพอดีกับที่ต้องการ การ append หมายถึงการจัดสรรบัฟเฟอร์ใหม่ขนาดใหญ่กว่าและคัดลอกเนื้อหาเดิมเข้าไป ไม่มีเมธอด append() โดยเจตนา รูปแบบที่ถูกต้องบนกล้องคือการจัดสรรปลายทางล่วงหน้าตามขนาดสุดท้ายแล้ว เติมข้อมูล หน้า ประสิทธิภาพ ครอบคลุมเทคนิคนี้

ด้วยบัฟเฟอร์ชนิด packed สำหรับข้อมูล ตัวบ่งชี้ขนาดเล็กสำหรับ metadata และการรับประกันพฤติกรรมสามประการ (การคำนวณ element-wise แบบเร็ว view สำรองของข้อมูลเดิมที่ไม่คัดลอก และรูปร่างที่ broadcast ได้) ndarray คือรากฐานที่ส่วนที่เหลือของบทนี้ยึดอยู่ คำถามปฏิบัติถัดไปคืออาร์เรย์มาเป็นอยู่จริงๆ ได้อย่างไร ไม่ว่าจะจาก literal จากการจัดสรรที่กรอกล่วงหน้า หรือจากบัฟเฟอร์ของอุปกรณ์ต่อพ่วง