مقدمه مقدماتی

پردازش سیگنال دیجیتال (DSP) ستون فقرات سیستم های جاسازی شده مدرن است، قادر به صدا، ویدئو، تله سنج و عملیات ارتباطات است. نوشتن کد کارآمد C برای وظایف DSP به طور مستقیم بر سیستم از طریق قطع، مصرف برق و تأخیر سیستم تأثیر می گذارد. برخلاف کد کلی، الگوریتم های DSP باید در محدودیت های زمان دقیق اجرا کنند در حالی که به حداکثر رساندن استفاده از حافظه محدود و پردازش منابع این راهنمای اصلی برای توسعه تکنیک های کاربردی دقیق و کاربردی برای نوشتن کد های کاربردی، از کد های محاسباتی، به طور دقیق، دستورالعمل های محاسباتی، به حداکثر رساندن کد های محاسباتی، و پردازش، به حداکثر رساندن کد های محاسباتی، به حداکثر رساندن کد های محاسباتی، به حداکثر رساندن.

درک تفاوت های اساسی در C

DSP شامل عملیات ریاضی مانند فیلترینگ، تبدیل، تکامل و تجزیه و تحلیل طیفی در سیگنال های نمونه شده است.در C، برنامه نویس کنترل هر جنبه از نمایندگی داده و جریان، که برای اجرای تعیین کننده کد جانبی اغلب بر روی میکروکنترلرها یا پردازنده های سیگنال دیجیتال که سخت افزار به آن متصل است - به عنوان مثال، MAC اختصاص داده شده (چندین-accumul) یا واحدهای دستورالعمل های کاربردی، ساختار هدف و ساختار هدف، مجموعه ای است.

ویژگی های کلیدی کد DSP:

  • محاسبه مجدد: حلقه با عملیات چند برابر غالب (به عنوان مثال، فیلترهای FIR).
  • محدودیت های زمان واقعی: [FLT 1] هر نمونه باید در یک دوره نمونه پردازش شود.
  • جریان داده: جریان های ورودی / خروجی مداوم نیاز به بافر کارآمد و حداقل کپی برداری دارند.
  • پهنای باند حافظه محدود است: بسیاری از الگوریتم های DSP با سرعت داده ها می توانند منتقل شوند، نه توسط عملیات محاسباتی.

برای یک مرجع بنیادی، ببینید تجهیزات اکسپلکس

Arithmetic: بدون شناور بدون نقطه شناور

بسیاری از پردازنده های DSP فاقد واحدهای شناور سخت افزاری (FPUs) یا دارای سرعت کمتری از FPU هستند؛ محاسبات ثابت با نقطه رای ضمنی، عملکرد تعیین کننده و مصرف انرژی پایین تر، QLT 6، 0 [FLT] [FLT] [F=1] [F=2 ] [F [F] [F3] [F [F] [F [F [F] [F [F] [F [F [2 ] [2 ] [2 ] [ [2 ] [2 ] [ [ [ [ [شکل ] [شکل ] [F ] [ [ [F ] [F ] [F ] [F [F ] [F ] [شکل ] [F ] [F ] [شکل ] [ [ [ [ [شکل ] [ [شکل ] [شکل ] [ [ [ [شکل ] [شکل ] [شکل ] [ [شکل ] [شکل ] [شکل ] [شکل ] [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [2 ] [شکل ] [ [شکل ] [شکل ] [ [ [ [ [2 ] [شکل ] [ [ [ [ [ [ [ [ [ [ [ [ [شکل ] [شکل ] [شکل ] [شکل ]

اجرای عملیات ثابت در C

اضافه کردن نقطه ثابت (به سادگی اضافه کردن صحیح) ساده است، اما ضرب نیاز به تنظیم نقطه راکس دارد.برای ضرب Q15، محصول دو عدد Q15 به یک نتیجه متوسط 32 بیتی نیاز دارد، سپس شما به طور صحیح 15 بیت برای بازگشت به Q15.

typedef int16_t q15_t;
q15_t q15_mul(q15_t a, q15_t b) {
 int32_t temp = (int32_t)a * (int32_t)b;
 return (q15_t)(temp >> 15);
}

هنگامی که تجمع رخ می دهد (به عنوان مثال، در فیلتر)، بیت های محافظ از سرریز جلوگیری می کنند.استفاده از 32 بیتی یا حتی 64 بیتی از آنزیم ها و نتایج اشباع شده، کتابخانه های نقطه ثابت مانند (FLT:0ARM CMS-DSP توابع نقطه ثابت بهینه شده را شامل فیلتر، تبدیل، و عملیات ماتریس ارائه می دهد.

هنگام استفاده از نقطه ثابت در مقابل شناور

پردازنده های مدرن با FPUs (به عنوان مثال، Cortex-M4/M7) می توانند عملیات شناور را به سرعت به عنوان نقطه ثابت اجرا کنند.

  • محدوده دینامیکی الگوریتم بالا است (به عنوان مثال، فیلترهای سازگار).
  • قابلیت نگهداری کد یک اولویت است (تحلیل مقیاس پذیری کم).
  • سخت افزار FPU موجود است و خط لوله می تواند همپوشانی و چند برابر داشته باشد.

در دستگاه های با حجم بالا بدون FPUs، نقطه ثابت همچنان استاندارد برای برنامه های حساس به هزینه است.

بهینه سازی دسترسی به حافظه DSP برای

الگوریتم های DSP اغلب آرایه های بزرگ داده ها را به طور متوالی پردازش می کنند.ک.ک.ک.ک.ک.چ و غرفه های اتوبوس می توانند عملکرد خود را از دست بدهند.

  • دسترسی به داده های خطی: آرایه های عبور در دستور فشرده (در C) اجتناب از الگوهای دسترسی گام به گام مگر اینکه توسط الگوریتم مورد نیاز باشد (به عنوان مثال، FFT کمی در حال گفتگو).
  • تراز داده: آرایه ها برای حفظ مرزهای خط کش تراز هستند، از ویژگی های کامپایلر مانند یا بخش های حافظه خاص استفاده کنید.
  • بربریت: استفاده از بافر دو بافر برای همپوشانی انتقال DMA با پردازش CPU.در حالی که CPU بر روی یک بافر کار می کند، بلوک نمونه بعدی بارگیری می شود.
  • کلمه کلیدی محدود: استفاده از C99 در اشاره کنندگان به اطلاع از کامپایلر که اشاره کنندگان alias، فعال سازی و برنامه ریزی بهتر آموزش نیست.

به عنوان مثال، یک تابع ساده فیلتر FIR باید با trict نوشته شود، زمانی که درب ورودی و خروجی جداگانه هستند:

void fir_lowpass(const int16_t * restrict x, int16_t * restrict y,
 const int16_t * restrict coeffs, int len, int order) {
 for (int i = 0; i < len; i++) {
 int32_t acc = 0;
 for (int j = 0; j < order; j++) {
 acc += (int32_t)x[i + j] * coeffs[j];
 }
 y[i] = (int16_t)(acc >> 15);
 }
}

انتخاب الگوریتم کارآمد و اجرای

پیچیدگی الگوریتمی به طور مستقیم به زمان اجرای و قدرت ترجمه می شود، همیشه کارآمدترین الگوریتم را برای این کار انتخاب کنید:

  • چهار تحول سریع (FFT): از Cooley-Tukey رادونیکس-2 یا تقسیم بندی برای قدرت دو طول اجتناب از ساده لوحی که O(N2) است، استفاده کنید. Precompute twiddle فاکتورها و ذخیره در ROM.
  • فیلترهای FIR: از تجزیه و تحلیل چند فاز برای تصمیم گیری / قطبی استفاده کنید؛ بهره برداری از تقارن برای فیلترهای خطی فاز به نصف کردن تعداد ضرب و شتم.
  • فیلترهای IIR: از فرم مستقیم II برای ثبات عددی بهتر استفاده کنید؛ از بخش های دودویی آبشاری (مرحله دوم سفارش) برای کاهش حساسیت به ضریب سنجی استفاده کنید.
  • [[۱] [۱۰] [۱] [۱۰] [۱] برای توالی های طولانی، استفاده از روش های همپوشانی یا همپوشانی به جای اتصال مستقیم.

به کتابخانه FFTW [FLT 1] مراجعه کنید تا به تکنیک های مدرن FFT (اگر چه در C نیست، اصول آن به طور گسترده ای در کتابخانه های جاسازی شده کپی شده است).

ویژگی های سخت افزاری: SIMD و دستورالعمل های DSP

تقریبا تمام میکروکنترلرهای مدرن شامل سیم کارت (داده های چندگانه) یا دستورالعمل های مربوط به DSP می باشند.

برای استفاده از این ویژگی ها در C، کد بنویسید که کامپایلر می تواند خودکار سازی کند (به عنوان مثال، حلقه های ساده بدون وابستگی) یا از توابع کامپایلر استفاده کند.

#include "arm_math.h"
arm_fir_instance_f32 S;
float32_t firState[128];
arm_fir_init_f32(&S, numTaps, coeffs, firState, blockSize);
arm_fir_f32(&S, input, output, blockSize);

این کتابخانه ها در تجمع برای حداکثر عملکرد، همیشه پروفایل قبل و بعد از تغییر از C عمومی به توابع کتابخانه، به دست آورده اند.

تکنیک های بهینه سازی حلقه

از آنجا که الگوریتم های DSP حلقه ای هستند، بهینه سازی در سطح حلقه سودهای بزرگ را پرداخت می کند:

  • بدون ثبت نام: به صورت دستی یا با کامپایلر pragmas (#pragma unroll N) برای کاهش حلقه و افزایش موازین سطح دستورالعمل.
  • لوله کشی نرم افزار: [FLT 1] حلقه های بازسازی به طوری که چندین ⁇ به طور همزمان پرواز می کنند، برخی از کامپایلرها این کار را به صورت خودکار انجام می دهند؛ استفاده از پرچم های خاص معماری و معماری.
  • (FLT:0) شاخه بندی: جایگزین مشروط با محاسبه (به عنوان مثال، من / حداکثر استفاده از ternary)، یا استفاده از جداول جستجو برای توابع غیر خطی.
  • از متغیرهای محلی استفاده کنید: ذخیره اغلب داده ها را در ثبت نام با اعلام متغیرها در داخل حلقه یا استفاده از اشاره "register" به ثبت رساند.
  • [[۱] [۱۰] تقسیم بندی: [[۱۰] [۱] [۱]] [۱] [۱] [۱] [۱] تقسیم بندی با ضرب و شتم ثابت با استفاده از تغییر برای قدرت دو.

جدول های مقدماتی و مقدماتی

توابع DSP مانند مقادیر مثلثی، ضریب ها و عوامل نفوذ باید به صورت آفلاین و ذخیره شده به عنوان آرایه های ثابت در ROM. برای استارت آپ غیر واقعی، شما می توانید آنها را یک بار محاسبه و استفاده مجدد کنید: برای یک FFT، پیش فرض کردن ارزش های گناه /cosine برای هر مرحله این ارزیابی زمان و کاهش قدرت.

جداول جستجو (LUTs) همچنین به توابع مانند ریشه مربع، اکتشافی و log مورد استفاده در DSP (به عنوان مثال، در پردازش گفتار) کمک می کند.استفاده از interpolation خطی بین ورودی های جدول برای تجارت حافظه در مقابل دقت.

حرفه ای و تونس

هیچ بهینه سازی بدون اندازه گیری کامل نیست.استفاده از این تکنیک ها برای شناسایی تنگنا:

  • پروفایل دایره ای (cycle-accurate) : از شمارنده های چرخه (به عنوان مثال DWT CYCCNT در Cortex-M) برای اندازه گیری طول عمر استفاده کنید.
  • ] [شاخص آماری] : برنامه نمونه (PC) برای دیدن اینکه چه عملکردی زمان CPU مصرف می کند.
  • پروفایل حافظه: از ابزار برای نظارت بر از دست دادن (در صورت امکان) و معاملات اتوبوس استفاده کنید.
  • بازخورد مقایسه ای: گزارش های بهینه سازی کامپایلر (فف-info-vec بهینه شده در GCC) را قادر می سازد تا ببیند آیا حلقه ها از بین رفته اند.

اندازه گیری، تغییر، اندازه گیری دوباره، اغلب بزرگترین دستاوردهای از بهبود الگوهای دسترسی به حافظه به جای اصلاح حساب می آیند.

خلاصه عملی: آوردن آن همه با هم

نوشتن کد پیشرفته DSP در C نیازمند یک رویکرد جامع است:

  • نمایش داده های مناسب (در نقطه ثابت در مقابل شناور) را انتخاب کنید.
  • طراحی ساختارهای داده برای دسترسی و هماهنگی متوالی
  • الگوریتم های با پیچیدگی پایین (FFT، Poly phase) را انتخاب کنید.
  • استفاده از کتابخانه های DSP در دسترس
  • حلقه های بدون پا و کاهش شاخه
  • ثابت های Precompute در ROM
  • بی وقفه پروفایل کنید و اجازه دهید کامپایلر کمک کند.

با استفاده از این اصول، توسعه دهندگان می توانند پردازش سیگنال را با استفاده از نمایندگان قابل مقایسه با مونتاژ دستی در حالی که حفظ قابلیت حمل و نگهداری C است، دستیابی به سیستم های قابل اعتماد و زمان واقعی DSP است که نیازهای محصولات مدرن جاسازی شده را برآورده می کنند - از سمعک تا ایستگاه های پایه 5G.