ndarray في Rust: دليل شامل للتعامل مع المصفوفات متعددة الأبعاد
1. ما هي ndarray ولماذا تحتاجها؟
مكتبة ndarray هي الإضافة الأساسية في نظام Rust البيئي للتعامل مع المصفوفات متعددة الأبعاد (N-dimensional tensors). توفر هذه المكتبة هياكل بيانات قوية وآمنة من حيث الأنواع وعالية الأداء للحسابات العددية والجبر الخطي ومعالجة الإشارات والتعلم الآلي والحسابات العلمية. إذا كنت معتادًا على NumPy في Python، فإن ndarray هي المكافئ المباشر لها في عالم Rust، ولكن مع مزايا التنميط الصارم وعدم وجود جامع للقمامة والتحكم الكامل في الذاكرة.
لماذا تحتاجها؟ لا يحتوي Rust على دعم مدمج للمصفوفات متعددة الأبعاد بعدد عشوائي من المحاور. المتجهات القياسية (Vec<T>) والشرائح (&[T]) تسمح فقط بالعمل مع بيانات أحادية البعد. للمهام التي تتطلب جبر المصفوفات أو عمليات الالتواء أو عمليات التنسور أو معالجة الصور، تحتاج إلى مكتبة متخصصة. تحل ndarray هذه المشاكل من خلال توفير:
- مصفوفات متعددة الأبعاد مقيدة النوع (
ArrayBase) بعدد ثابت أو ديناميكي من المحاور. - شرائح فعالة (slicing) وفهرسة وتكرار.
- عمليات حسابية متجهة (broadcasting).
- التكامل مع BLAS/LAPACK عبر
ndarray-linalgللحسابات الجبرية الخطية عالية الأداء. - دعم الحسابات المتوازية عبر
rayon.
تُستخدم المكتبة بنشاط في مشاريع مثل RustML و Linfa (إطار عمل للتعلم الآلي) و Image (معالجة الصور) والعديد من المشاريع الأخرى. إنها الأساس للحسابات العلمية في Rust.
2. التثبيت
لتثبيت ndarray، استخدم مدير الحزم Cargo المضمن في Rust. أضف التبعية إلى ملف Cargo.toml لمشروعك:
[dependencies]
ndarray = "0.16"
ثم نفذ الأمر التالي في الطرفية:
cargo build
للعمل مع الجبر الخطي (ضرب المصفوفات، القيم الذاتية)، أضف ndarray-linalg واختر الخلفية BLAS (مثل OpenBLAS أو Intel MKL):
[dependencies]
ndarray = "0.16"
ndarray-linalg = { version = "0.16", features = ["openblas"] }
للتكرار المتوازي، استخدم ndarray-parallel:
[dependencies]
ndarray = "0.16"
ndarray-parallel = "0.16"
3. البداية السريعة — مثال عملي بسيط
لنقم بإنشاء مصفوفة أحادية البعد، وإجراء عملية جمع عنصر بعنصر، وعرض النتيجة. احفظ الكود التالي في ملف src/main.rs:
use ndarray::Array;
fn main() {
// إنشاء مصفوفة أحادية البعد من 5 عناصر
let a = Array::from_vec(vec![1, 2, 3, 4, 5]);
let b = Array::from_vec(vec![10, 20, 30, 40, 50]);
// جمع عنصر بعنصر
let c = &a + &b;
println!("a = {:?}", a);
println!("b = {:?}", b);
println!("a + b = {:?}", c);
}
قم بتشغيل البرنامج:
cargo run
النتيجة:
a = [1, 2, 3, 4, 5], shape=[5], strides=[1], layout=CFcf (0x1)
b = [10, 20, 30, 40, 50], shape=[5], strides=[1], layout=CFcf (0x1)
a + b = [11, 22, 33, 44, 55], shape=[5], strides=[1], layout=CFcf (0x1)
4. أهم الدوال والطرق (8 دوال على الأقل)
4.1. Array::from_shape_vec
التوقيع: pub f