ابنِ تطبيقات ذكاء اصطناعي محلية باستخدام C++ وعينات NVIDIA TensorRT RTX

توفّر أمثلة NVIDIA TensorRT RTX لمطوري C++ نقطة انطلاق عملية لتشغيل نماذج الذكاء الاصطناعي المحلية على أجهزة RTX. تشرح هذه المقالة ما تقدّمه الأمثلة، وكيف تتناسب مع سير عمل استدلال محلي، وأين ينتهي التفسير ويبدأ التوثيق المُتحقَّق منه للمطورين الذين يخططون لأول عملية بناء.

القراءة الصوتية غير متاحة في هذا المتصفح
ابنِ تطبيقات ذكاء اصطناعي محلية باستخدام C++ وعينات NVIDIA TensorRT RTX

الوسوم

ملخص سريع

توفّر أمثلة NVIDIA TensorRT RTX لمطوري C++ نقطة انطلاق عملية لتشغيل نماذج الذكاء الاصطناعي المحلية على أجهزة RTX. تشرح هذه المقالة ما تقدّمه الأمثلة، وكيف تتناسب مع سير عمل استدلال محلي، وأين ينتهي التفسير ويبدأ التوثيق المُتحقَّق منه للمطورين الذين يخططون لأول عملية بناء.

بناء تطبيقات ذكاء اصطناعي محلية باستخدام C++ وعينات NVIDIA TensorRT RTX

انتقل تشغيل نماذج الذكاء الاصطناعي على جهازك الخاص من هواية متخصصة إلى خيار هندسي حقيقي. فبطاقات الرسوميات الاستهلاكية وبطاقات محطات العمل تمتلك الآن قدرة حسابية كافية لخدمة أعباء استدلال فعلية، وقد نضجت منظومة البرمجيات المحيطة بها إلى درجة أن كلمة "محلي" لم تعد تعني "لعبة". وبالنسبة للمطورين الذين يريدون هذه القدرة داخل تطبيق أصلي بدلاً من دفتر ملاحظات Python، يُعدّ الجمع بين C++ وNVIDIA TensorRT RTX من أكثر المسارات المباشرة المتاحة.

تقدم تدوينة NVIDIA للمطورين بعنوان Build Local AI Apps with C++ and NVIDIA TensorRT RTX Samples هذا المسار العملي: بيئة تشغيل مُحسَّنة لأجهزة فئة RTX، بالإضافة إلى مجموعة من العينات توضح كيف تتكامل الأجزاء. توسّع هذه المقالة نقطة الانطلاق تلك إلى دليل عملي — ما هي العينات، وما تحتاجه، وكيفية التثبيت والبناء، وكيفية الانتقال من ملف تنفيذي تجريبي إلى شيء يمكنك نشره.

ملاحظة حول النطاق قبل أن نبدأ: التفاصيل أدناه مستمدة من تدوينة NVIDIA للمطورين المشار إليها أعلاه ومن السلوك العام الموثّق علنًا لسلسلة الأدوات. وحيثما يعتمد مسار معين أو علامة معينة أو اسم حزمة على إصدار SDK أو المنصة، يُشار إلى هذا الاعتماد بدلاً من تخمينه.

ما الذي تقدمه عينات TensorRT RTX فعليًا

TensorRT RTX هي بيئة تشغيل موجّهة للاستدلال على بطاقات NVIDIA RTX. والعينات المصاحبة لها هي التطبيقات المرجعية: برامج صغيرة ومركّزة توضح آليات تحميل النموذج، وتحضيره للتنفيذ، وتغذيته بالمدخلات، وقراءة المخرجات.

هذه الجملة الأخيرة أهم مما تبدو عليه. فمعظم الصعوبة في عمل الاستدلال الأصلي ليست في الرياضيات — بل في البنية التحتية:

  • نقل التنسورات بين ذاكرة المضيف وذاكرة الجهاز بشكل صحيح
  • إدارة أحجام التخصيص وأعمارها دون تسريب
  • بناء محرك تنفيذ مُهيَّأ لبطاقة الرسوميات المحددة التي سيعمل عليها
  • التعامل مع الحدود التنسيقية بين نموذج مدرَّب وقطعة أثرية قابلة للتشغيل

توجد العينات لتقدم لك إجابة عملية لكل من هذه المشكلات. قراءتها أسرع من استنباط نفس الإجابات من مرجع API وحده، لأنها تجسّد ترتيب العمليات الذي تتوقعه بيئة التشغيل.

ما لا تقدمه العينات هو منتج نهائي. فهي عادةً مكتوبة للوضوح أكثر من المتانة: معالجة أخطاء بسيطة، ومسارات مُثبَّتة، وافتراضات حول شكل المدخلات. تعامل معها كقالب لتفرّعه، لا كمكتبة تربطها.

لماذا تُعدّ C++ طبقة منطقية للذكاء الاصطناعي المحلي

تهيمن Python على تدريب النماذج والتجريب، وهذا مبرَّر. أما للنشر على جهاز المستخدم، فتتغير الحسابات.

فالتطبيق المكتوب بـ C++ لا يحمل مفسّرًا، ولا بيئة افتراضية، ولا خطوة لحل التبعيات وقت التثبيت. يبدأ بسرعة، وبصمته الذاكرية متوقعة، ويتكامل مع التعليمات البرمجية الأصلية الموجودة — أدوات CAD، ومحركات الألعاب، وخطوط معالجة الوسائط، وبرمجيات التحكم الصناعي — دون جسر لغوي.

هناك تكاليف حقيقية، ومن الأمانة ذكرها. فإعداد البناء أكثر تعقيدًا. وإدارة الذاكرة مسؤوليتك. وتصحيح انهيار داخل نواة GPU أصعب من قراءة تتبّع Python. العينات تقلّل التكلفة الأولى بشكل كبير، وهي على الأرجح قيمتها العملية الأساسية.

إذا كان هدفك أداة سطح مكتب، أو إضافة، أو مكوّنًا مضمّنًا يستخدم شبكة عصبية، فإن C++ هي لغة الاستضافة الطبيعية. وإذا كان هدفك التكرار على معمارية النموذج، فهي ليست كذلك. اختر وفقًا لذلك.

المتطلبات

قبل تثبيت أي شيء، تأكد من أن الجهاز يستوفي الحد الأدنى.

العتاد

  • بطاقة NVIDIA RTX. تستهدف TensorRT RTX العتاد من فئة RTX، لذا فإن بطاقة من جيل GTX ليست هدفًا مدعومًا.
  • برنامج تشغيل حديث بما يكفي لإصدار SDK الخاص بك. يجب أن تتوافق إصدارات برنامج التشغيل وبيئة التشغيل؛ وهذا هو المصدر الأكثر شيوعًا لأخطاء التشغيل المحيّرة.
  • ذاكرة VRAM كافية لنموذجك. قاعدة تخطيط تقريبية: الأوزان زائد التنشيطات زائد مساحة العمل. النماذج الكبيرة تحتاج بطاقات كبيرة.

البرمجيات

  • مترجم يدعم C++17: MSVC على Windows، أو GCC أو Clang على Linux.
  • CMake لنظام البناء المستخدم في معظم العينات.
  • حزمة CUDA Toolkit، مطابقة للإصدار الذي يتوقعه بناء TensorRT RTX الخاص بك.
  • حزمة TensorRT RTX SDK نفسها.
  • Git، لجلب مصادر العينات.
  • Python مع PyTorch، فقط إذا كنت تحتاج إلى تصدير نموذج ONNX بنفسك.

المعرفة

الإلمام بالطرفية، وقراءة أخطاء البناء، ومفاهيم GPU الأساسية مثل ذاكرة الجهاز. لا تُشترط خبرة سابقة بـ TensorRT، لكن متابعة العينات ستكون أسهل إذا فهمت ما هو شكل التنسور.

التثبيت خطوة بخطوة

التسلسل أدناه مرتب عمدًا: تحقّق من GPU، ثبّت CUDA، ثبّت SDK، احصل على العينات، ابنِ، ثم شغّل.

1. التحقق من GPU وبرنامج التشغيل

ابدأ بتأكيد أن برنامج التشغيل يرى البطاقة ويبلغ عن إصدار CUDA.

nvidia-smi

يطبع هذا إصدار برنامج التشغيل المثبَّت وأقصى إصدار CUDA runtime يدعمه برنامج التشغيل. إذا فشل هذا الأمر، توقف هنا وأصلح تثبيت برنامج التشغيل أولاً — فلن يعمل أي شيء لاحق.

2. تثبيت CUDA Toolkit

ثبّت إصدار CUDA Toolkit يطابق المتطلب المذكور في وثائق TensorRT RTX SDK الخاصة بك. على Linux، يوفر مستودع حزم NVIDIA حزمًا وصفية:

sudo apt update && sudo apt install -y cuda-toolkit

على Windows، استخدم مثبّت CUDA Toolkit واختر خيار التثبيت المخصص لتتمكن من إلغاء تحديد المكونات التي لا تحتاجها، مثل حزم برامج التشغيل الأقدم.

بعد التثبيت، تأكد من أن المترجم على مسارك:

nvcc --version

3. تثبيت TensorRT RTX SDK

حمّل حزمة SDK من صفحة تنزيلات مطوّري NVIDIA — عادةً ما يُشترط وجود حساب مطوّر لدى NVIDIA. فك ضغطها إلى موقع ثابت وسجّل ذلك المسار، لأن كل خطوة لاحقة تشير إليه.

sudo mkdir -p /opt/nvidia/tensorrt-rtx
sudo tar -xf tensorrt-rtx-*.tar.gz -C /opt/nvidia/tensorrt-rtx --strip-components=1

يختلف اسم الأرشيف الدقيق والتخطيط الداخلي للمجلدات حسب الإصدار. تحقق من المحتويات في المستوى الأعلى بعد الاستخراج قبل المتابعة.

اجعل مكتبات بيئة التشغيل قابلة للاكتشاف:

export TRT_RTX_ROOT=/opt/nvidia/tensorrt-rtx
export LD_LIBRARY_PATH=$TRT_RTX_ROOT/lib:$LD_LIBRARY_PATH

أضف هذين السطرين إلى ملف تعريف الصدفة لديك إذا كنت لا تريد تكرارهما في كل جلسة. على Windows، تتمثل الخطوة المكافئة في إضافة مجلدَي bin وlib الخاصين بـ SDK إلى PATH، ومجلد التضمين إلى INCLUDE.

4. الحصول على العينات

تُشحن العينات إلى جانب SDK أو تُنشر كمستودع مصدري في مؤسسة NVIDIA على GitHub. اجلبها باستخدام Git:

git clone <samples-repository-url> tensorrt-rtx-samples
cd tensorrt-rtx-samples

خذ رابط المستودع من تدوينة NVIDIA للمطورين أو من وثائق SDK وليس من مصدر ثانوي؛ إذ تُعاد تسمية مستودعات العينات أو تُدمج أحيانًا بين الإصدارات.

5. الإعداد والبناء باستخدام CMake

اضبط البناء في مجلد منفصل ليبقى شجرة المصدر نظيفة. مرّر موقع SDK صراحةً لتجنّب اضطرار CMake إلى التخمين:

cmake -S . -B build \
  -DCMAKE_BUILD_TYPE=Release \
  -DTENSORRT_ROOT=$TRT_RTX_ROOT

يختلف اسم المتغير لجذر SDK بين مجموعات العينات — بعضها يستخدم TENSORRT_ROOT، وبعضها يتوقع متغير بيئة أو ملف إعداد. إذا أبلغ CMake أنه لا يستطيع العثور على TensorRT، فافحص ملف CMakeLists.txt الخاص بالعينة لمعرفة المتغير الدقيق الذي يبحث عنه.

البناء:

cmake --build build --config Release --parallel

على Windows مع مُولِّد Visual Studio، حدّد المولّد والمنصة مسبقًا:

cmake -S . -B build -G "Visual Studio 17 2022" -A x64 -DTENSORRT_ROOT=$env:TRT_RTX_ROOT
cmake --build build --config Release

6. التحقق من البناء

اسرد الملفات التنفيذية الناتجة وتأكد من أن كل واحد منها يستجيب لـ --help:

./build/bin/<sample_name> --help

اقرأ مخرجات المساعدة بعناية. فهي القائمة الموثوقة للعلامات الخاصة بالإصدار الذي بنيته، وهي السبب في أن هذه المقالة تتجنب عمدًا تثبيت أسماء العلامات أدناه.

تفاصيل الإعداد المهمة وقت التشغيل

بمجرد أن تُترجم العينات، تهيمن ثلاثة اعتبارات إعداد.

تنسيق النموذج. تستهلك بيئات تشغيل الاستدلال الأصلية عمومًا إما رسمًا بيانيًا لـ ONNX أو محركًا مُسلسَلًا مسبق البناء. ONNX هو المدخل المحمول؛ والمحرك هو القطعة الأثرية المُحسَّنة الخاصة بـ GPU. إذا كان نموذجك في PyTorch، فصدّره:

import torch

model = torch.load("model.pth", map_location="cpu").eval()
dummy = torch.randn(1, 3, 224, 224)

torch.onnx.export(
    model,
    dummy,
    "model.onnx",
    input_names=["input"],
    output_names=["output"],
    dynamic_axes={"input": {0: "batch"}, "output": {0: "batch"}},
    opset_version=17,
)

تحقق من رقم opset مقابل ما تدعمه بيئة التشغيل لديك. فالمشغّل غير المدعوم يُعدّ فشلاً وقت البناء، وليس تدهورًا سلسًا.

قابلية نقل المحرك. يرتبط المحرك المُسلسَل عمومًا بمعمارية GPU وإصدار بيئة التشغيل التي بُني عليها. ابنِ المحركات على الجهاز الهدف، أو ابنِ محركًا واحدًا لكل تكوين هدف. وتخزين المحركات مؤقتًا على جهاز المستخدم عند التشغيل الأول نمط شائع ويتجنب شحن ما يعادل مزرعة بناء كاملة من القطع الأثرية.

الدقة. يُعدّ تنفيذ FP16 وINT8 الرافعتين المعتادتين للإنتاجية. لكنهما ليسا مجانيين: فالتكميم يمكن أن يغيّر النتائج، ويحتاج INT8 تحديدًا إلى بيانات معايرة لاختيار المقاييس بشكل معقول. تحقق دائمًا من الدقة مقابل مرجع كامل الدقة قبل تمكين مسار دقة مخفّضة.

أمثلة الاستخدام

توضح الأمثلة التالية شكل العمل بدلاً من الاستدعاءات الدقيقة، لأن أسماء العلامات تختلف حسب الإصدار. تحقق دائمًا من --help.

مثال 1: تشغيل عينة مرفقة

تأخذ عينة استدلال نموذجية مسار نموذج وبعض المدخلات، ثم تكتب مخرجات:

./build/bin/<inference_sample> \
  --model ./models/model.onnx \
  --input ./data/input.bin \
  --output ./data/output.bin

إذا كانت العينة تتوقع محركًا مبنيًا مسبقًا بدلاً من ONNX، فمن المرجح أنها ستكشف عن خطوة بناء منفصلة أو علامة مثل --build-engine. راجع نص المساعدة.

مثال 2: بنية برنامج استدلال بسيط

تتبع جميع العينات الهيكل العام نفسه تقريبًا. وباختصار إلى الأساسيات، يبدو هذا الهيكل هكذا — تعامل مع الأسماء كعناصر نائبة هيكلية واستبدلها بالرموز الفعلية من ترويسات SDK التي ثبّتها:

// Illustrative structure only. Use the real API names from your installed
// TensorRT RTX headers and the sample you are basing your code on.
#include <iostream>
#include <vector>

int main(int argc, char** argv) {
    // 1. Create the runtime and deserialize (or build) an engine.
    //    This is the expensive step; do it once, not per inference.
    auto engine = loadOrBuildEngine("model.onnx");

    // 2. Create an execution context. Contexts are cheap and hold the
    //    per-inference state; one context per concurrent stream.
    auto context = engine->createExecutionContext();

    // 3. Allocate device buffers for inputs and outputs, sized from the
    //    engine's tensor descriptors rather than from hard-coded numbers.
    auto buffers = allocateBuffers(engine);

    // 4. Copy input data from host to device.
    copyInputToDevice(buffers, "input.bin");

    // 5. Enqueue the work and synchronize before reading results.
    enqueue(context, buffers);
    synchronize();

    // 6. Copy outputs back to host and use them.
    writeOutputToHost(buffers, "output.bin");

    return 0;
}

قيمة العينات أنها تملأ كل خطوة من هذه الخطوات الست بكود عامل، بما في ذلك فحوصات الأخطاء وحسابات أحجام المخازن المؤقتة التي يسهل الخطأ فيها بشكل دقيق.

مثال 3: استدلال دفعي من قائمة ملفات

للعمل الموجّه نحو الإنتاجية، يكون النمط هو تحميل المحرك مرة واحدة ثم التكرار:

for f in ./data/*.bin; do
  ./build/bin/<inference_sample> --model ./models/model.onnx --input "$f" --output "${f%.bin}.out"
done

هذا جيد لاختبار الصحة. أما للإنتاجية الحقيقية، ففضّل عملية واحدة تجمّع المدخلات دفعات، لأن بدء العملية وإلغاء تسلسل المحرك يهيمنان على الوقت بخلاف ذلك. والتجميع في دفعات يخفف كليهما.

ملاحظات الأداء والتحقق

هناك عادتان تمنعان معظم الجهد المهدر.

تحقق من الأرقام قبل التحسين. شغّل نموذجك عبر العينة وعبر تطبيق مرجعي — PyTorch أو ONNX Runtime — على مدخلات متطابقة. قارن بسماحية مناسبة للمهمة. فقط عندما تتطابق المخرجات ينبغي أن تبدأ ضبط الدقة أو حجم الدفعة، وإلا فلن تستطيع التمييز بين خطأ صحة ونتيجة تكميم.

قِس على الهدف. يعتمد أداء الاستدلال على طراز GPU، وإصدار برنامج التشغيل، وحدود الطاقة والحرارة، وحجم الدفعة، وشكل المدخلات. الأرقام من جهاز مختلف، أو من وضع دقة مختلف، ستضللك. ابنِ أداة صغيرة تثبّت شكل المدخلات وتُبلّغ عن زمن الاستجابة على مدى تكرارات كثيرة، بما في ذلك جولات الإحماء — فالاستدلال الأول بعد إنشاء المحرك ليس ممثلاً.

قائمة التحقق لحل المشكلات

  • خطأ وقت تشغيل حول إصدارات غير متوافقة. برنامج التشغيل لديك أقدم من متطلبات SDK، أو CUDA Toolkit لديك غير مطابق. أعد التحقق من كليهما مقابل ملاحظات إصدار SDK.
  • المكتبة غير موجودة عند بدء التشغيل. LD_LIBRARY_PATH على Linux، أو PATH على Windows، يفتقد مجلد مكتبات SDK.
  • CMake لا يستطيع العثور على TensorRT. مرّر جذر SDK صراحةً أو افحص CMakeLists.txt لاسم المتغير المتوقع.
  • فشل تحميل النموذج. مشغّل أو opset غير مدعوم. أعد التصدير بـ opset مدعوم وتحقق من قائمة المشغّلات.
  • المخرجات خاطئة لكن لا يُثار أي خطأ. أحجام المخازن المؤقتة، أو أشكال التنسورات، أو تخطيط المدخلات غير متطابقة. اطبع واصفات مدخلات ومخرجات المحرك وقارنها بما تُغذّيه فعليًا.
  • الأداء أسوأ من المتوقع. التشغيل الأول يتضمن بناء المحرك؛ يجب أن تكون التشغيلات اللاحقة أسرع. تأكد أيضًا من أنك لا تعمل على CPU عن غير قصد.

الخاتمة

المسار من نموذج مدرَّب إلى تطبيق ذكاء اصطناعي محلي أصلي قصير إذا بدأت من المكان الصحيح. توفر عينات TensorRT RTX من NVIDIA نقطة الانطلاق تلك: كود C++ عامل يوضح دورة حياة المحرك، وإدارة المخازن المؤقتة، وتدفق التنفيذ الذي لولاها لكنت مضطرًا لإعادة بنائه من المبادئ الأولى.

التسلسل العملي مباشر. تحقق من GPU وبرنامج التشغيل لديك، وثبّت CUDA Toolkit وTensorRT RTX SDK متوافقين، واجلب العينات، واضبط الإعداد بـ CMake مع الإشارة صراحةً إلى جذر SDK، ثم ابنِ. بعد ذلك اقرأ العينة الأقرب إلى حالة استخدامك، وشغّلها على نموذج ONNX الخاص بك، وتحقق من المخرجات قبل المساس بالأداء.

العينات أساس، وليست تطبيقًا منتهيًا. تبقى معالجة الأخطاء المتينة، وتخزين المحركات مؤقتًا، واستراتيجية التجميع في دفعات، وقرارات التكميم من عملك. لكنها العمل الذي يهم، والنص البرمجي المتكرر الذي يقف أمامه هو بالضبط ما تزيله العينات. وبالنسبة للمطورين الذين يريدون استدلالاً يعمل على عتادهم الخاص، داخل برمجياتهم الأصلية، فهذا مكان مفيد حقًا للبدء.

الدليل الأصلي والعينات نفسها مرتبطان من مدونة مطوّري NVIDIA: Build Local AI Apps with C++ and NVIDIA TensorRT RTX Samples.

المصادر