سؤال

يعمل مشروع معالجة الصور الخاص بي مع صور GraysCale. لدي منصة معالج ARM Cortex-A8. أريد أن أستفيد من النيون.

لدي صورة رمادية (ضع في اعتبارك المثال أدناه) وفي ALOGORITHM ، لا بد لي من إضافة الأعمدة فقط.

كيف يمكنني التحميل أربع قيم بكسل 8 بت بالتوازي ، والتي هي uint8_t, ، كما أربعة uint32_t في واحدة من سجلات النيون 128 بت؟ ما هو الجوهري الذي يجب أن أستخدمه للقيام بذلك؟

أعني:

alt text

يجب أن أحملها على أنها 32 بت لأنه إذا نظرت بعناية ، في اللحظة التي أقوم فيها 255 + 255 هي 512 ، والتي لا يمكن عقدها في سجل 8 بت.

على سبيل المثال

255 255 255 255 ......... (640 pixels)
255 255 255 255
255 255 255 255
255 255 255 255
.
.
.
.
.
(480 pixels) 
هل كانت مفيدة؟

المحلول

سأوصي بأن تقضي بعض الوقت في فهم كيفية عمل SIMD على ARM. ينظر الى:

ألق نظرة على:

  1. http://blogs.arm.com/software-enablement/161-coding-for-neon-bart-1-load-and-stores/
  2. http://blogs.arm.com/software-enablement/196-coding-for-neon-bart-2-dealing-with-leftovers/
  3. http://blogs.arm.com/software-enablement/241-coding-for-neon-bart-3-matrix-multiplication/
  4. http://blogs.arm.com/software-enablement/277-coding-for-neon-bart-4-shifting-left-and-right/

لتبدأ. يمكنك بعد ذلك تنفيذ رمز SIMD الخاص بك باستخدام ANDLINE ASSEMBLER أو HUNTRONSIC ARM المقابل الموصى به من قبل DOMEN.

نصائح أخرى

يعتمد على المترجم الخاص بك و (احتمال عدم وجود) امتدادات.

بمعنى آخر. بالنسبة إلى GCC ، قد تكون هذه نقطة انطلاق: http://gcc.gnu.org/onlinedocs/gcc/arm-neon-intrinsics.html

إذا كنت بحاجة إلى تلخيص ما يصل إلى 480 قيم 8 بت ، فستحتاج تقنيًا إلى 17 بت من التخزين الوسيط. ومع ذلك ، إذا قمت بإجراء الإضافات على مرحلتين ، أي أعلى 240 صفًا ثم أسفل 240 صفًا ، يمكنك القيام بذلك في 16 بت. ثم يمكنك إضافة النتائج من نصفين للحصول على الإجابة النهائية.

هناك في الواقع تعليمات النيون المناسبة لخوارزمية تسمى VADDW. سيضيف متجه DWORD إلى متجه QWORT ، مع وجود عناصر تحتوي على عرض مرتين مثل السابق. في حالتك ، يمكن استخدام vaddw.u8 لإضافة 8 بكسل إلى 8 بتر مراكم 16 بت. بعد ذلك ، يمكن استخدام vaddw.u16 لإضافة مجموعتين من 8 بتر مراكم في مجموعة واحدة من 8 32 بت-لاحظ أنه يجب عليك استخدام التعليمات مرتين للحصول على كلا النصفين.

إذا لزم الأمر ، يمكنك أيضًا تحويل القيم إلى 16 بت أو 8 بت باستخدام VMOVN أو VQMOVN.

لا توجد تعليمات يمكنها تحميل قيمة 4 8bit في سجل 4 32 بت.

يجب تحميلها ثم استخدام VSHL مرتين. نظرًا لأن النيون لا يمكنه استخدام 32 سجلًا ، فسوف يتعين عليك العمل على 8 بكسل (وليس 4)

يمكنك استخدام سجل 16 بت فقط. يجب أن يكون كافيا ...

قم بتحميل 4 بايت باستخدام تعليمات تحميل حارة واحدة (vld1 <register>[<lane>], [<address]) في Q-register ، ثم استخدم تعليمين طويلتين (vmovl) للترويج لهم أولاً إلى 16 ثم إلى 32 بت. يجب أن تكون النتيجة شيئًا مثل (في بناء جملة GNU)

vld1 d0[0], [<address>] @Now d0 = (*<addr>, *<addr+1>, *<addr+2>, *<addr+3>, <junk>, ... <junk> )
vmovl.u8 q0, d0 @Now q1 = (d0, d1) = ((uint16_t)*<addr>, ... (uint16_t)*<addr+3>, <junk>, ... <junk>)
vmovl.u16 q0, d2 @Now d0 = ((uint32_t)*<addr>, ... (uint32_t)*<addr+3>), d1 = (<junk>, ... <junk>)

إذا كنت تستطيع ضمان ذلك <address> هو محاذاة 4 بايت ، ثم اكتب [<address>: 32] بدلاً من ذلك في تعليمات التحميل ، لحفظ دورة أو اثنين. إذا قمت بذلك ولم يكن العنوان محاذاة ، فستحصل على خطأ.

أم ، لقد أدركت فقط أنك تريد استخدام الجوهارات ، وليس التجميع ، لذلك هذا هو نفس الشيء مع الجوهارات.

uint32x4_t v8; // Will actually hold 4 uint8_t
v8 = vld1_lane_u32(ptr, v8, 0);
const uint16x4_t v16 = vget_low_u16(vmovl_u8(vreinterpret_u8_u32(v8)));
const uint32x4_t v32 = vmovl_u16(v16);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top