- 연혁

디지털 신호 처리 (DSP)는 현대 임베디드 시스템의 백본이며 실시간 오디오, 비디오, 원격 측정 및 통신 작업을 가능하게합니다. DSP 작업에 대한 효율적인 C 코드를 직접적으로 시스템 처리량, 전력 소비 및 대기 시간에 영향을 미칩니다. 범용 코드와 달리 DSP 알고리즘은 제한된 메모리 및 처리 리소스의 사용을 극대화하면서 엄격한 타이밍 제약 내에서 수행해야합니다. 이 가이드는 핵심 원칙을 확장하고 DSP 애플리케이션의 생산 등급 C 코드를 작성하는 데 필요한 조치를 제공합니다. 고정 표준 하드웨어에 최적화 된 하드웨어.

C에서 DSP Fundamentals 이해

DSP는 필터링, 변형, 복잡한 분석, 샘플 신호에 대한 스펙트럼 분석과 같은 수학 작업을 포함합니다. C에서 프로그래머는 세분화적인 실행에 중요한 데이터 표현과 흐름의 모든 측면을 제어합니다. DSP 코드는 종종 하드웨어가 단단히 결합되는 디지털 신호 프로세서에서 실행됩니다. 예를 들어, 전용 MAC (다중 축적) 단위 또는 SIMD 벡터 엔진. 대상 아키텍처의 메모리, 기본 메모리 및 C 형 간섭 기능에 대한 깊은 이해는 필수적입니다. C는 C 형 간섭을 작성하는 데 필수적입니다.

DSP 부호의 중요한 특성:

  • Repeated arithmetic: 멀티플락 추가 작업 도미트와 루프 (예: FIR 필터).
  • Real-time constraints: 각 샘플은 샘플 기간 내에 처리되어야 합니다.
  • 데이터 스트리밍: 연속 입력/출력 스트림은 효율적인 버퍼링과 최소 복사가 필요합니다.
  • Memory 대역폭 경계: 많은 DSP 알고리즘은 빠른 데이터가 이동할 수 있는 방법, arithmetic 가동에 의해 제한됩니다.

기초 참조를 위해 Analog 장치 ' DSP Basics]를 참조하십시오.

고정점 Arithmetic: 뜨 점 머리 없는 정밀도

많은 DSP 프로세서는 하드웨어 부동점 단위 (FPUs) 또는 느린 FPUs가 부족합니다. 고정점 이론적 인 사용은 불쾌한 반경 점을 가진 정수 가동을 사용하여, 세례적인 성과 및 낮은 전력 소비를 제공합니다. 가장 일반적인 표현은 Q 표기입니다: Qm].]n] [FLT:[FLT:]]]:[FLT:]]:[FLT:]]:[FLT:]]]:]]

C에서 고정 포인트 작동 구현

고정 포인트는 직선 (매우 정수를 추가)이지만, 멀티 복제는 반경 점을 조정해야합니다. Q15 멀티 응용 프로그램을 위해 2 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 비트 축적자 및 포화 결과를 사용하십시오. ARM CMSIS-DSP와 같은 고정 지점 라이브러리를 제공 필터링, 변형, 매트릭스 작업.

고정 포인트 대 플로팅 포인트를 사용 할 때

FPU(예: Cortex-M4/M7)을 사용한 현대 프로세서는 고정점으로 플로팅 포인트 작업을 빠르게 수행할 수 있습니다. 플로팅 포인트를 사용할 때:

  • Algorithm 동적 범위는 높은 (예를들면, 적응 필터)입니다.
  • Code maintainability는 우선권 (무연한 사기 분석)입니다.
  • FPU 하드웨어는 현재 및 파이프라인은 overlap adds 및 multiplies 할 수 있습니다.

FPU 없이 고형 기기에서 고정점은 비용 감지 애플리케이션의 표준을 유지한다.

DSP에 대한 최적의 메모리 액세스

DSP 알고리즘은 종종 데이터의 큰 배열을 순차적으로 처리합니다. 캐시 미스트 및 버스 씰은 성능을 죽일 수 있습니다. 이러한 원리를 따르십시오.

  • 라인 데이터 액세스: contiguous order의 트래버스 어레이 (C에서 row-major). 알고리즘에 의해 요구되는 경우, 액세스 패턴을 강제하지 마십시오 (예: FFT bit-reversal).
  • Data 정렬:은 배열이 캐시 라인 경계에 정렬됩니다. 또는 특수 메모리 섹션과 같은 컴파일러 속성을 사용합니다.
  • Buffering: CPU 처리와 overlap DMA 전송에 두 배 버퍼링을 사용합니다. CPU가 한 버퍼에서 작동하면서, 다음 샘플 블록이로드됩니다.
  • 키워드: C99의 ]를 사용해서 포인터가 별명이 아닌 컴파일러를 알 수 있도록 벡터화와 더 나은 교육 스케줄링을 할 수 있습니다.

예를 들어, 간단한 FIR 필터 함수는 입력 및 출력 버퍼가 분리될 때 `restrict`로 작성되어야 합니다.

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);
 }
}

효율적인 알고리즘 선택 및 구현

Algorithmic complexity는 직접 시간과 힘을 실행하는 번역합니다. 항상 작업에 가장 효율적인 알고리즘을 선택합니다.

  • Fast Fourier Transform (FFT): 쿨리-Tukey radix-2 또는 파워-of-two 길이를 위한 스플래드릭스를 사용합니다. O(N2)인 네이티브 DFT를 피하십시오. 롬의 Precompute twiddle 인자와 저장소를 사용하십시오.
  • FIR 필터: decimation/interpolation에 대한 polyphase decomposition; 여러 개의 곱셈을 halve 선형 단계 필터에 대 한 심리학을 악용.
  • IIR 필터: use direct form II transposed for better numerical 안정성; 계수 정량에 대한 감도를 줄이기 위해 케이캐드 건수면(초순서 단계)를 사용 합니다.
  • Convolution: 긴 순서에 대한, FFT 기반 오버랩 추가 또는 오버랩-저장 방법을 직접 볼링보다.

FFTW library] 현대 FFT 기술에 대한 참조를 위해 (C에서하지 않는, 그것의 원칙은 널리 내장 된 DSP 라이브러리에 복사됩니다).

하드웨어 특징 활용: SIMD 및 DSP 지침

거의 모든 현대 마이크로 제어기는 SIMD (단일 지침 다중 데이터) 또는 DSP-enhanced 지침을 포함합니다. 예를 들어:

  • ARM Cortex-M4/M7: SIMD (SADD, SMUAD, 등), 포화 arithmetic 및 분수 가동 (QADD, QSUB). CMSIS-DSP 본질적인 기능을 사용하십시오.
  • TI C6000 DSP: 8개의 곱셈 단위, 이중 MAC 및 소프트웨어 pipelining. ]TI DSP 최적화 가이드]는 상세한 기술을 제공합니다.
  • P-extensions를 가진 RISC-V: 미래 핵심은 DSP 같이 지시가 있을 것입니다.

C의 이러한 기능을 사용하려면 컴파일러가 자동 학습 (예 : 의존성없이 간단한 루프) 또는 컴파일러 인트리니컬 기능을 사용하여 코드를 작성하십시오. FIR 필터의 ARM CMSIS-DSP를 사용하여 예 :

#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 알고리즘은 루프 중력이므로 루프 레벨의 최적화는 큰 배당을 지불합니다.

  • Loop unrolling: 수동으로 또는 컴파일러 pragmas (`#pragma unroll N`) 반복 오버 헤드를 감소시키고 명령 레벨 병렬을 증가시키기 위해.
  • Software pipelining: 여러 반복이 비행중에 있다 그래야 구조 루프를 동시에 합니다. 몇몇 컴파일러는 이것을 자동적으로 합니다; `-O3`와 건축별 플래그를 사용하십시오.
  • Reduce 분지: arithmetic (e.g., ternary를 사용하여 min/max)를 가진 조건을 대체하거나 nonlinear 기능을 위한 lookup 테이블을 사용하십시오.
  • 사용 로컬 변수: 저장 자주 접근된 데이터는 반복 내부의 변수를 선언하거나 `register` hint를 사용하여 등록합니다.
  • 부분의 부분:은 reciprocal에 의해 곱셈과 상수로 분할을 대체합니다; 2의 힘을 위한 이동을 사용합니다.

Precomputing Constants 및 Lookup 테이블

삼각대 값, 계수, 그리고 철자 요인과 같은 DSP 기능은 ROM에 있는 일정한 배열로 전산화되고 저장되어야 합니다. 비 일류 시작을 위해, 당신은 그(것)들을 한 번 그리고 재사용할 수 있습니다. 보기: 1024-point FFT를 위해, 각 단계를 위한 사인/코신 가치를 전산화하십시오. 이것은 주회할 평가를 삭제하고 힘을 감소시킵니다.

Lookup Table (LUTs)는 사각형 루트, exponent, 그리고 DSP (예: 연설 처리)에서 사용되는 로그와 같은 기능을 위해 도움을 줍니다. 테이블 항목 간의 선형 교환을 사용하여 메모리 대 정확도를 거래하십시오.

직업 및 조정

최적화는 측정 없이 완료되지 않습니다. 이러한 기술을 사용하여 Bottleneck을 식별하십시오.

  • Cycle-accurate profiling:] 함수 내구를 측정하기 위해, Cortex-M에 DWT CYCCNT를 내장하여 온보드 사이클 카운터(e.g., DWT CYCCNT)를 사용합니다.
  • Statistical 프로파일링: 샘플 프로그램 카운터(PC)는 CPU 시간을 소비하는 기능을 볼 수 있습니다.
  • Memory 프로파일링: 캐시미트를 모니터링하는 도구(사용 가능한 경우) 및 버스 거래.
  • Compiler Feedback: 컴파일러 최적화 보고서를 활성화('-fopt-info-vec-optimized' in GCC) 루프가 벡터화 된 경우.

Iterate: 측정, 변경, 다시 측정. 가장 큰 이득은 tweaking arithmetic 보다는 오히려 기억 접근 본을 개량에서 옵니다.

실제 요약 : 함께 가져 오기

C의 효율적인 DSP 코드를 작성하면 전체적인 접근 방식을 요구합니다.

  • 올바른 데이터 표현 (fixed-point vs Floating-point)를 선택하십시오.
  • 숙련된 데이터 구조와 alignment를 설계합니다.
  • 낮은 복잡성(FFT, polyphase) 알고리즘을 선택합니다.
  • 사용할 때 공급 업체 DSP 라이브러리를 사용하십시오.
  • 언롤 루프 및 분지 감소.
  • ROM의 상수.
  • relentlessly 프로필을 작성하고 컴파일러 도움을 준다.

이러한 원칙을 적용함으로써 개발자는 C의 패시성과 유지성을 유지하면서 손으로 조립된 조립에 대해 비교할 수 있는 신호 처리 처리 처리 처리 처리 처리량을 달성할 수 있습니다. 이 결과는 신뢰할 수 있고, 현대 임베디드 제품의 요구를 충족하는 실시간 DSP 시스템입니다. 보청기에서 5G 기지국.