현재 위치 - 중국 분류 정보 발표 플랫폼 - 중고환승안내 - 온라인 고득점 도움말 등: 2명의 어셈블러를 하나로 결합

온라인 고득점 도움말 등: 2명의 어셈블러를 하나로 결합

C6000 프로그램을 작성하고 디버깅할 때 C6000 코드의 최상의 성능을 얻으려면 소프트웨어 프로그래밍의 세 단계를 따라야 합니다. 각 단계에서 완료되는 작업은 다음과 같습니다[4]. ​

첫 번째 단계: 처음에는 C6000 관련 지식을 무시하고 전적으로 작업을 기반으로 C 언어 프로그램을 작성할 수 있습니다. CCS 환경의 C6000 코드 생성 도구를 사용하여 C6000에서 실행되는 코드를 컴파일하고 생성하여 해당 기능이 올바른지 증명하십시오. 그런 다음 디버그 및 프로파일러와 같은 CCS 디버깅 도구를 사용하여 코드에 존재하고 성능에 영향을 미칠 수 있는 비효율적인 섹션을 분석하고 확인합니다. 코드 성능을 더욱 향상하려면 두 번째 단계가 필요합니다.

두 번째 단계: 인라인 함수, CCS 컴파일 옵션 및 기타 특정 최적화 방법을 사용하여 C 언어 프로그램을 개선합니다. 첫 번째 단계를 반복하고 결과 C6000 코드의 성능을 확인합니다. 생성된 코드가 여전히 원하는 성능을 달성할 수 없는 경우 세 번째 단계로 들어갑니다.

세 번째 단계: C 언어 프로그램에서 성능에 큰 영향을 미치는 프로그램 세그먼트를 추출하여 선형 어셈블리로 다시 작성한 다음 어셈블리 최적화 프로그램을 사용하여 원하는 성능 요구 사항이 달성될 때까지 최적화하고 연결합니다. .

G.729A 표준 코덱의 실시간 요구 사항과 관련하여 세 번째 단계는 작업의 초점이며 선형 어셈블리의 재작성은 프로그램 코드의 특성에 대한 완전한 이해와 DSP.

3. G.729A 코드 분석

CCS 통합 개발 환경은 소프트웨어 개발자에게 효율적인 개발 및 디버깅 도구를 제공합니다. 특히, 특정 코드 간격으로 프로그램 실행에 대한 통계적 성능을 수집하여 프로그램 내의 각 세그먼트와 각 하위 기능이 소비하는 프로세서 시간을 분석하고 판단하여 최적화에 집중하는 프로파일러용 최적화 도구를 제공합니다. 프로그램 성능에 가장 큰 영향을 미치는 코드 세그먼트가 나열되어 있습니다 [5]. 두 가지 테스트 방법은 다음과 같습니다.

(1) 복잡성을 측정해야 하는 프로그램 세그먼트의 시작과 끝 부분에 두 개의 중단점을 설정하고 시계 창을 열고 프로그램을 실행합니다. 첫 번째 중단점에서 실행이 중지됩니다. 이때 시계 창을 두 번 클릭하여 0으로 초기화합니다. 그런 다음 프로그램을 계속 실행하고 두 번째 중단점에서 중지합니다. 이때 시계 창에 표시되는 값은 의 복잡도입니다. 코드. 이는 프로그램에서 기능의 복잡성을 테스트하는 데 매우 유용합니다.

(2) 먼저 통계 창을 열고 테스트해야 할 프로그램 세그먼트의 시작과 끝 부분에 통계 포인트(Probe Points)를 설정합니다. 프로그램 실행 후 프로그램 뒤에 있는 통계 값입니다. 통계 창의 세그먼트는 코드 세그먼트의 복잡성입니다. 이 방법은 수동 개입 없이 자동으로 통계 정보를 수집합니다. 이는 프로그램의 여러 코드 세그먼트의 복잡성을 측정하는 데 매우 유용합니다. >

4. 선형 어셈블리 최적화<. /p>

선형 어셈블리는 TI에서 제공하는 어셈블리 언어로, 명령어 체계는 어셈블리 언어와 완전히 동일하지만 레지스터와 레지스터를 지정할 필요가 없습니다. 쓰기 시 연산 단위가 필요하며 지연 문제를 고려할 필요가 없으므로 선형 어셈블리를 작성하는 것이 상대적으로 쉽습니다. [6]

최적화의 첫 번째 및 두 번째 단계 후에는 오디오의 실행 상태가 달라집니다. DM642의 인코딩 프로그램은 크게 개선되었지만 테스트 후에도 여전히 실시간 효과는 달성되지 않았으며 고급 언어의 효율성은 거의 최대화되었습니다. 36.5 프레임/초. 최적화 이전의 10배. 이때 선형 어셈블리 언어를 사용하여 C 코드의 비효율적인 부분을 다시 작성하고 프로그램의 실행 효율성을 더욱 향상시키며 DM642의 하드웨어 리소스를 최대한 활용하고 최종적으로 G를 구현했습니다. 설계 요구 사항에 따라 실시간으로 DM642에서 729A 코딩을 수행합니다. 이전 DSP 개발 프로세스에서 언급했듯이 DSP 개발의 마지막 방법은 어셈블리에서 C를 다시 작성하는 것입니다. 왜냐하면 병렬 프로세서용 어셈블리를 작성하는 것이 매우 어렵기 때문입니다. 즉, 프로그램의 주요 부분은 C 코드로 작성되고, 다른 부분은 C 코드로 작성되어 시간이 많이 걸리는 기능을 선형 어셈블리로 다시 작성할 수 있습니다.

선형 어셈블리 최적화 코드를 작성하는 과정에서 코드 실행 효율성을 높이기 위해 다음 원칙을 따라야 합니다 [7]:

(1) 병렬 코드 작성: 어셈블리 명령어를 사용하여 병렬 실행 방법은 루프 내의 실행 주기 수를 줄이고 선형 어셈블리 코드를 최적화합니다. 여기서 중요한 문제는 관련되지 않은 명령어만 병렬로 실행할 수 있도록 명령어 종속성을 파악하는 것입니다. 명령어가 관련되어 있는지 확인하려면 상관 다이어그램을 사용할 수 있습니다.

(2) 점프 명령 처리 및 전송 명령: 조립 프로그램의 주요 특징은 점프가 빈번하다는 것입니다. 다른 조건이 충족되면 프로그램이 다른 작업을 수행하거나 해당 위치로 점프해야 합니다. "보다 큼", "보다 크거나 같음", "보다 작음", "작거나 같음"과 같은 긴밀한 논리적 판단 및 처리는 주의해서 처리해야 합니다. 그렇지 않으면 논리적 오류가 발생하여 디버그하기가 어렵습니다. 이 현상은 오버플로가 발생할 때 특히 두드러지며 이에 따라 처리해야 합니다.

(3) 루프 본문의 명령 수 최소화: G.729A의 알고리즘 구현 중 상당수는 고정 코드북 검색 프로세스와 같은 일부 위치에서 완료됩니다. 0이 아닌 4개 결정 펄스의 위치와 진폭도 여러 사이클을 사용하여 결정됩니다. 루프 내에서, 특히 깊게 중첩된 루프 내에서 명령어 하나를 줄이면 프로그램 작업 수가 크게 줄어들 수 있습니다. 예를 들어, 루프당 8개의 루프가 있는 4중 중첩 루프의 경우 가장 안쪽 루프에서 감소된 각 명령에 대해 전체 프로그램은 84 = 4096개의 더 적은 문을 실행할 수 있습니다. 따라서 프로그램을 설계할 때 루프 외부에서 실행될 수 있는 명령문은 최대한 루프 외부에서 실행되도록 해야 합니다.

(4) 프로그램 본체 확장: 특정 조건에서는 시간을 위해 공간을 희생하면서 서브루틴 호출 및 리턴 수를 줄이기 위해 프로그램을 최대한 확장합니다.

G.729A 알고리즘의 LPC 모듈, LSP 양자화 및 여기 코드북 검색은 코드 효율성을 더욱 향상시키기 위해 관련 계산 및 FIR 필터링과 같은 일부 기능을 선형으로 다시 작성했습니다. 어셈블리 언어를 사용하여 상관관계 다이어그램을 그리는 등의 방법을 사용하여 목표한 최적화를 수행합니다. 어셈블리 옵티마이저로 최적화한 후 C 언어로 직접 컴파일하는 것보다 코드 효율성이 크게 향상됩니다.

5. 최적화 작업의 혁신 포인트

G.729A 최적화에서 이 기사는 이전 연구 결과를 기반으로 TMS320DM642 DSP 시리즈 칩에 대한 몇 가지 귀중한 아이디어를 제시합니다. 방법. 이러한 혁신은 코드의 최적화 속도와 실행 효율성을 다양한 수준으로 향상시켰으며 음성 인코딩 및 디코딩을 위한 DSP의 실시간 구현에 핵심적인 역할을 했습니다. 아래에는 몇 가지 고전적인 방법이 예시로 설명되어 있습니다.

5.1 분석 다이어그램 그리기 및 함수 구조 익히기

명령문이 많고 구조가 복잡한 함수의 경우 논리 구조와 명령문의 상관 관계를 완전히 이해하기 위해 일반적으로 다음을 사용합니다. 도면 분석 다이어그램 방법. 분석 다이어그램의 형식은 비교적 유연하며 특정 상황에 따라 다양한 그리기 도구를 선택할 수 있습니다. 선형 어셈블리를 작성할 때 배열의 요소 액세스, 데이터 패키징 작업 및 데이터 상관 관계와 같은 문제를 고려해야 합니다. 분석 다이어그램은 이러한 문제를 올바르게 처리하는 데 도움이 됩니다.

Cor_h_X() 함수를 최적화하는 과정에서 몇 가지 어려움에 직면했습니다. 그 이유는 내부 레이어의 횟수가 외부 레이어와 관련되어 있기 때문입니다. 외부 레이어의 루프 수는 40개이며 루프 내부의 명령문은 순차적으로 연결됩니다. 이러한 구조에서 루프 확장을 사용하면 64개를 초과하는 많은 수의 레지스터가 사용됩니다. 임시 변수를 저장하려면 추가 메모리 공간을 열어야 하므로 메모리를 많이 소모하므로 실행 효율성이 떨어집니다. 충분히 개선될 것입니다. 이와 관련하여 우리는 그림 1과 같이 분석 다이어그램을 사용하여 함수의 키 코드 배열 X[ ] 및 h[ ]의 사용법을 설명합니다.

그림 1 cor_h_X() 함수 분석 다이어그램(일부)

그림 1은 배열 16비트 h[ ]와 임시 배열 32비트 Y[]에 저장된 16비트 간의 곱셈과 덧셈 관계를 직관적으로 반영합니다. 이 분석 다이어그램을 연구함으로써 우리는 h[ ]와 It의 일부 요소가 사용된 레지스터 수를 절약할 수 있고 메모리 공간을 열고 중간 변수에 대한 명령에 액세스할 필요가 없다는 것을 발견했습니다.

선형 어셈블리를 작성하기 위해 위의 아이디어를 사용하는 cor_h_X() 함수의 경우 작업을 완료하려면 57개의 레지스터만 정의하면 됩니다. 액세스 명령은 1760에서 30까지 최적화되어 있으며 이는 1/에 불과합니다. 60. 동시에 실행 속도는 390072 클럭에서 35871 클럭으로 줄어들어 원본의 1/10로 줄어듭니다.

작성된 분석 다이어그램에는 관련 다이어그램, 관련 테이블 등이 포함될 수 있어 리소스 배치가 더욱 합리적입니다. 이 방법은 다른 함수를 다시 작성할 때도 여러 번 사용되었습니다.

5.2 유사한 기능을 가진 함수 또는 코드 세그먼트를 하나의 함수로 병합

선형 어셈블리는 코드 효율성을 향상시킬 뿐만 아니라 코드 크기를 기하급수적으로 증가시킵니다. 위의 cor_h_X()를 예로 들어 보겠습니다. , 작성 후 코드 크기가 660에서 7776으로 증가했습니다(이 데이터는 CCS 프로파일링 도구로 분석되었습니다). 엔지니어링 애플리케이션에서는 제한된 메모리 프로그램 영역에 대해 프로그램이 차지하는 공간을 적절하게 줄입니다. 이는 유사한 기능을 가진 기능을 병합하여 달성할 수 있습니다.

LSP 양자화 처리에는 소스 코드에 Lsp_select_1( )과 Lsp_select_2( )라는 두 개의 LSP 선택 함수가 제공되어 있으며 동일한 기능과 유사한 구조를 가지고 있음을 확인했습니다. 둘을 선형 어셈블리로 적용하려면 LSP 양자화 처리에서 이 두 모듈의 기능을 실현하기 위해 함수(Lsp_select라는 이름)만 작성하면 됩니다.

또한 일부 배열 복사 및 배열 초기화 코드의 경우 이 방법을 사용하여 함수 구현을 작성할 수도 있으며, 이는 실행 효율성을 향상시키고 프로그램이 차지하는 메모리 공간을 줄일 수 있습니다.

5.3 여러 루프를 하나의 루프로 병합

C 코드를 선형 어셈블리로 다시 작성할 때 일부 조정만 수행하면 두 개 이상의 루프로 완료되는 작업이 다음과 같이 완료되는 경우가 종종 있습니다. 완전히 이것은 루프로 수행될 수 있습니다. LPC 서브모듈의 240포인트 윈도우 음성의 자기상관 계산 Autocorr() 함수를 예로 들면, 최적화되고 다시 작성된 C 코드(부분)는 다음과 같습니다:

for (i=0; i

y[i] = (_smpy(x[i], hamwindow[i])+0x00008000L)>>16;

sum = 1; //0의 상황을 피하세요.

for (i=0; i

sum = _sadd(sum,_smpy( y[ i], y[i]));

이 코드에는 두 개의 for 루프가 포함되어 있습니다. CCS에서 직접 컴파일하고 실행하면 병렬성이 떨어지므로 선형 어셈블리를 사용하여 코드가 다시 작성됩니다. 두 루프 본문의 루프 수가 60개(L_WINDOW=60)이고 처리되는 배열이 다르며 두 루프가 관련이 없으므로 첫 번째와 두 번째 루프를 하나의 루프로 병합할 수 있음을 확인했습니다. 전자의 기능은 음성 신호를 창으로 표시하는 것이고 후자는 곱셈과 누적을 구현하는 것입니다(Mac).

두 개가 병합된 후 코드는 다음과 같습니다.

mvk 60,i //루프 수 설정

loop1: lddw *ham++, hamih:hamil //hamwindow[] 포인터

lddw *x++,xih:xil //x[] 포인터

smpy2 hamil,xil,yi1:yi0 //2쌍의 16 -비트 피연산자는 상속되어 병렬로 실행됩니다.< /p>

smpy2 hamih,xih,yi3:yi2

sadd yi0,con0x8000,yi0

sadd yi1,con0x8000,yi1

sadd yi2, con0x8000,yi2

sadd yi3,con0x8000,yi3

packh2 yi1,yi0,yl //데이터 패키징 기술

packh2 yi3,yi2,yh

stdw yh:yl,*y++ //이중 단어 액세스, 실행 효율성 향상

smpy2 yl,yl,yi1:yi0

< p> sadd sum0,yi1,sum0< /p>

sadd sum0,yi0,sum0

smpy2 yh,yh,yi3:yi2

sadd sum0,yi3,sum0< /p>

sadd sum0, yi2,sum0

add i,-1,i

[i] b loop1 // 첫 번째와 두 번째 루프를 하나의 큰 루프로 결합합니다. 전송 횟수를 줄이기 위해

생성된 어셈블리 코드의 병렬 파이프라인 성능이 크게 향상되었으며, 소비되는 클록 사이클 수가 1,310,000에서 15,000으로 이전보다 1/8 미만으로 감소했습니다. 적응.

6. 결론

코덱 실행의 클럭 주기는 선형 어셈블리가 다시 작성되기 전과 후에 CCS의 프로파일러 분석 도구를 통해 파일 버전을 알 수 있습니다. 10 프레임(100MS)이 1억 5,970만 개에서 6,850만 개로 줄어들어 원래 수치의 42%에 불과합니다. 하드웨어 버전을 테스트한 결과 인코딩 및 디코딩된 프레임 수가 88프레임/초 이상으로 늘어났습니다. 인코딩 및 디코딩 시간 비율이 5:1이기 때문에 이 시스템의 인코딩은 100프레임/초에 도달했습니다. 실시간 통신 요구 사항.