GPU-Accelerated 3D Non-Local Means for Python: A Toolchain-Free, Pip-Installable CuPy Implementation
تقدم هذه الورقة تنفيذًا لـ CuPy يمكن تثبيته عبر pip في ملف واحد، يتيح إزالة الضجيج باستخدام خوارزمية "المتوسط غير المحلي" ثلاثية الأبعاد (3D Non-Local Means) بتسريع عبر وحدة معالجة الرسومات دون الحاجة إلى حزمة أدوات CUDA أو مترجم C++، محققًا تسريعًا يتجاوز 100 ضعف مقارنة بالمرجع القائم على وحدة المعالجة المركزية من scikit-image مع الحفاظ على دقة المخرجات وإمكانية الاستخدام التفاعلي.
في عالم التصوير الرقمي، ولا سيما عندما يتفحص العلماء المسوحات ثلاثية الأبعاد لجسم الإنسان أو الهياكل الجيولوجية، تبرز مشكلة مستمرة وهي: الضجيج. هذا التداخل الحبيبي الساكن يحجب التفاصيل الدقيقة التي يحتاج الباحثون لرؤيتها. ولتنظيف هذه الصور، يستخدم العلماء تقنية قوية تسمى "إزالة الضجيج بالوسائل غير المحلية" (non-local means denoising). وبخلاف الطرق الأبسط التي تكتفي بالنظر إلى الجيران المباشرين للبكسل، يبحث هذا النهج المتطور في حجم الصورة بأكלו ل find مناطق أخرى تشبهها، ثم يجمعها معاً عبر المتوسط لتنعيم الحبيبات مع الحفاظ على الحواف الحادة. ومع ذلك، فإن هذه مهمة ثقيلة حسابياً؛ فبسبب ضرورة مقارنة كل كتلة ثلاثية الأبعاد صغيرة في الصورة بعدد لا يحصى من الكتل الأخرى، يمكن أن تستغرق العملية ساعاتاً على المعدات القياسية، مما يجبر العلماء على الانتظار حتى تنتهي المهمة قبل أن يتمكنوا من رؤية النتائج أو ضبط إعداداتهم. هذا التأخير يحول ما يمكن أن يكون استكشافاً تفاعلياً إلى مهمة بطيئة تعتمد على المعالجة بالدفعات.
لقد نجح باحث يدعى متين مهزاد في سد الفجوة بين طريقة التنظيف القوية هذه والحاجة إلى السرعة، حيث ابتكر أداة جديدة تعمل على بطاقات الرسوميات (graphics cards) لجعل العملية فورية تقريباً. جوهر هذا العمل هو حزمة برمجية تتناسب مع بيئة البرمجة "بايثون" القياسية، وهي اللغة التي يستخدمها معظم علماء البيانات، ولكن دون الصداع المعتاد المتعلق بالتثبيت. عادةً، لتشغيل عمليات رياضية معقدة على بطاقة الرسوميات، يجب على المستخدم تثبيت مجموعة ضخمة ومعقدة من أدوات التطوير ومترجم (compiler) محدد، وهي عملية غالباً ما تفشل على أنظمة الكمبيوتر المختلفة. لقد تجاوز حل مهزاد هذا الأمر تماماً؛ فالبرنامج عبارة عن ملف واحد يمكن تثبيته بأمر واحد فقط، ولا يتطلب سوى وجود بطاقة الرسوميات نفسها. وهو يعمل عن طريق ترجمة تعليمات التنظيف إلى لغة تفهمها بطاقة الرسوميات في اللحظة التي يبدأ فيها البرنامج، بدلاً من اشتراط نسخة مسبقة البناء وثابتة.
النتائج المحققة من هذا النهج دراماتيكية. فعند اختباره على صورة كبيرة ثلاثية الأبعاد تبلغ أبعادها 500 في 500 في 500 بكسل، استغرقت الطريقة القياسية التي تعمل على معالج كمبيوتر حديث ما بين 420 و433 ثانية لإتمام المهمة. أي ما يعادل حوالي سبع دقائق من وقت الانتظار لصورة واحدة. وقد قللت تنفيذ بطاقة الرسوميات الجديد ذلك الوقت إلى 3.25 ثانية فقط عند استخدام الدقة القياسية، و7.8 ثانية عند استخدام دقة أعلى. ويمثل هذا تسريعاً بنحو 130 مرة. والمخرجات ليست أسرع فحسب، بل هي مطابقة رياضياً للطريقة البطيئة، حيث تطابق النتائج المرجعية حتى أصغر خانة عشرية. وقد تحقق هذا الدقة من خلال إعادة محاكة الطرق المحددة، والغريبة نوعاً ما، التي تعاملت بها البرمجية الأصلية مع الحسابات، مما يضمن أن الأداة الجديدة تنتج نفس الصورة تماماً مثل الأداة القديمة، ولكن في كسر من الوقت.
يكمن مفتاح هذه السرعة في كيفية إدارة البرنامج للذاكرة داخل بطاقة الرسوميات. تمتلك بطاقة الرسوميات بنك ذاكرة صغيراً فائق السرعة يمكنه استيعاب كمية محدودة من البيانات في المرة الواحدة. وقد صُممت الأداة الجديدة لتقرر بذكاء مقدار الجزء الذي يجب تحميله في هذه الذاكرة السريعة في أي لحظة. فهي تختبر أربع استراتيجيات مختلفة، تتراوح من تحميل قطعة صغيرة من الصورة إلى تحميل قسم كبير، وتختار تلقائياً الاستراتيجية الأكثر هجومية التي تتناسب مع حدود الذاكرة لبطاقة الرسوميات المستخدمة تحديداً. وهذا يضمن عدم إضاعة وقت الكمبيوتر في انتظار انتقال البيانات من الذاكرة الرئيسية الأبطأ. ومن خلال تحسين تدفق البيانات هذا، تحول البرنامج من مهمة كانت تجبر العلماء سابقاً على العمل في الخلفية، بعيداً عن شاشاتهم، إلى شيء يمكنهم مشاهدته وضبطه في الوقت الفعلي.
لا يدعي هذا العمل حل كل مشكلة في معالجة الصور، كما أنه لا يحاول العمل على عدة بطاقات رسوميات في آن واحد أو التعامل مع كل التباينات الممكنة لخوارزمية التنظيف. إنه يركز تحديداً على النسخة الأكثر شيوعاً وكفاءة من الطريقة ويعمل على بطاقة رسوميات واحدة. لم يكن الهدف ابتكار نظرية رياضية جديدة، بل جعل أداة قوية وموجودة بالفعل متاحة لأي شخص يمتلك حاسوباً قياسياً وبطاقة رسوميات متوافقة. ومن خلال إزالة الحاجة إلى خطوات التثبيت المعقدة وتقديم النتائج في ثوانٍ بدلاً من دقائق، يغير هذا البرنامج طبيعة العمل؛ فهو يسمح للباحث بتنقية صورة، وفحص النتيجة، وتعديل إعداد، ثم تنقية صورة أخرى مجدداً في الوقت الذي يستغرقه إعداد كوب من القهوة، مما يبقي العقل البشري منخرطاً مع البيانات بدلاً من الانتظار حتى ينتهي الجهاز. الكود متاح الآن كبرمجية مفتوحة المصدر، جاهزة للاستخدام من قبل أي شخص دون الحاجة لأن يكون مهندس برمجيات.
ملخص تقني: خوارزمية المتوسط غير المحلي ثلاثي الأبعاد المسرعة بواسطة وحدة معالجة الرسومات (GPU) للغة بايثون
بيان المشكلة تعد عملية إزالة الضجيج باستخدام المتوسط غير المحلي (NLM) تقنية قياسية في التصوير العلمي، وهي مُنفذة في مكتبة scikit-image الخاصة بلغة بايثون عبر دالة denoise_nl_means. وبينما تستخدم scikit-image خوارزمية "الوضع السريع" (fast-mode) المحسنة القائمة على الصور التكاملية (Darbon et al. [3]; Froment [4]) لتقليل التعقيد الحسابي، إلا أن المرجع المرجعي الذي يعمل على المعالج المركزي (CPU) يظل بطيئاً بشكل غير مقبول للكتل ثلاثية الأبعاد الكبيرة. إذ تستغرق معالجة حجم واحد بمقاس 500×500×500 حوالي 420–434 ثانية، مما يفرض على سير العمل أن يكون في وضع الدفعات فقط (batch-only) ويمنع التعديل التفاعلي أو الفوري للمعلمات.
الحلول الحالية المعتمدة على وحدة معالجة الرسومات (GPU) لـ 3D NLM غير متاحة لمنظومة بايثون القياسية؛ فهي تتطلب عادةً كود CUDA C++ مجمعاً مرتبطاً بمجموعات متعددة من وحدات معالجة الرسومات، أو نماذج تصوير محددة (مثل الرنين المغناطيسي)، أو بيئات تعمل بنظام لينكس فقط. وعلاوة على ذلك، فإن توزيعات OpenCV التي تدعم تسريع GPU تفتقر إلى دعم CUDA في نسخها القياسية القابلة للتثبيت عبر pip ولا توفر أي بديل ثلاثي الأبعاد. كما أن مكتبات GPU الرئيسية في بايثون مثل PyTorch تتطلب وجود مترجم C++ وبيئة CUDA Toolkit لتطوير نوى (kernels) مخصصة، مما يخلق حاجزاً أمام المستخدمين الذين يفتقرون إلى أدوات التطوير الكاملة.
المنهجية تقدم هذه الورقة تنفيذاً بلغة بايثون، يمكن تثبيته عبر pip في ملف واحد، لخوارزمية 3D NLM يعمل بالكامل على وحدة معالجة رسومات واحدة دون الحاجة إلى مترجم C++ مضيف أو توزيع برمجيات مسبقة التجميع. يعتمد النهج التقني الجوهري على المكونات التالية:
التجميع في وقت التشغيل عبر CuPy: يستخدم التنفيذ واجهة RawKernel الخاصة بـ CuPy، والتي تستفيد من NVRTC (NVIDIA Runtime Compilation) لتجميع كود CUDA C++ الخام المضمن كنص بايثون في وقت التشغيل. هذا يلغي الحاجة إلى nvcc أو MSVC أو gcc، ويتطلب فقط تعريفاً لوحدة معالجة رسومات متوافقة مع CUDA.
الدقة الخوارزمية: يلتزم الصياغة الرياضية بدقة بخوارزمية "الوضع السريع" لـ NLM المستخدمة في scikit-image. يتضمن ذلك إعادة صياغة الصورة التكاملية لحساب مسافة الرقعة (patch-distance)، وتصحيح تباين الانحياز المحدد عند توفير الانحراف المعياري للضجيج.
خط أنابيب الدقة: لضمان التكافؤ العددي مع المرجع الخاص بالمعالج المركزي، يتعامل التنفيذ مع الدقة بعناية. وبينما تعالج العملية الرئيسية بيانات float32 أو float64 بناءً على المدخلات، فإن حساب الوزن الأسي يستخدم تقريب Schraudolph السريع (الذي يتطلب معالجة بتات الدقة المزدوجة) لإعادة إنتاج مخرجات scikit-image تطابقها بتّاً ببتّ.
تسلسل التخزين المؤقت للذاكرة المشتركة: إدراكاً لأن النواة (kernel) تعاني من محدودية الذاكرة (memory-bound) وليس الحوسبة، يستخدم التنفيذ استراتيجية تخزين مؤقت ديناميكية مكونة من أربعة مستويات للذاكرة المشتركة. في وقت التشغيل، يختار النظام الاستراتيجية الأكثر عدوانية (من المستوى 0 إلى المستوى 3) التي تناسب حجم الكتلة ومعلمات الرقعة ضمن ميزانية ذاكرة مشتركة ثابتة قدرها 46 كيلوبايت (مع ترك مساحة احتياطية لحد الـ 48 كيلوبايت في معالجات Pascal).
المستوى 3: يقوم بتخزين كامل نطاق البحث والرقعة في بلاطة واحدة، يتم تحميلها مرة واحدة لكل كتلة.
المستويان 2 و1: يمددان البلاطة المرشحة عبر محاور أقل لتقليل المساحة المستخدمة.
المستوى 0: يعيد تحميل البلاطة الكاملة عند كل إزاحة، ليكون بمثابة حل احتياطي عالمي.
يقوم النظام بالمرور من المستوى الأكثر عدوانية (المستوى 3) نزولاً إلى المستوى 0، ليختار أول تكوين صالح لحجم الكتلة ومعلمات الرقعة المطلوبة.
المساهمات الرئيسية
توزيع خالٍ من أدوات التطوير: تقدم الورقة حزمة بايثون عامة قابلة للتثبيت عبر pip (باسم nlm3d_cuda) لا تتطلب خطوة تجميع من قبل المستخدم النهائي، وتعمل بشكل متطابق على ويندوز ولينكس، بشرط وجود تعريف CUDA.
توافق تام في واجهة برمجة التطبيقات (API): يعمل التنفيذ كبديل مباشر لدالة denoise_nl_means في scikit-image؛ حيث يقبل نفس المعلمات (fast_mode و preserve_range و channel_axis) وينتج مخرجات لا يمكن تمييزها عددياً عن المرجع الخاص بالمعالج المركزي (ضمن حدود أخطاء التقريب العائم).
التحسين في وقت التشغيل: تقديم آلية اختيار مستويات الذاكرة المشتركة الديناميكية التي تتكيف مع معلمات الرقعة المحددة من قبل المستخدم دون الحاجة إلى ضبط يدوي أو إعادة تجميع.
النتائج أُجري اختبار الأداء على حجم اصطناعي بمقاس 500×500×500 باستخدام بطاقة NVIDIA GTX 1080 Ti (بمعمارية Pascal، وقدرة حسابية 6.1) مع patch_size=3 و patch_distance=3.
الأداء:
المرجع (المعالج المركزي - scikit-image الإصدار 0.26.0): 420–434 ثانية.
وحدة معالجة الرسومات (Float32): 3.25 ثانية (تسريع بمقدار 129–134 ضعفاً).
وحدة معالجة الرسومات (Float64): 7.82–7.83 ثانية (تسريع بمقدار 54–55 ضعفاً).
الدقة: كان أقصى فرق مطلق بين مخرجات وحدة معالجة الرسومات والمرجع المعالج المركزي هو 5.96×10−8 لـ Float32 و 3.21×10−8 لـ Float64. تُعزى هذه الانحرافات إلى اختلافات ترتيب التراكم في الحسابات العائمة في مستويات التخزين المؤقت العدوانية، وهي تظل ضمن الحدود العددية المقبولة.
سلوك محدودية الذاكرة: تؤكد نسب التسريع الملحوظة (وهي أقل بكثير من نسبة إنتاجية FP64:FP32 الخام البالغة 32:1 في معمارية Pascal) أن النواة مقيدة بالذاكرة، مما يؤكد صحة التركيز على أنماط الوصول إلى الذاكرة (التخزين المؤقت) بدلاً من تحسينات الدقة الحسابية.
الأهمية تدعي الورقة سد فجوة محددة في منظومة الحوسبة العلمية بلغة بايثون، وهي غياب تنفيذ GPU لـ 3D NLM عام ومتاح دون تعقيدات أدوات التطوير. ومن خلال تقليل وقت المعالجة من أكثر من سبع دقائق إلى أقل من ثماني ثوانٍ، ينقل هذا التنفيذ العملية من قيد "الدفعات فقط" إلى إمكانية "التفاعل الفوري". وهذا يسمح للمستخدمين بتضمين إزالة الضجيج كخطوة في سلاسل العمل حيث يمكنهم انتظار النتائج أو تكرار المعلمات في الوقت الفعلي، بدلاً من مجرد إرسال مهام تعمل في الخلفية. ويؤكد هذا العمل على سهولة الوصول، مما يمكّن الباحثين الذين يمتلكون محطات عمل قياسية (ويندوز أو لينكس) ووحدات معالجة رسومات CUDA من استخدام إزالة الضجيج ثلاثي الأبعاد عالية الأداء دون تعقيد بناء أدوات CUDA مخصصة.