12.11.2014 Views

PDF version - ARM Information Center

PDF version - ARM Information Center

PDF version - ARM Information Center

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

®<br />

RealView<br />

컴파일 도구<br />

버전 3.1<br />

NEON <br />

벡터화 컴파일러 설명서<br />

Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved.<br />

<strong>ARM</strong> DUI 0350AK


RealView 컴파일 도구<br />

NEON 벡터화 컴파일러 설명서<br />

Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved.<br />

릴리스 정보<br />

이 설명서에서 변경된 내용은 다음과 같습니다.<br />

변경 내역<br />

날짜 발행판 기밀 상태 변경된 내용<br />

2007년 3월 A 기밀 문서 아님 RVDS 버전 3.1용 릴리스 3.1<br />

소유권 고지 사항<br />

®<br />

또는 표시가 있는 단어와 로고는 <strong>ARM</strong> Limited 소유의 등록 상표 또는 상표입니다. 이 설명서에 언<br />

급된 기타 브랜드와 이름은 해당 소유자의 상표일 수 있습니다.<br />

이 설명서에 포함된 전체 또는 일부 정보나 설명된 제품은 해당 저작권 소유자의 사전 서면 승인 없<br />

이는 어떤 형태로도 개조되거나 복제될 수 없습니다.<br />

이 설명서에 설명된 제품은 지속적으로 개발 및 개선될 수 있습니다. 이 설명서에 포함된 모든 제품<br />

명세와 해당 사용법은 <strong>ARM</strong>의 신뢰하에 제공됩니다. 그러나 <strong>ARM</strong>에서는 상품성 또는 특정 목적에의<br />

적합성을 비롯하여 그 밖의 묵시적이거나 명시적인 모든 보증을 부인합니다.<br />

이 설명서는 제품 사용자를 지원하는 용도로만 만들어졌습니다. <strong>ARM</strong> Limited는 이 설명서 정보의 사<br />

용, 정보의 오류나 누락 또는 제품의 잘못된 사용에 따른 어떠한 손실이나 손상도 책임지지 않습니다.<br />

<strong>ARM</strong>이라는 단어가 사용되는 경우 "<strong>ARM</strong>이나 해당하는 자회사"를 의미합니다.<br />

기밀 상태<br />

이 설명서는 기밀 문서가 아닙니다. 이 설명서의 사용, 복사 및 공개에 대한 권한은 <strong>ARM</strong>과 <strong>ARM</strong>으로<br />

부터 이 설명서를 제공받은 당사자가 동의한 계약 조건에 따라 라이센스 제한의 적용을 받을 수 있습<br />

니다.<br />

제품 상태<br />

이 설명서의 정보는 개발이 완료된 제품에 대한 최종 정보입니다.<br />

웹 주소<br />

http://www.arm.com<br />

ii Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. <strong>ARM</strong> DUI 0350AK


목차<br />

RealView Compilation Tools<br />

NEON 벡터화 컴파일러 설명서<br />

서문<br />

설명서 정보 .................................................................................................... vi<br />

사용자 의견 .................................................................................................... ix<br />

1장<br />

2장<br />

소개<br />

1.1 NEON 벡터화 컴파일러 정보 ...................................................................... 1-2<br />

NEON 벡터화 기능<br />

2.1 명령 행 옵션 ................................................................................................ 2-2<br />

2.2 키워드 ......................................................................................................... 2-6<br />

2.3 Pragma ....................................................................................................... 2-7<br />

2.4 ETSI 기본 작업 .......................................................................................... 2-10<br />

<strong>ARM</strong> DUI 0350AK Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. iii


목차<br />

3장<br />

NEON 벡터화 컴파일러 사용<br />

3.1 NEON 장치 ................................................................................................. 3-2<br />

3.2 NEON용 코드 작성 ..................................................................................... 3-3<br />

3.3 자동 벡터화 사용 ........................................................................................ 3-5<br />

3.4 성능 향상 .................................................................................................... 3-8<br />

3.5 예제 .......................................................................................................... 3-18<br />

iv Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. <strong>ARM</strong> DUI 0350AK


서문<br />

이 서문에서는 RealView Compilation Tools NEON 벡터화 컴파일러를 소개합니다.<br />

여기에는 다음 단원이 포함되어 있습니다.<br />

• vi페이지의 설명서 정보<br />

• ix페이지의 사용자 의견<br />

<strong>ARM</strong> DUI 0350AK Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. v


서문<br />

설명서 정보<br />

이 설명서에서는 NEON 벡터화 컴파일러에 대한 정보를 제공하고 자동 벡터화<br />

기능을 활용하는 방법에 대해 설명합니다.<br />

대상 독자<br />

이 설명서는 NEON 장치가 있는 <strong>ARM</strong> 프로세서를 타겟으로 하는 NEON 벡터화<br />

컴파일러를 사용하여 응용 프로그램을 만들려는 모든 개발자를 위한 것입니다.<br />

여기에서는 독자가 경험 있는 소프트웨어 개발자라고 가정합니다. RVCT와 함께<br />

제공되는 <strong>ARM</strong> 개발 도구의 개요를 보려면 RealView Compilation Tools 핵심 설명<br />

서를 참조하십시오.<br />

설명서 사용<br />

이 설명서는 다음 장으로 구성되어 있습니다.<br />

1장 소개<br />

이 장에서는 NEON 벡터화 컴파일러에 대해 간략히 소개합니다.<br />

2장 NEON 벡터화 기능<br />

이 장에서는 NEON 벡터화 컴파일러에서 지원하는 명령 행 옵션에<br />

대해 설명합니다.<br />

3장 NEON 벡터화 컴파일러 사용<br />

이 장에서는 NEON 벡터화 컴파일러를 익힐 수 있는 자습 과정을 제<br />

공합니다. NEON 장치에 대한 정보를 제공하고 자동 벡터화 기능을<br />

활용하는 방법에 대해 설명합니다.<br />

이 설명서에서는 <strong>ARM</strong> 소프트웨어가 기본 위치에 설치되어 있다고 가정합니다.<br />

예를 들어 Windows의 경우 기본 위치는 volume:\Program Files\<strong>ARM</strong>일 수 있습니다.<br />

경로 이름을 참조할 때 install_directory는 이 위치를 가리키는 것으로 가정합니<br />

다. 예를 들어 경로는 install_directory\Documentation\...과 같을 수 있습니다.<br />

<strong>ARM</strong> 소프트웨어를 다른 위치에 설치한 경우에는 이 위치를 변경해야 합니다.<br />

vi Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. <strong>ARM</strong> DUI 0350AK


서문<br />

표기 규칙<br />

이 설명서에서는 다음과 같은 표기 규칙을 사용합니다.<br />

monospace .<br />

monospace .<br />

명령, 파일 및 프로그램 이름, 소스 코드와 같이 키보드로 입력할 수<br />

있는 텍스트를 나타냅니다.<br />

명령 또는 옵션 대신 사용할 수 있는 약어를 나타냅니다. 밑줄이 그<br />

어진 텍스트는 전체 명령이나 옵션 이름 대신 입력할 수 있습니다.<br />

monospace italic<br />

명령 및 함수의 인수를 나타냅니다. 인수는 특정 값으로 대체할 수<br />

있습니다.<br />

고정 폭 굵은 글꼴<br />

외부 예제 코드가 사용될 경우 언어 키워드를 나타냅니다.<br />

기울임 글꼴 . 중요한 사항을 강조 표시하고, 특수 용어를 소개하며, 내부 상호 참<br />

조 및 인용 부분을 나타냅니다.<br />

굵은 글꼴 . 메뉴 이름과 같은 인터페이스 요소를 강조 표시합니다. 적절한 경우<br />

설명 목록의 내용을 강조할 때와 <strong>ARM</strong> 프로세서 신호 이름을 표시<br />

할 때도 사용됩니다.<br />

추가 정보<br />

이 단원에는 <strong>ARM</strong> 계열 프로세서용 코드를 개발하는 데 대한 추가 정보를 제공하<br />

는 <strong>ARM</strong> Limited 및 타사 게시물 목록이 나와 있습니다.<br />

<strong>ARM</strong> Limited는 설명서의 내용을 정기적으로 업데이트하고 수정합니다.<br />

http://www.arm.com에서 정오표, 추가 목록 및 <strong>ARM</strong> FAQ를 참조하십시오.<br />

<strong>ARM</strong> 게시물<br />

이 설명서에는 RVCT 사용에 필요한 개발 도구와 관련된 추가 정보가 포함됩니<br />

다. 이 제품군에 포함된 다른 게시물은 다음과 같습니다.<br />

• RVCT 컴파일러 사용 설명서(<strong>ARM</strong> DUI 0205)<br />

• RVCT 컴파일러 참조 설명서(<strong>ARM</strong> DUI 0348)<br />

• RVCT 라이브러리 및 부동 소수점 지원 설명서(<strong>ARM</strong> DUI 0349)<br />

• RVCT 핵심 설명서(<strong>ARM</strong> DUI 0202)<br />

• RVCT 링커 및 유틸리티 설명서(<strong>ARM</strong> DUI 0206)<br />

<strong>ARM</strong> DUI 0350AK Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. vii


서문<br />

• RVCT 어셈블러 설명서(<strong>ARM</strong> DUI 0204)<br />

• RVCT 개발자 설명서(<strong>ARM</strong> DUI 0203)<br />

• RealView Development Suite 용어집(<strong>ARM</strong> DUI 0324)<br />

<strong>ARM</strong>에서 지원하는 기본 표준, 소프트웨어 인터페이스 및 기타 표준에 대한 자세<br />

한 내용은 install_directory\Documentation\Specifications\...에서 볼 수 있습니다.<br />

또한 <strong>ARM</strong> 제품과 관련된 구체적인 내용은 다음 설명서를 참조하십시오.<br />

• <strong>ARM</strong>7-M Architecture Reference Manual(<strong>ARM</strong> DDI 0403)<br />

• <strong>ARM</strong> Architecture Reference Manual, <strong>ARM</strong>v7-A and <strong>ARM</strong>v7-R edition (<strong>ARM</strong><br />

DDI 0406)<br />

• <strong>ARM</strong> Architecture Reference Manual Advanced SIMD Extensions and VFPv3<br />

Supplement(<strong>ARM</strong> DDI 0268)<br />

• 하드웨어 장치에 대한 <strong>ARM</strong> 데이터시트 또는 기술 참조 문서<br />

viii Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. <strong>ARM</strong> DUI 0350AK


서문<br />

사용자 의견<br />

RealView Compilation Tools 및 설명서에 대한 의견이 있으시면 <strong>ARM</strong> Limited에<br />

언제든 알려 주시기 바랍니다.<br />

RealView Compilation Tools에 대한 사용자 의견<br />

RVCT와 관련된 문제가 있으시면 해당 공급업체에 문의하십시오. 문의 시 다음<br />

사항을 함께 알려 주시면 보다 신속하고 유용한 답변을 받으실 수 있습니다.<br />

• 사용자 이름 및 회사<br />

• 제품 일련 번호<br />

• 사용 중인 릴리스 정보<br />

• 실행 중인 플랫폼의 세부 사항(예: 하드웨어 플랫폼, 운영 체제 유형 및 버전)<br />

• 문제를 재현하는 작은 독립 실행형 코드 샘플<br />

• 의도한 결과와 실제로 발생한 결과에 대한 명확한 설명<br />

• 사용한 명령(명령 행 옵션 포함)<br />

• 문제를 보여 주는 샘플 출력<br />

• 도구의 버전 문자열(버전 번호 및 빌드 번호 포함)<br />

설명서에 대한 사용자 의견<br />

이 설명서에 오류나 누락이 있으면 다음 사항을 기재하여 errata@arm.com으로 전<br />

자 메일을 보내 주시기 바랍니다.<br />

• 설명서 제목<br />

• 설명서 번호<br />

• 문의 내용에 해당하는 페이지 번호<br />

• 문제에 대한 간략한 설명<br />

추가 및 향상되었으면 하는 기능에 대한 일반적인 제안도 환영합니다.<br />

<strong>ARM</strong> DUI 0350AK Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. ix


서문<br />

x Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. <strong>ARM</strong> DUI 0350AK


1장<br />

소개<br />

NEON은 <strong>ARM</strong> Advanced SIMD(Single Instruction Multiple Data) Extension을 구현<br />

한 것입니다.<br />

이 장에서는 NEON 벡터화 컴파일러에 대해 설명하며 다음 단원이 포함되어 있<br />

습니다.<br />

• 1-2페이지의 NEON 벡터화 컴파일러 정보<br />

<strong>ARM</strong> DUI 0350AK Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. 1-1


소개<br />

1.1 NEON 벡터화 컴파일러 정보<br />

RVCT는 Cortex-A8과 같은 NEON 장치가 있는 <strong>ARM</strong> 프로세서를 타겟으로 하는<br />

<strong>ARM</strong> 컴파일러의 벡터화 버전인 armcc --vectorize를 제공합니다.<br />

벡터화는 컴파일러가 C 또는 C++ 코드에서 직접 NEON 벡터 명령을 생성하는 것<br />

을 의미합니다. 컴파일러는 dspfns.h 헤더 파일에서 + 및 일부 ITU intrinsic 함수와<br />

같은 C 및 C++의 일반적인 연산을 벡터화합니다.<br />

또한 RVCT는 컴파일러 벡터화의 대체 방법으로 컴파일러 벡터화 단계와 어셈블<br />

러 코드 작성 단계 사이에서 SIMD 코드를 생성하는 중간 단계로서 NEON<br />

intrinsic 함수를 제공합니다. 자세한 내용은 RVCT 컴파일러 참조 설명서에서 부<br />

록 E NEON 지원 사용을 참조하십시오.<br />

참고<br />

NEON 벡터화 컴파일러를 사용하려면 별도의 FLEXnet 라이센스가 설치되어 있<br />

어야 합니다. 이 라이센스는 RVDS 제품에 필요한 라이센스와는 별개입니다.<br />

RVDS 라이센스를 사용하여 NEON 벡터화 컴파일러를 사용하려고 하면 NEON<br />

컴파일러는 오류 메시지를 생성합니다.<br />

라이센싱에 대한 자세한 내용은 <strong>ARM</strong> FLEXnet 라이센스 관리 설명서(<strong>ARM</strong> DUI<br />

0209)를 참조하십시오.<br />

1-2 Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. <strong>ARM</strong> DUI 0350AK


2장<br />

NEON 벡터화 기능<br />

이 장에서는 NEON 벡터화 컴파일러 armcc --vectorize에서 지원하는 명령 행 옵<br />

션, 키워드 및 기능에 대해 설명합니다. 여기에는 다음 단원이 포함되어 있습니다.<br />

• 2-2페이지의 명령 행 옵션<br />

• 2-6페이지의 키워드<br />

• 2-7페이지의 Pragma<br />

• 2-10페이지의 ETSI 기본 작업<br />

<strong>ARM</strong> DUI 0350AK Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. 2-1


NEON 벡터화 기능<br />

2.1 명령 행 옵션<br />

이 단원에서는 <strong>ARM</strong> 컴파일러에서 지원하는 명령 행 옵션 외에도 NEON 벡터화<br />

컴파일러에서 지원하는 명령 행 옵션에 대해 설명합니다.<br />

2.1.1 --diag_suppress=optimizations<br />

이 옵션은 고수준 최적화에 대한 진단 메시지를 표시하지 않습니다.<br />

기본값<br />

기본적으로 최적화 메시지에는 설명 수준이 포함됩니다.<br />

--diag_suppress=optimizations를 지정하면 최적화 메시지를 표시하지 않습니다.<br />

참고<br />

--remarks 옵션을 사용하면 설명 수준이 있는 최적화 메시지를 볼 수 있습니다.<br />

사용법<br />

컴파일러에서는 최적화 수준 -O3에서 컴파일하는 경우 루프 언롤링과 같은 특정<br />

고수준 벡터 및 스칼라 최적화를 수행합니다. 이 옵션을 사용하면 이러한 고수준<br />

최적화에 대한 진단 메시지를 표시하지 않습니다.<br />

예제<br />

/*int*/ factorial(int n)<br />

{<br />

int result=1;<br />

while (n > 0)<br />

result *= n--;<br />

}<br />

return result;<br />

-O3 -Otime --remarks --diag_suppress=optimizations 옵션을 사용하여 이 코드를 컴<br />

파일하면 최적화 메시지를 표시하지 않습니다.<br />

2-2 Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. <strong>ARM</strong> DUI 0350AK


NEON 벡터화 기능<br />

추가 참고:<br />

• 2-3페이지의 --diag_warning=optimizations<br />

• 컴파일러 참조 설명서에서 2-31페이지의 --diag_suppress=tag[,tag,...]<br />

• 컴파일러 참조 설명서에서 2-33페이지의 --diag_warning=tag[,tag,...]<br />

• 컴파일러 참조 설명서에서 2-73페이지의 -Onum<br />

• 컴파일러 참조 설명서에서 2-75페이지의 -Otime<br />

2.1.2 --diag_warning=optimizations<br />

이 옵션은 고수준 최적화 진단 메시지를 경고 수준으로 설정합니다.<br />

기본값<br />

기본적으로 최적화 메시지에는 설명 수준이 포함됩니다.<br />

사용법<br />

컴파일러에서는 최적화 수준 -O3 -Otime에서 컴파일하는 경우 루프 언롤링과 같<br />

은 특정 고수준 벡터 및 스칼라 최적화를 수행합니다. 이 옵션을 사용하면 고수준<br />

최적화에 대한 진단 메시지를 표시합니다.<br />

예제<br />

int factorial(int n)<br />

{<br />

int result=1;<br />

while (n > 0)<br />

result *= n--;<br />

}<br />

return result;<br />

--vectorize --cpu=Cortex-A8 -O3 -Otime --diag_warning=optimizations 옵션을 사용<br />

하여 이 코드를 컴파일하면 최적화 경고 메시지가 생성됩니다.<br />

<strong>ARM</strong> DUI 0350AK Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. 2-3


NEON 벡터화 기능<br />

추가 참고:<br />

• 2-2페이지의 --diag_suppress=optimizations<br />

• 컴파일러 참조 설명서에서 2-73페이지의 -Onum<br />

• 컴파일러 참조 설명서에서 2-75페이지의 -Otime<br />

• 컴파일러 참조 설명서에서 2-31페이지의 --diag_suppress=tag[,tag,...]<br />

• 컴파일러 참조 설명서에서 2-33페이지의 --diag_warning=tag[,tag,...]<br />

2.1.3 --[no_]vectorize<br />

이 옵션을 사용하면 C 또는 C++ 코드에서 직접 NEON 벡터 명령 생성 여부를 설<br />

정할 수 있습니다.<br />

기본값<br />

기본값은 --no_vectorize입니다.<br />

제한<br />

다음 옵션은 벡터화할 루프에 지정되어야 합니다.<br />

--cpu=name<br />

-Otime<br />

-Onum<br />

참고<br />

타겟 프로세스에 NEON 기능이 포함되어야 합니다.<br />

실행 시간을 줄이기 위한 최적화 유형입니다.<br />

최적화 수준으로 다음 중 하나를 사용해야 합니다.<br />

• -O2 높은 최적화. 기본값입니다.<br />

• -O3 최대 최적화<br />

NEON은 <strong>ARM</strong> Advanced SIMD(Single Instruction, Multiple Data) Extension을 구현<br />

한 것입니다.<br />

벡터화를 사용하려면 별도의 FLEXnet 라이센스가 필요합니다.<br />

2-4 Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. <strong>ARM</strong> DUI 0350AK


NEON 벡터화 기능<br />

예제<br />

armcc --vectorize --cpu=Cortex-A8 -O3 -Otime -c file.c<br />

추가 참고:<br />

• 컴파일러 참조 설명서에서 2-17페이지의 --cpu=name<br />

• 컴파일러 참조 설명서에서 2-73페이지의 -Onum<br />

• 컴파일러 참조 설명서에서 2-75페이지의 -Otime<br />

<strong>ARM</strong> DUI 0350AK Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. 2-5


NEON 벡터화 기능<br />

2.2 키워드<br />

이 단원에서는 <strong>ARM</strong> 컴파일러에서 지원하는 C/C++ 키워드 외에도 NEON 벡터화<br />

컴파일러에서 지원하는 C/C++ 키워드에 대해 설명합니다.<br />

2.2.1 restrict<br />

restrict 키워드는 다양한 개체 포인터 유형과 함수 매개변수 배열이 메모리의 중<br />

복 영역을 가리키지 않도록 해 주는 C99 기능입니다. 따라서 컴파일러는 별칭 지<br />

정 가능성 때문에 다른 방식으로 방해받을 수도 있는 최적화 작업을 수행할 수 있<br />

습니다.<br />

C90 또는 C++에서 restrict 키워드를 사용하려면 --restrict 옵션을 지정해야 합<br />

니다.<br />

--restrict 옵션에 상관없이 키워드 __restrict 및 __restrict__ 는 restrict 의 동의<br />

어로 지원되면 항상 사용할 수 있습니다 .<br />

예제<br />

void func (int *restrict pa, int *restrict pb, int x)<br />

{<br />

int i;<br />

for (i=0; i


NEON 벡터화 기능<br />

2.3 Pragma<br />

이 단원에서는 <strong>ARM</strong> 컴파일러에서 지원하는 <strong>ARM</strong> 관련 pragma 외에도 NEON 벡<br />

터화 컴파일러에서 지원하는 <strong>ARM</strong> 관련 pragma에 대해 설명합니다.<br />

2.3.1 #pragma unroll [(n)]<br />

이 pragma는 n 이터레이션으로 루프를 언롤링하도록 컴파일러에 지시합니다.<br />

참고<br />

벡터화된 루프와 벡터화되지 않은 루프 모두 #pragma unroll [(n)]을 사용하여 언<br />

롤링할 수 있습니다. 즉 #pragma unroll [(n)]은 --vectorize 및 --no_vectorize 모두<br />

에 적용됩니다.<br />

구문<br />

#pragma unroll<br />

#pragma unroll (n)<br />

인수 설명:<br />

n<br />

언롤링할 이터레이션 수를 나타내는 선택적인 값입니다.<br />

기본값<br />

n에 값을 지정하지 않으면 컴파일러는 #pragma unroll (4)로 간주합니다.<br />

사용법<br />

-O3 -Otime에서 컴파일하는 경우 컴파일러는 이러한 수행에 적합한 위치에 있는<br />

루프를 자동으로 언롤링합니다. 이 pragma를 사용하면 자동으로 언롤링되지 않<br />

은 루프를 언롤링하도록 컴파일러에 요청할 수 있습니다.<br />

참고<br />

이 #pragma는 확실한 경우에만 사용해야 합니다. 예를 들어 컴파일러가 자체적으<br />

로 루프를 언롤링하지 않는 --diag_warning=optimizations에서 사용할 수 있습니다.<br />

<strong>ARM</strong> DUI 0350AK Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. 2-7


NEON 벡터화 기능<br />

제한<br />

#pragma unroll [(n)]은 for 루프, while 루프 또는 do ... while 루프 바로 앞에만 사<br />

용할 수 있습니다.<br />

예제<br />

void matrix_multiply(float ** __restrict dest, float ** __restrict src1,<br />

float ** __restrict src2, unsigned int n)<br />

{<br />

unsigned int i, j, k;<br />

}<br />

for (i = 0; i < n; i++)<br />

{<br />

for (k = 0; k < n; k++)<br />

{<br />

float sum = 0.0f;<br />

/* #pragma unroll */<br />

for(j = 0; j < n; j++)<br />

sum += src1[i][j] * src2[j][k];<br />

dest[i][k] = sum;<br />

}<br />

}<br />

이 예제에서 src2가 src2[j][k]로 인덱싱되어 있는 데 루프는 반대 순서(즉 k 내부<br />

에 j가 위치)로 중첩되어 있으므로 대개 컴파일러는 해당 루프를 완료하지 못합<br />

니다. #pragma unroll 주석을 이 예제에서 제거하면 컴파일러는 루프를 언롤링하<br />

기 위해 4번 수행합니다.<br />

크기가 4의 배수가 아닌 매트릭스를 증가시키려는 경우(예: n * n 매트릭스)<br />

#pragma unroll (m)을 대신 사용할 수 있습니다. 여기서 m은 n이 m의 정수의 배수가<br />

되도록 하는 어떤 값입니다.<br />

추가 참고:<br />

• 2-3페이지의 --diag_warning=optimizations<br />

• #pragma unroll_completely<br />

• 2-4페이지의 --[no_]vectorize<br />

• 컴파일러 참조 설명서에서 2-73페이지의 -Onum<br />

• 컴파일러 참조 설명서에서 2-75페이지의 -Otime<br />

• 컴파일러 사용 설명서에서 4-4페이지의 루프 최적화<br />

2-8 Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. <strong>ARM</strong> DUI 0350AK


NEON 벡터화 기능<br />

2.3.2 #pragma unroll_completely<br />

이 pragma는 루프를 완전히 언롤링하도록 컴파일러에 지시합니다. 이는 루프에<br />

있는 이터레이션 수를 컴파일러가 결정할 수 있는 경우에만 적용됩니다.<br />

참고<br />

벡터화된 루트와 벡터화되지 않은 루프 모두 #pragma unroll_completely를 사용하<br />

여 언롤링할 수 있습니다. 즉 #pragma unroll_completely는 --no_vectorize 및<br />

--vectorize 모두에 적용됩니다.<br />

사용법<br />

-O3 -Otime에서 컴파일하면 컴파일러는 이러한 수행에 적합한 위치에 있는 루프<br />

를 자동으로 언롤링합니다. 이 pragma를 사용하여 자동으로 완전히 언롤링되지<br />

않은 루프를 완전히 언롤링하도록 컴파일러에 요청할 수 있습니다.<br />

참고<br />

이 #pragma는 확실한 경우에만 사용해야 합니다. 예를 들어 컴파일러가 자체적으<br />

로 루프를 언롤링하지 않는 --diag_warning=optimizations에서 사용할 수 있습니다.<br />

제한<br />

#pragma unroll_completely는 for 루프, while 루프 또는 do ... while 루프 바로 앞에만<br />

사용할 수 있습니다.<br />

외부 루프에 #pragma unroll_completely를 사용하면 벡터화를 방지할 수 있습니다.<br />

즉 내부 루프에 #pragma unroll_completely를 사용하면 어떤 경우에는 도움이 될 수<br />

도 있습니다.<br />

추가 참고:<br />

• 2-3페이지의 --diag_warning=optimizations<br />

• 2-4페이지의 --[no_]vectorize<br />

• 2-7페이지의 #pragma unroll [(n)]<br />

• 컴파일러 참조 설명서에서 2-73페이지의 -Onum<br />

• 컴파일러 참조 설명서에서 2-75페이지의 -Otime<br />

• 컴파일러 사용 설명서에서 4-4페이지의 루프 최적화<br />

<strong>ARM</strong> DUI 0350AK Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. 2-9


NEON 벡터화 기능<br />

2.4 ETSI 기본 작업<br />

RVCT는 ETSI G.729 권장 사항인 CS-ACELP(Conjugate-Structure<br />

Algebraic-Code-Excited Linear Prediction)를 사용하여 8kbit/s로 음성 코딩에 설명<br />

되어 있는 원래 ETSI 계열의 기본 작업을 지원합니다. 전체 작업 목록에 대한 자<br />

세한 내용은 컴파일러 참조 설명서에서 4-103페이지의 ETSI 기본 연산을 참조하<br />

십시오.<br />

표 2-1에서는 벡터화할 수 있는 작업 목록을 보여 줍니다. ETSI 기본 작업을 사용<br />

자 코드에 사용하려면 dspfns.h 헤더 파일을 포함해야 합니다.<br />

표 2-1 RVCT 3.1에서 지원하는 ETSI 기본 연산<br />

Intrinsic<br />

abs_s L_sub L_mult mult_r shl<br />

extract_h L_deposit_h L_negate negate shr<br />

extract_l L_deposit_l L_shl norm_s shr_r<br />

L_abs L_mac L_shr norm_l sub<br />

L_add L_msu mult round<br />

2-10 Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. <strong>ARM</strong> DUI 0350AK


3장<br />

NEON 벡터화 컴파일러 사용<br />

이 장에서는 NEON 장치에 대한 정보를 제공하고 자동 벡터화 기능을 활용하는<br />

방법에 대해 설명합니다. 여기에는 다음 단원이 포함되어 있습니다.<br />

• 3-2페이지의 NEON 장치<br />

• 3-3페이지의 NEON용 코드 작성<br />

• 3-5페이지의 자동 벡터화 사용<br />

• 3-8페이지의 성능 향상<br />

• 3-18페이지의 예제<br />

<strong>ARM</strong> DUI 0350AK Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. 3-1


NEON 벡터화 컴파일러 사용<br />

3.1 NEON 장치<br />

NEON 장치는 16바이트 정보를 보유하는 벡터 레지스터를 총 32개 제공합니다.<br />

이러한 16바이트 레지스터는 NEON 장치에서 병렬로 작동할 수 있습니다. 예를<br />

들어 8개의 16비트 정수를 8개의 다른 16비트 정수에 추가하여 8개의 16비트를<br />

만들 수 있는 명령어를 한 벡터에 추가할 수 있습니다.<br />

NEON 장치는 32비트 부동 소수점 연산을 비롯하여 8비트, 16비트 및 32비트 정<br />

수 연산과 일부 64비트 연산을 지원합니다.<br />

참고<br />

벡터 부동 소수점 연산은 VFP 보조 프로세서가 RunFast 모드에서 작동하고 있는<br />

경우에만 수행됩니다. 부동 소수점 코드를 벡터화하려면 --fpmode fast를 사용하<br />

여 컴파일해야 합니다.<br />

NEON 장치는 하나의 명령을 사용하여 벡터 레지스터에서 여러 요소에 대해 작<br />

동하는 벡터 SIMD 장치로 분류됩니다.<br />

예를 들어 배열 A는 8개의 요소를 포함한 16비트 정수 배열입니다.<br />

1 2 3 4 5 6 7 8<br />

표 3-1 배열 A<br />

배열 B에는 이러한 8개의 요소가 있습니다.<br />

80 70 60 50 40 30 20 10<br />

표 3-2 배열 B<br />

두 배열을 더하려면 각 벡터를 벡터 레지스터로 가져오고 하나의 벡터 SIMD 명<br />

령어를 사용하여 결과를 가져옵니다.<br />

81 72 63 54 45 36 27 18<br />

표 3-3 결과<br />

3-2 Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. <strong>ARM</strong> DUI 0350AK


NEON 벡터화 컴파일러 사용<br />

3.2 NEON용 코드 작성<br />

이 단원에서는 NEON 장치에 대한 코드를 작성하는 방법에 대해 간략히 설명합<br />

니다. 다음과 같은 몇 가지 방법으로 NEON에서 실행하는 코드를 가져올 수 있습<br />

니다.<br />

• 어셈블리 언어로 작성하거나 C에서 임베디드 어셈블리 언어를 사용하고<br />

NEON 명령어를 직접 사용합니다.<br />

• NEON C 언어 확장을 사용하여 C 또는 C++로 작성합니다.<br />

• NEON 명령어를 사용하도록 최적화된 라이브러리 루틴을 호출합니다.<br />

• 자동 벡터화를 사용하여 NEON에 대해 벡터화된 루프를 가져옵니다.<br />

3.2.1 NEON C 확장<br />

NEON C 확장은 C에서 NEON 장치에 액세스할 수 있도록 <strong>ARM</strong>에 의해 정의된 새<br />

데이터 유형 및 intrinsic 함수의 세트입니다. 대부분의 벡터 함수는 NEON 장치에<br />

서 사용 가능한 벡터 명령어에 직접 매핑되며 NEON의 향상된 <strong>ARM</strong> C 컴파일러<br />

에서 인라인으로 컴파일됩니다. 이러한 확장을 사용하면 C 수준에서 성능을 향<br />

상시킬 수 있습니다. 이러한 성능 향상은 어셈블리 언어 코딩을 통해 얻을 수 있<br />

는 성능 향상과 유사합니다.<br />

자세한 내용은 RVCT 컴파일러 참조 설명서에서 부록 E NEON 지원 사용을 참조<br />

하십시오.<br />

3.2.2 자동 벡터화<br />

명시적 NEON 명령어로 작성하는 대신 벡터화할 수 있는 루프로 코딩하면 프로<br />

세서 사이에 코드 이식성을 유지할 수 있습니다. 손으로 직접 코딩한 벡터화의 성<br />

능 수준과 비슷한 성능 수준을 적은 노력으로 달성할 수 있습니다.<br />

예제 3-1에서는 자동 벡터화를 호출하는 데 필요한 명령 행 옵션을 보여 줍니다.<br />

예제 3-1 자동 벡터화<br />

armcc --vectorize --cpu=Cortex-A8 -O3 -Otime -c file.c<br />

<strong>ARM</strong> DUI 0350AK Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. 3-3


NEON 벡터화 컴파일러 사용<br />

벡터화를 사용하여 향상된 성능을 위해 최적화할 때 vectorize 옵션을 활성화하고<br />

비활성화하여 스칼라 코드와의 타이밍 비교를 수행할 수 있습니다. 자세한 내용<br />

은 2-4페이지의 --[no_]vectorize를 참조하십시오.<br />

참고<br />

-O2 -Otime을 사용하여 컴파일할 수도 있지만 최대 코드 성능을 제공하지는 않습<br />

니다.<br />

3.2.3 성능 목표<br />

대부분의 응용 프로그램은 벡터화를 통해 최상의 성능을 얻을 수 있도록 조정해<br />

야 합니다. 항상 약간의 오버헤드가 있으므로 이론적인 최대 성능에는 도달할 수<br />

없습니다. 예를 들어 NEON 장치는 한 번에 4개의 단일정밀도 부동 소수점을 처<br />

리할 수 있습니다. 이는 벡터화되지 않은 원래 스칼라 코드에서는 부동 소수점 응<br />

용 프로그램에 대한 이론적인 최대 성능 요소가 4임을 의미합니다. 일반적인 오<br />

버헤드를 고려할 때 전체 부동 소수점 응용 프로그램의 알맞은 목표는 스칼라 코<br />

드를 통해 성능의 50%를 향상시키는 것입니다. 완전히 벡터화되지 않은 대규모<br />

응용 프로그램의 경우 적합한 목표는 스칼라 코드를 통해 성능의 25%를 향상시<br />

키는 것입니다.<br />

자세한 내용은 3-8페이지의 성능 향상을 참조하십시오.<br />

3-4 Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. <strong>ARM</strong> DUI 0350AK


NEON 벡터화 컴파일러 사용<br />

3.3 자동 벡터화 사용<br />

이 단원에서는 자동 벡터화에 대해 간략히 설명하고 생성된 코드의 벡터화 프로<br />

세스 및 성능에 영향을 미치는 요소에 대해 설명합니다.<br />

3.3.1 자동 벡터화 개요<br />

자동 벡터화는 코드에 있는 루프의 고수준 분석과 관련이 있습니다. 이는 대부분<br />

의 일반 코드를 NEON 장치의 기능에 매핑할 때 가장 효과적인 방법입니다. 대부<br />

분의 코드에서는 더 작은 스케일의 알고리즘 종속적 병렬화를 통해 얻을 수 있는<br />

이득이 이러한 기회를 자동 분석하는 비용과 비교해볼 때 매우 적습니다. 이러한<br />

이유로 인해 NEON 장치는 단순한 루프 기반 병렬화의 타겟으로 디자인되었습니<br />

다.<br />

벡터화는 최적화된 코드가 벡터화되지 않은 코드와 동일한 결과를 제공하는 방<br />

식으로 수행됩니다. 경우에 따라 루프의 벡터화가 수행되지 않아 잘못된 결과가<br />

발생하지 않을 수 있습니다. 이는 하위 최적 코드가 될 수 있으므로 자동 벡터화<br />

에 보다 적합하도록 코드를 수동으로 조정해야 할 수도 있습니다. 자세한 내용은<br />

3-8페이지의 성능 향상을 참조하십시오.<br />

3.3.2 벡터화 개념<br />

이 단원에서는 코드의 벡터화를 고려할 때 일반적으로 사용되는 몇 가지 개념에<br />

대해 설명합니다.<br />

데이터 참조<br />

코드에 있는 데이터 참조는 다음 세 가지 유형 중 하나로 분류할 수 있습니다.<br />

스칼라<br />

인덱스<br />

벡터<br />

루프의 모든 이터레이션에서 변경되지 않는 단일 위치입니다.<br />

루프의 각 패스마다 일정 양만큼 증가하는 정수의 양입니다.<br />

연속적인 요소 간에 상수 스트라이드를 포함한 메모리 위치의 범위<br />

입니다.<br />

3-6페이지의 예제 3-2에서는 루프에 있는 변수의 분류를 보여 줍니다.<br />

i,j 인덱스 변수<br />

a,b 벡터<br />

x<br />

스칼라<br />

<strong>ARM</strong> DUI 0350AK Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. 3-5


NEON 벡터화 컴파일러 사용<br />

예제 3-2 벡터화할 수 있는 루프의 범주화<br />

float *a, *b;<br />

int i, j, n;<br />

...<br />

for (i = 0; i < n; i++)<br />

{<br />

*(a+j) = x +b[i];<br />

j += 2;<br />

};<br />

변수를 분류하면 루프 벡터화의 결과가 스칼라 버전의 결과와 동일하게 됩니다.<br />

추후 이터레이션을 계산하는 루프 내부의 데이터 종속성이 있으면 루프를 직접<br />

벡터화할 수 없습니다. 자세한 내용은 3-8페이지의 데이터 종속성을 참조하십시<br />

오.<br />

스트라이드 패턴 및 데이터 액세스<br />

루프의 데이터 액세스 스트라이드 패턴은 순차적인 루프 이터레이션 간의 데이<br />

터 요소에 대한 액세스 패턴입니다. 예를 들어 배열의 각 요소에 연속적으로 액세<br />

스하는 루프에 있는 스트라이드가 1입니다. 또 다른 예로, 사용된 각 요소 간에 상<br />

수 오프셋을 포함한 배열에 액세스하는 루프가 상수 스트라이드를 포함하는 것<br />

으로 간주됩니다.<br />

3.3.3 벡터화 성능에 영향을 미치는 요소<br />

생성된 코드의 자동 벡터화 프로세스 및 성능에 영향을 미치는 사항은 다음과 같<br />

습니다.<br />

루프가 구성된 방식<br />

성능을 극대화하려면 루프 중첩에 있는 맨 안쪽의 루프가 스트라이<br />

드가 1인 배열에 액세스해야 합니다.<br />

데이터가 구성된 방식<br />

예를 들어 데이터 배열을 포함하는 단일 구조체는 구조체 배열보다<br />

더 효율적일 수 있습니다. 또한 NEON 레지스터에 보유할 수 있는 데<br />

이터 요소의 수 및 병렬적으로 수행할 수 있는 연산 수를 데이터 유<br />

형에서 결정할 수 있습니다.<br />

3-6 Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. <strong>ARM</strong> DUI 0350AK


NEON 벡터화 컴파일러 사용<br />

루프의 이터레이션 수<br />

루프 오버헤드는 이터레이션이 많을수록 감소하기 때문에 일반적<br />

으로 이터레이션 수가 많은 것이 좋습니다. 두 개 또는 세 개의 요소<br />

같이 이터레이션 수가 매우 적은 경우에는 비벡터 명령어를 사용하<br />

여 처리하는 작업을 보다 신속하게 수행할 수 있습니다. 수만 개의<br />

배열 요소에 액세스하는 매우 긴 루프는 캐시 크기를 초과하고 데이<br />

터 재사용에 방해가 될 수 있습니다.<br />

배열의 데이터 유형<br />

예를 들어 배정밀도 부동 소수점 배열이 사용되는 경우 NEON에서<br />

성능을 향상시킬 수 없습니다.<br />

메모리 계층 사용<br />

대부분의 최신 프로세서의 경우 메모리 대역폭과 프로세서 용량 간<br />

의 균형이 비교적 맞지 않습니다. 예를 들어 주 메모리에서 검색된<br />

큰 데이터 세트에서 상대적으로 매우 적은 수의 산술 연산을 수행하<br />

는 작업은 시스템의 메모리 대역폭에 의해 제한을 받습니다.<br />

<strong>ARM</strong> DUI 0350AK Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. 3-7


NEON 벡터화 컴파일러 사용<br />

3.4 성능 향상<br />

대부분의 응용 프로그램에서는 최상의 NEON 결과를 얻기 위해 프로그래머가 어<br />

느 정도 조정 작업을 수행해야 합니다. 이 단원에서는 여러 가지 루프 유형에 대<br />

해 설명합니다. 그리고 벡터화가 일부 루프에서는 성공적으로 작동하지만 다른<br />

루프에서는 제대로 작동하지 않는 방식에 대해 설명합니다. 벡터화된 코드를 통<br />

해 최상의 성능을 얻을 수 있도록 코드를 수정하는 방법에 대해서도 설명합니다.<br />

3.4.1 일반적인 성능 문제<br />

명령 행 옵션 -O3 및 -Otime을 사용하면 코드를 통해 벡터화의 성능 향상을 비롯하<br />

여 상당한 성능 향상 효과를 얻을 수 있습니다.<br />

성능을 위해 최적화하는 경우 고수준 알고리즘 구조, 데이터 요소 크기, 배열 구<br />

성, 엄격한 반복 루프, 축소 연산 및 데이터 종속성 문제를 고려해야 합니다. 성능<br />

을 위해 최적화하려면 프로그램을 이해하는 데 대부분의 시간을 할애해야 합니<br />

다. 성능을 극대화하기 위해 실제 상황에서 코드의 프로파일링 및 벤치마킹을 사<br />

용해야 할 수도 있습니다.<br />

자동 벡터화 기능은 코드에 대한 이전의 수동 최적화, 예를 들어 소스 코드 또는<br />

복잡한 배열 액세스에서의 수동 루프 언롤링으로 인해 저하될 수도 있습니다. 최<br />

상의 결과를 얻기 위한 가장 좋은 방법은 컴파일러가 최적화를 모두 수행할 수 있<br />

도록 단순 루프를 사용하여 코드를 작성하는 것입니다. 수동으로 최적화된 레거<br />

시 코드의 경우에는 단순 루프를 사용하여 원래 알고리즘을 기반으로 중요한 부<br />

분을 다시 작성하는 것이 더 간단할 수 있습니다. 수동 최적화를 제거하면 자동<br />

벡터화 기능이 저하될 수도 있습니다.<br />

자세한 내용은 다음 항목을 참조하십시오.<br />

• 2-4페이지의 --[no_]vectorize<br />

• RVCT 컴파일러 참조 설명서에서 2-73페이지의 -Onum<br />

• RVCT 컴파일러 참조 설명서에서 2-75페이지의 -Otime<br />

3.4.2 데이터 종속성<br />

하나의 이터레이션에서 얻은 결과가 동일한 루프의 추후 이터레이션으로 피드백<br />

되는 루프에 데이터 종속성 충돌이 있다고 합니다. 충돌하는 값은 누산 합계와 같<br />

은 배열 요소 또는 스칼라일 수 있습니다.<br />

데이터 종속성 충돌을 포함하는 루프는 완전히 최적화되지 않을 수도 있습니다.<br />

배열 및/또는 포인터와 관련된 데이터 종속성을 검색하려면 각 루프 중첩에 사용<br />

된 배열을 광범위하게 분석하고, 루프에 사용되고 저장된 각 배열 차원을 따라 요<br />

3-8 Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. <strong>ARM</strong> DUI 0350AK


NEON 벡터화 컴파일러 사용<br />

소에 대한 액세스의 오프셋 및 스트라이드를 검사해야 합니다. 루프의 다른 이터<br />

레이션에서 중복되는 배열을 사용하고 저장해야 할 경우에는 데이터 종속성 문<br />

제가 발생할 수 있습니다. 연산의 벡터 순서가 결과를 변경할 수 있는 경우에는<br />

루프를 안전하게 벡터화할 수 없습니다. 이 경우 컴파일러는 문제를 감지하고 원<br />

래 형식의 루프를 그대로 두거나 루프의 벡터화를 부분적으로 수행합니다. 성능<br />

을 극대화하려면 코드에서 이러한 유형의 데이터 종속성이 존재하지 않도록 해<br />

야 합니다.<br />

예제 3-3의 루프에서는 루프의 맨 위에 있는 a[i-2]에 대한 참조가 맨 아래에 있는<br />

a[i]로의 저장과 충돌합니다. 이 루프에서 벡터화를 수행하면 다른 결과가 발생<br />

하며 루프가 원래 형식으로 남아 있게 됩니다.<br />

예제 3-3 벡터화할 수 없는 데이터 종속성<br />

float a[99], b[99], t;<br />

int i;<br />

for (i = 3; i < 99; i++)<br />

{<br />

t = a[i-1] + a[i-2];<br />

b[i] = t + 3.0 + a[i];<br />

a[i] = sqrt(b[i]) - 5.0;<br />

};<br />

다른 배열 첨자에서 가져온 정보는 종속성을 분석하는 데 사용됩니다. 예제 3-4의<br />

경우 배열 a에 대한 참조의 비벡터 첨자는 같을 수 없으며 n이 n+1과 같지 않으므<br />

로 루프가 벡터화되어 이터레이션 간에 피드백이 수행되지 않습니다. 배열 a에 대<br />

한 참조는 배열에 있는 두 개의 서로 다른 부분을 사용하므로 데이터를 공유하지<br />

않습니다.<br />

예제 3-4 벡터화할 수 있는 데이터 종속성<br />

float a[99][99], b[99][99], c[99];<br />

int i, n, m;<br />

...<br />

for (i = 1; i < m; i++) a[n][i] = a[n+1][i-1] * b[i] + c[i];<br />

<strong>ARM</strong> DUI 0350AK Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. 3-9


NEON 벡터화 컴파일러 사용<br />

3.4.3 스칼라 변수<br />

NEON 루프에서 사용되지만 설정되지 않은 스칼라 변수는 벡터 레지스터에 있는<br />

각 위치에 복제되며 결과는 벡터 계산에 사용됩니다.<br />

루프에 설정되고 사용되는 스칼라는 벡터로 승격됩니다. 일반적으로 이러한 변<br />

수에는 임시 벡터 값을 보유해야 하는 루프의 임시 스칼라 값이 포함되어 있습니<br />

다. 3-10페이지의 예제 3-5에서 x는 사용된 스칼라이고 y는 승격된 스칼라입니다.<br />

예제 3-5 벡터화할 수 있는 루프<br />

float a[99], b[99], x, y;<br />

int i, n;<br />

...<br />

for (i = 0; i < n; i++)<br />

{<br />

y = x + b[i];<br />

a[i] = y + 1/y;<br />

};<br />

루프에서 사용되고 설정된 스칼라를 캐리 순환 스칼라라고 합니다. 이러한 변수<br />

는 루프의 한 패스에서 계산된 값이 다음 패스로 전달되기 때문에 벡터화를 방해<br />

할 수 있습니다. 예제 3-6에서 x는 캐리 순환 스칼라입니다.<br />

예제 3-6 벡터화할 수 없는 루프<br />

float a[99], b[99], x;<br />

int i, n;<br />

...<br />

for (i = 0; i < n; i++)<br />

{<br />

a[i] = x + b[i];<br />

x = a[i] + 1/x;<br />

};<br />

3-10 Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. <strong>ARM</strong> DUI 0350AK


NEON 벡터화 컴파일러 사용<br />

축소 연산<br />

루프에서 사용되는 스칼라의 특별한 범주가 축소 연산입니다. 이 범주는 값 벡터<br />

를 축소하여 스칼라 결과를 도출하는 작업과 관련이 있습니다. 가장 일반적인 축<br />

소는 벡터의 모든 요소를 합하는 것입니다. 그 외 축소에는 두 벡터의 내적, 벡터<br />

의 최대값, 벡터의 최소값, 모든 벡터 요소의 곱, 벡터의 최대 또는 최소 요소 위치<br />

가 포함됩니다.<br />

3-11페이지의 예제 3-7에서는 내적 축소를 보여 줍니다. 여기서 x는 축소 스칼라<br />

입니다.<br />

예제 3-7 내적 축소<br />

float a[99], b[99], x;<br />

int i, n;<br />

...<br />

for (i = 0; i < n; i++) x += a[i] * b[i];<br />

축소 연산은 자주 수행되므로 벡터화하는 것이 좋습니다. 일반적으로 축소 연산<br />

은 이후에 최종 결과 스칼라로 축소되는 부분 축소 벡터를 만들어 벡터화됩니다.<br />

3.4.4 포인터 사용<br />

벡터화하려면 일반적으로 포인터보다 배열을 사용하는 것이 좋습니다. 컴파일러<br />

는 루프가 안전한지 확인할 수 있는 경우 포인터가 포함된 루프를 벡터화할 수 있<br />

습니다. 메모리에 대한 벡터 액세스가 있는지 확인하기 위해 루프의 배열 참조와<br />

포인터 참조를 모두 분석합니다. 경우에 따라 컴파일러는 런타임 테스트를 만들<br />

고 테스트 결과에 따라 벡터 버전 또는 스칼라 버전의 루프를 실행합니다.<br />

함수 인수는 대개 포인터로 전달됩니다. 여러 포인터 변수가 함수에 전달되면 메<br />

모리의 중복되는 섹션을 가리킬 수 있습니다. 런타임에 예외적인 경우도 있지만<br />

일반적으로 컴파일러는 항상 안전한 방법을 따르고 할당 연산자의 왼쪽과 오른<br />

쪽 모두에 나타나는 포인터와 관련된 루프의 최적화는 수행하지 않습니다. 예를<br />

들어 예제 3-8에서의 함수를 살펴 보십시오.<br />

<strong>ARM</strong> DUI 0350AK Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. 3-11


NEON 벡터화 컴파일러 사용<br />

예제 3-8 벡터화할 수 없는 포인터<br />

void func (int *pa, int *pb, int x)<br />

{<br />

for (i = 0; i < 100; i++) *(pa + i) = *(pb + i) + x;<br />

};<br />

이 예제에서 pa 및 pb가 한 루프 패스의 결과가 다음 루프 패스로 피드백되도록 하<br />

는 방식으로 메모리에 중복되는 경우 루프를 벡터화하면 잘못된 결과가 나타날<br />

수 있습니다. 함수가 다음 인수를 사용하여 호출되면 벡터화가 모호해질 수 있습<br />

니다.<br />

int *a;<br />

func (a, a-1);<br />

컴파일러는 포인터 별칭이 발생하는지 확인하기 위해 런타임 테스트를 수행합니<br />

다. 포인터 별칭이 발생하지 않으면 코드의 벡터화 버전이 실행됩니다. 포인터 별<br />

칭이 발생하면 원래의 벡터화되지 않은 코드가 대신 실행됩니다. 이렇게 하면 런<br />

타임 효율성 및 코드 크기에 있어서 비용을 줄일 수 있습니다.<br />

실제로는 함수 인수 때문에 데이터 종속성이 거의 존재하지 않습니다. 중복되는<br />

포인터를 전달하는 프로그램을 벡터화 관련 문제와 별도로 이해하고 디버깅하는<br />

것은 매우 어렵습니다.<br />

자세한 내용은 2-6페이지의 restrict를 참조하십시오.<br />

간접 주소 지정<br />

간접 주소 지정은 값 벡터에서 배열에 액세스한 경우 발생합니다. 배열을 메모리<br />

에서 가져오는 경우 이 작업을 수집이라고 합니다. 배열이 메모리에 저장되는 경<br />

우 이 작업을 스캐터라고 합니다. 예제 3-9에서 a는 스캐터되고 b는 수집됩니다.<br />

예제 3-9 벡터화할 수 없는 간접 주소 지정<br />

float a[99], b[99];<br />

int ia[99], ib[99], i, n, j;<br />

...<br />

for (i = 0; i < n; i++) a[ia[i]] = b[j + ib[i]];<br />

3-12 Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. <strong>ARM</strong> DUI 0350AK


NEON 벡터화 컴파일러 사용<br />

간접 주소 지정은 메모리에 연속적으로 저장된 벡터만 다룰 수 있으므로 NEON<br />

장치를 통해 벡터화할 수 없습니다. 루프에 간접 주소 지정 및 중요한 계산이 있<br />

는 경우 간접 주소 지정을 벡터가 아닌 별도의 루프로 이동하는 것이 보다 효율적<br />

일 수 있습니다. 이렇게 하면 계산을 효과적으로 벡터화할 수 있습니다.<br />

3.4.5 루프 구조<br />

루프의 전체 구조는 벡터화를 통해 최상의 성능을 얻는 데 중요합니다. 일반적으<br />

로 루프의 시작 부분에 고정되어 있고 복잡한 조건문이나 조건부 종료를 포함하<br />

지 않는 이터레이션 수를 사용하여 단순한 루프를 작성하는 것이 가장 좋습니다.<br />

코드의 벡터화 성능을 향상시키기 위해 루프를 다시 작성해야 할 수도 있습니다.<br />

루프에서 종료<br />

또한 예제 3-10은 루프에서 종료를 포함하므로 벡터화할 수 없습니다. 이 경우 벡<br />

터화에 성공하려면 가능한 경우 루프를 다시 작성해야 합니다.<br />

예제 3-10 벡터화할 수 없는 루프<br />

int a[99], b[99], c[99], i, n;<br />

...<br />

for (i = 0; i < n; i++)<br />

{<br />

a[i] = b[i] + c[i];<br />

if (a[i] > 5) break;<br />

};<br />

루프 이터레이션 수<br />

루프의 시작 부분에는 고정된 이터레이션 수가 있어야 합니다. 예제 3-11에서는<br />

이터레이션 수가 n이며 이 수가 루프를 진행하는 동안 변경되지 않음을 보여 줍<br />

니다.<br />

예제 3-11 벡터화할 수 있는 루프<br />

int a[99], b[99], c[99],i, n;<br />

...<br />

for (i = 0; i < n; i++) a[i] = b[i] + c[i];<br />

<strong>ARM</strong> DUI 0350AK Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. 3-13


NEON 벡터화 컴파일러 사용<br />

예제 3-12는 고정된 이터레이션 수를 포함하지 않으며 자동으로 벡터화할 수 없<br />

습니다.<br />

예제 3-12 벡터화할 수 없는 루프<br />

int a[99], b[99], c[99], i, n;<br />

...<br />

while (i < n)<br />

{<br />

a[i] = b[i] + c[i];<br />

i += a[i];<br />

};<br />

NEON 장치는 2, 4, 8 또는 16 그룹의 요소에서 작동할 수 있습니다. 루프의 시작<br />

부분에 있는 이터레이션 수가 알려진 경우 컴파일러는 런타임 테스트를 추가하<br />

여 이터레이션 수가 NEON 레지스터의 적합한 데이터 유형에 사용될 수 있는 레<br />

인의 배수가 아닌지 확인합니다. 이렇게 하면 추가로 벡터화되지 않은 코드가 생<br />

성되어 모든 추가 루프 이터레이션을 샐행하기 때문에 코드 크기가 늘어납니다.<br />

이터레이션 수가 NEON에서 지원하는 이터레이션 수 중 하나임을 알고 있는 경<br />

우에는 이를 컴파일러에 알릴 수 있습니다. 가장 효과적인 방법은 호출자에서 이<br />

터레이션 수를 4로 나눠 벡터화하려는 함수에서 4를 곱하는 것입니다. 모든 호출<br />

함수를 수정할 수는 없는 경우 루프 제한 테스트에 적절한 식을 사용하여 루프 이<br />

터레이션이 적합한 배수임을 나타낼 수 있습니다. 예를 들어 루프 이터레이션이<br />

4의 배수임을 나타내려면 다음을 사용합니다.<br />

for(i = 0; i < (n >> 2


NEON 벡터화 컴파일러 사용<br />

3.4.6 함수 호출 및 인라인<br />

루프 내에서 다른 함수를 호출하는 경우 호출된 함수의 내용을 처리할 수 없으므<br />

로 컴파일러에서 이러한 호출이 허용되지 않습니다. 컴파일러가 벡터화의 일부<br />

결과를 NEON 레지스터의 다른 함수에 전달할 수 없으므로 벡터화가 금지됩니다.<br />

일반적으로는 이해하기 쉽도록 복잡한 연산을 여러 함수로 나눕니다. 이러한 함<br />

수에 대해 벡터화를 고려하려면 해당 함수를 __inline 또는 __forceinline 키워드<br />

를 사용하여 표시해야 합니다. 그러면 이러한 함수가 벡터화를 위해 인라인으로<br />

확장됩니다. 자세한 내용은 RVCT 컴파일러 참조 설명서에서 4-9페이지의<br />

__inline 및 4-6페이지의 __forceinline을 참조하십시오.<br />

참고<br />

또한 이러한 키워드에 내부 정적 링키지가 포함됩니다.<br />

3.4.7 조건문<br />

효과적인 벡터화를 위해 루프에는 대개 할당문이 포함되어야 하고 if 및 switch<br />

문은 되도록이면 제한적으로 사용해야 합니다.<br />

루프의 이터레이션 간에 변경되지 않는 단순한 조건을 불변 루프라고 합니다. 이<br />

는 컴파일러에 의해 루프 앞으로 이동할 수 있으므로 각 루프 이터레이션에서 실<br />

행할 필요가 없습니다. 더 복잡한 조건부 연산은 벡터 모드에 있는 모든 경로를<br />

계산하고 결과를 병합하여 벡터화됩니다. 조건부로 수행해야 할 중요한 계산이<br />

있는 경우에는 상당히 많은 시간이 소요됩니다.<br />

예제 3-13에서는 사용할 수 있는 조건문을 보여 줍니다.<br />

예제 3-13 벡터화할 수 있는 조건<br />

float a[99], b[99], c[i];<br />

int i, n;<br />

...<br />

for (i = 0; i < n; i++)<br />

{<br />

if (c[i] > 0) a[i] = b[i] - 5.0;<br />

else a[i] = b[i] * 2.0;<br />

};<br />

<strong>ARM</strong> DUI 0350AK Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. 3-15


NEON 벡터화 컴파일러 사용<br />

3.4.8 소스 코드 조정을 통한 성능 향상의 예제<br />

컴파일러는 벡터화 최적화가 성공적으로 적용된 경우와 벡터화 적용에 실패한<br />

경우를 나타내는 진단 정보를 제공할 수 있습니다. 자세한 내용은 2-2페이지의<br />

--diag_suppress=optimizations 및 2-3페이지의 --diag_warning=optimizations를 참<br />

조하십시오.<br />

예제 3-14에서는 배열에 단순한 합계 연산을 구현하는 두 개의 함수를 보여 줍니<br />

다. 이 코드는 벡터화되지 않습니다.<br />

예제 3-14 벡터화할 수 없는 코드<br />

int addition(int a, int b)<br />

{<br />

return a + b;<br />

}<br />

void add_int(int *pa, int *pb, unsigned int n, int x)<br />

{<br />

unsigned int i;<br />

for(i = 0; i < n; i++) *(pa + i) = addition(*(pb + i),x);<br />

}<br />

--diag_warnings=optimization 옵션을 사용하면 addition() 함수에 대한 최적화 경<br />

고 메시지가 생성됩니다.<br />

__inline 한정자를 addition() 정의에 추가하면 이 코드가 벡터화되지만 아직 최적<br />

의 상태는 아닙니다. --diag_warnings=optimization 옵션을 다시 사용하면 루프가<br />

벡터화되지만 포인터 별칭 문제가 발생할 수 있다는 최적화 경고 메시지가 생성<br />

됩니다.<br />

컴파일러는 별칭에 대한 런타임 테스트를 생성해야 하며 코드의 벡터화된 복사<br />

본 및 스칼라 복사본을 모두 출력해야 합니다. 예제 3-15에서는 포인터의 별칭이<br />

지정되지 않은 경우 restrict 키워드를 사용하여 성능을 향상시킬 수 있는 방법을<br />

보여 줍니다.<br />

3-16 Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. <strong>ARM</strong> DUI 0350AK


NEON 벡터화 컴파일러 사용<br />

예제 3-15 restrict를 사용하여 벡터화 성능 향상<br />

__inline int addition(int a, int b)<br />

{<br />

return a + b;<br />

}<br />

void add_int(int * __restrict pa, int * __restrict pb, unsigned int n, int x)<br />

{<br />

unsigned int i;<br />

for(i = 0; i < n; i++) *(pa + i) = addition(*(pb + i),x);<br />

}<br />

마지막으로 시도해 볼 수 있는 성능 향상 노력은 루프 이터레이션의 수와 관련이<br />

있습니다. 예제 3-15에서 이터레이션 수는 고정되어 있지 않으며 NEON 레지스<br />

터에 정확하게 맞는 배수가 아닐 수 있습니다. 이는 컴파일러에서 벡터화되지 않<br />

은 코드를 사용하여 실행할 남아 있는 이터레이션을 테스트해야 함을 의미합니<br />

다. 이터레이션 수가 NEON에서 지원하는 이터레이션 수 중 하나임을 알고 있는<br />

경우 이를 컴파일러에 알릴 수 있습니다. 예제 3-16에서는 벡터화를 통해 최상의<br />

성능을 얻기 위해 마지막으로 기울일 수 있는 노력을 보여 줍니다.<br />

예제 3-16 최상의 벡터화 성능을 위해 조정된 코드<br />

__inline int addition(int a, int b)<br />

{<br />

return a + b;<br />

}<br />

void add_int(int * __restrict pa, int * __restrict pb, unsigned int n, int x)<br />

{<br />

unsigned int i;<br />

for(i = 0; i < (n & ~3); i++) *(pa + i) = addition(*(pb + i),x);<br />

/* n is a multiple of 4 */<br />

}<br />

<strong>ARM</strong> DUI 0350AK Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. 3-17


NEON 벡터화 컴파일러 사용<br />

3.5 예제<br />

다음은 벡터화 코드의 예제입니다. 예제 3-17 및 3-20페이지의 예제 3-18을 참조<br />

하십시오.<br />

예제 3-17 벡터화 코드<br />

/*<br />

* Vectorizable example code.<br />

* Copyright 2006 <strong>ARM</strong> Limited. All rights reserved.<br />

*<br />

* Includes embedded assembly to initialize cpu; link using '--entry=init_cpu'.<br />

*<br />

* Build using:<br />

* armcc --vectorize -c vector_example.c --cpu Cortex-A8 -Otime<br />

* armlink -o vector_example.axf vector_example.o --entry=init_cpu<br />

*/<br />

#include <br />

void fir(short *__restrict y, const short *x, const short *h, int n_out, int n_coefs)<br />

{<br />

int n;<br />

for (n = 0; n < n_out; n++)<br />

{<br />

int k, sum = 0;<br />

for (k = 0; k < n_coefs; k++)<br />

{<br />

sum += h[k] * x[n - n_coefs + 1 + k];<br />

}<br />

y[n] = ((sum>>15) + 1) >> 1;<br />

}<br />

}<br />

int main()<br />

{<br />

static const short x[128] =<br />

{<br />

0x0000, 0x0647, 0x0c8b, 0x12c8, 0x18f8, 0x1f19, 0x2528, 0x2b1f,<br />

0x30fb, 0x36ba, 0x3c56, 0x41ce, 0x471c, 0x4c3f, 0x5133, 0x55f5,<br />

0x5a82, 0x5ed7, 0x62f2, 0x66cf, 0x6a6d, 0x6dca, 0x70e2, 0x73b5,<br />

0x7641, 0x7884, 0x7a7d, 0x7c29, 0x7d8a, 0x7e9d, 0x7f62, 0x7fd8,<br />

0x8000, 0x7fd8, 0x7f62, 0x7e9d, 0x7d8a, 0x7c29, 0x7a7d, 0x7884,<br />

0x7641, 0x73b5, 0x70e2, 0x6dca, 0x6a6d, 0x66cf, 0x62f2, 0x5ed7,<br />

0x5a82, 0x55f5, 0x5133, 0x4c3f, 0x471c, 0x41ce, 0x3c56, 0x36ba,<br />

0x30fb, 0x2b1f, 0x2528, 0x1f19, 0x18f8, 0x12c8, 0x0c8b, 0x0647,<br />

0x0000, 0xf9b9, 0xf375, 0xed38, 0xe708, 0xe0e7, 0xdad8, 0xd4e1,<br />

3-18 Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. <strong>ARM</strong> DUI 0350AK


NEON 벡터화 컴파일러 사용<br />

};<br />

0xcf05, 0xc946, 0xc3aa, 0xbe32, 0xb8e4, 0xb3c1, 0xaecd, 0xaa0b,<br />

0xa57e, 0xa129, 0x9d0e, 0x9931, 0x9593, 0x9236, 0x8f1e, 0x8c4b,<br />

0x89bf, 0x877c, 0x8583, 0x83d7, 0x8276, 0x8163, 0x809e, 0x8028,<br />

0x8000, 0x8028, 0x809e, 0x8163, 0x8276, 0x83d7, 0x8583, 0x877c,<br />

0x89bf, 0x8c4b, 0x8f1e, 0x9236, 0x9593, 0x9931, 0x9d0e, 0xa129,<br />

0xa57e, 0xaa0b, 0xaecd, 0xb3c1, 0xb8e4, 0xbe32, 0xc3aa, 0xc946,<br />

0xcf05, 0xd4e1, 0xdad8, 0xe0e7, 0xe708, 0xed38, 0xf375, 0xf9b9,<br />

static const short coeffs[8] =<br />

{<br />

0x0800, 0x1000, 0x2000, 0x4000,<br />

0x4000, 0x2000, 0x1000, 0x0800<br />

};<br />

int i, ok = 1;<br />

short y[128];<br />

static const short expected[128] =<br />

{<br />

0x1474, 0x1a37, 0x1fe9, 0x2588, 0x2b10, 0x307d, 0x35cc, 0x3afa,<br />

0x4003, 0x44e5, 0x499d, 0x4e27, 0x5281, 0x56a9, 0x5a9a, 0x5e54,<br />

0x61d4, 0x6517, 0x681c, 0x6ae1, 0x6d63, 0x6fa3, 0x719d, 0x7352,<br />

0x74bf, 0x6de5, 0x66c1, 0x5755, 0x379e, 0x379e, 0x5755, 0x66c1,<br />

0x6de5, 0x74bf, 0x7352, 0x719d, 0x6fa3, 0x6d63, 0x6ae1, 0x681c,<br />

0x6517, 0x61d4, 0x5e54, 0x5a9a, 0x56a9, 0x5281, 0x4e27, 0x499d,<br />

0x44e5, 0x4003, 0x3afa, 0x35cc, 0x307d, 0x2b10, 0x2588, 0x1fe9,<br />

0x1a37, 0x1474, 0x0ea5, 0x08cd, 0x02f0, 0xfd10, 0xf733, 0xf15b,<br />

0xeb8c, 0xe5c9, 0xe017, 0xda78, 0xd4f0, 0xcf83, 0xca34, 0xc506,<br />

0xbffd, 0xbb1b, 0xb663, 0xb1d9, 0xad7f, 0xa957, 0xa566, 0xa1ac,<br />

0x9e2c, 0x9ae9, 0x97e4, 0x951f, 0x929d, 0x905d, 0x8e63, 0x8cae,<br />

0x8b41, 0x8a1b, 0x893f, 0x88ab, 0x8862, 0x8862, 0x88ab, 0x893f,<br />

0x8a1b, 0x8b41, 0x8cae, 0x8e63, 0x905d, 0x929d, 0x951f, 0x97e4,<br />

0x9ae9, 0x9e2c, 0xa1ac, 0xa566, 0xa957, 0xad7f, 0xb1d9, 0xb663,<br />

0xbb1b, 0xbffd, 0xc506, 0xca34, 0xcf83, 0xd4f0, 0xda78, 0xe017,<br />

0xe5c9, 0xebcc, 0xf229, 0xf96a, 0x02e9, 0x0dd8, 0x1937, 0x24ce,<br />

};<br />

fir(y, x + 7, coeffs, 128, 8);<br />

for (i = 0; i < sizeof(y)/sizeof(*y); ++i)<br />

{<br />

if (y[i] != expected[i])<br />

{<br />

printf("mismatch: y[%d] = 0x%04x; expected[%d] = 0x%04x\n", i, y[i], i, expected[i]);<br />

ok = 0;<br />

break;<br />

}<br />

}<br />

if (ok) printf("** TEST PASSED OK **\n");<br />

<strong>ARM</strong> DUI 0350AK Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. 3-19


NEON 벡터화 컴파일러 사용<br />

}<br />

return ok ? 0 : 1;<br />

#ifdef __TARGET_ARCH_7_A<br />

__asm void init_cpu() {<br />

// Set up CPU state<br />

MRC p15,0,r4,c1,c0,0<br />

ORR r4,r4,#0x00400000 // enable unaligned mode (U=1)<br />

BIC r4,r4,#0x00000002 // disable alignment faults (A=0)<br />

// MMU not enabled: no page tables<br />

MCR p15,0,r4,c1,c0,0<br />

#ifdef __BIG_ENDIAN<br />

SETEND BE<br />

#endif<br />

MRC p15,0,r4,c1,c0,2 // Enable VFP access in the CAR -<br />

ORR r4,r4,#0x00f00000 // must be done before any VFP instructions<br />

MCR p15,0,r4,c1,c0,2<br />

MOV r4,#0x40000000 // Set EN bit in FPEXC<br />

MSR FPEXC,r4<br />

IMPORT __main<br />

B __main<br />

}<br />

#endif<br />

예제 3-18 DSP 벡터화 코드<br />

/*<br />

* DSP Vectorizable example code.<br />

* Copyright 2006 <strong>ARM</strong> Limited. All rights reserved.<br />

*<br />

* Includes embedded assembly to initialize cpu; link using '--entry=init_cpu'.<br />

*<br />

* Build using:<br />

* armcc -c dsp_vector_example.c --cpu Cortex-A8 -Otime --vectorize<br />

* armlink -o dsp_vector_example.axf dsp_vector_example.o --entry=init_cpu<br />

*/<br />

#include <br />

#include "dspfns.h"<br />

void fn(short *__restrict r, int n, const short *__restrict a, const short *__restrict b)<br />

{<br />

int i;<br />

for (i = 0; i < n; ++i)<br />

{<br />

3-20 Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. <strong>ARM</strong> DUI 0350AK


NEON 벡터화 컴파일러 사용<br />

}<br />

}<br />

r[i] = add(a[i], b[i]);<br />

int main()<br />

{<br />

static const short x[128] =<br />

{<br />

0x0000, 0x0647, 0x0c8b, 0x12c8, 0x18f8, 0x1f19, 0x2528, 0x2b1f,<br />

0x30fb, 0x36ba, 0x3c56, 0x41ce, 0x471c, 0x4c3f, 0x5133, 0x55f5,<br />

0x5a82, 0x5ed7, 0x62f2, 0x66cf, 0x6a6d, 0x6dca, 0x70e2, 0x73b5,<br />

0x7641, 0x7884, 0x7a7d, 0x7c29, 0x7d8a, 0x7e9d, 0x7f62, 0x7fd8,<br />

0x8000, 0x7fd8, 0x7f62, 0x7e9d, 0x7d8a, 0x7c29, 0x7a7d, 0x7884,<br />

0x7641, 0x73b5, 0x70e2, 0x6dca, 0x6a6d, 0x66cf, 0x62f2, 0x5ed7,<br />

0x5a82, 0x55f5, 0x5133, 0x4c3f, 0x471c, 0x41ce, 0x3c56, 0x36ba,<br />

0x30fb, 0x2b1f, 0x2528, 0x1f19, 0x18f8, 0x12c8, 0x0c8b, 0x0647,<br />

0x0000, 0xf9b9, 0xf375, 0xed38, 0xe708, 0xe0e7, 0xdad8, 0xd4e1,<br />

0xcf05, 0xc946, 0xc3aa, 0xbe32, 0xb8e4, 0xb3c1, 0xaecd, 0xaa0b,<br />

0xa57e, 0xa129, 0x9d0e, 0x9931, 0x9593, 0x9236, 0x8f1e, 0x8c4b,<br />

0x89bf, 0x877c, 0x8583, 0x83d7, 0x8276, 0x8163, 0x809e, 0x8028,<br />

0x8000, 0x8028, 0x809e, 0x8163, 0x8276, 0x83d7, 0x8583, 0x877c,<br />

0x89bf, 0x8c4b, 0x8f1e, 0x9236, 0x9593, 0x9931, 0x9d0e, 0xa129,<br />

0xa57e, 0xaa0b, 0xaecd, 0xb3c1, 0xb8e4, 0xbe32, 0xc3aa, 0xc946,<br />

0xcf05, 0xd4e1, 0xdad8, 0xe0e7, 0xe708, 0xed38, 0xf375, 0xf9b9,<br />

};<br />

static const short y[128] =<br />

{<br />

0x8000, 0x7fd8, 0x7f62, 0x7e9d, 0x7d8a, 0x7c29, 0x7a7d, 0x7884,<br />

0x7641, 0x73b5, 0x70e2, 0x6dca, 0x6a6d, 0x66cf, 0x62f2, 0x5ed7,<br />

0x5a82, 0x55f5, 0x5133, 0x4c3f, 0x471c, 0x41ce, 0x3c56, 0x36ba,<br />

0x30fb, 0x2b1f, 0x2528, 0x1f19, 0x18f8, 0x12c8, 0x0c8b, 0x0647,<br />

0x0000, 0xf9b9, 0xf375, 0xed38, 0xe708, 0xe0e7, 0xdad8, 0xd4e1,<br />

0xcf05, 0xc946, 0xc3aa, 0xbe32, 0xb8e4, 0xb3c1, 0xaecd, 0xaa0b,<br />

0xa57e, 0xa129, 0x9d0e, 0x9931, 0x9593, 0x9236, 0x8f1e, 0x8c4b,<br />

0x89bf, 0x877c, 0x8583, 0x83d7, 0x8276, 0x8163, 0x809e, 0x8028,<br />

0x8000, 0x8028, 0x809e, 0x8163, 0x8276, 0x83d7, 0x8583, 0x877c,<br />

0x89bf, 0x8c4b, 0x8f1e, 0x9236, 0x9593, 0x9931, 0x9d0e, 0xa129,<br />

0xa57e, 0xaa0b, 0xaecd, 0xb3c1, 0xb8e4, 0xbe32, 0xc3aa, 0xc946,<br />

0xcf05, 0xd4e1, 0xdad8, 0xe0e7, 0xe708, 0xed38, 0xf375, 0xf9b9,<br />

0x0000, 0x0647, 0x0c8b, 0x12c8, 0x18f8, 0x1f19, 0x2528, 0x2b1f,<br />

0x30fb, 0x36ba, 0x3c56, 0x41ce, 0x471c, 0x4c3f, 0x5133, 0x55f5,<br />

0x5a82, 0x5ed7, 0x62f2, 0x66cf, 0x6a6d, 0x6dca, 0x70e2, 0x73b5,<br />

0x7641, 0x7884, 0x7a7d, 0x7c29, 0x7d8a, 0x7e9d, 0x7f62, 0x7fd8,<br />

};<br />

short r[128];<br />

static const short expected[128] =<br />

{<br />

0x8000, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff,<br />

0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff,<br />

0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff,<br />

<strong>ARM</strong> DUI 0350AK Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. 3-21


NEON 벡터화 컴파일러 사용<br />

0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff,<br />

0x8000, 0x7991, 0x72d7, 0x6bd5, 0x6492, 0x5d10, 0x5555, 0x4d65,<br />

0x4546, 0x3cfb, 0x348c, 0x2bfc, 0x2351, 0x1a90, 0x11bf, 0x08e2,<br />

0x0000, 0xf71e, 0xee41, 0xe570, 0xdcaf, 0xd404, 0xcb74, 0xc305,<br />

0xbaba, 0xb29b, 0xaaab, 0xa2f0, 0x9b6e, 0x942b, 0x8d29, 0x866f,<br />

0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,<br />

0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,<br />

0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,<br />

0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000,<br />

0x8000, 0x866f, 0x8d29, 0x942b, 0x9b6e, 0xa2f0, 0xaaab, 0xb29b,<br />

0xbaba, 0xc305, 0xcb74, 0xd404, 0xdcaf, 0xe570, 0xee41, 0xf71e,<br />

0x0000, 0x08e2, 0x11bf, 0x1a90, 0x2351, 0x2bfc, 0x348c, 0x3cfb,<br />

0x4546, 0x4d65, 0x5555, 0x5d10, 0x6492, 0x6bd5, 0x72d7, 0x7991,<br />

};<br />

int i, ok = 1;<br />

fn(r, sizeof(r)/sizeof(*r), x, y);<br />

#if 0<br />

printf("r[] = {");<br />

for (i = 0; i < sizeof(r)/sizeof(*r); ++i)<br />

{<br />

if (i % 8 == 0) printf("\n ");<br />

printf(" 0x%04x,", (unsigned short)r[i]);<br />

}<br />

printf("\n};\n");<br />

#endif<br />

}<br />

for (i = 0; i < sizeof(r)/sizeof(*r); ++i)<br />

{<br />

if (r[i] != expected[i])<br />

{<br />

printf("mismatch: r[%d] = 0x%04x; expected[%d] = 0x%04x\n", i, r[i], i, expected[i]);<br />

ok = 0;<br />

break;<br />

}<br />

}<br />

if (ok) printf("** TEST PASSED OK **\n");<br />

return ok ? 0 : 1;<br />

#ifdef __TARGET_ARCH_7_A<br />

__asm void init_cpu()<br />

{<br />

// Set up CPU state<br />

MRC p15,0,r4,c1,c0,0<br />

ORR r4,r4,#0x00400000<br />

BIC r4,r4,#0x00000002<br />

// enable unaligned mode (U=1)<br />

// disable alignment faults (A=0)<br />

3-22 Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. <strong>ARM</strong> DUI 0350AK


NEON 벡터화 컴파일러 사용<br />

// MMU not enabled: no page tables<br />

MCR p15,0,r4,c1,c0,0<br />

#ifdef __BIG_ENDIAN<br />

SETEND BE<br />

#endif<br />

MRC p15,0,r4,c1,c0,2 // Enable VFP access in the CAR -<br />

ORR r4,r4,#0x00f00000 // must be done before any VFP instructions<br />

MCR p15,0,r4,c1,c0,2<br />

MOV r4,#0x40000000 // Set EN bit in FPEXC<br />

MSR FPEXC,r4<br />

IMPORT __main<br />

B __main<br />

}<br />

#endif<br />

<strong>ARM</strong> DUI 0350AK Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. 3-23


NEON 벡터화 컴파일러 사용<br />

3-24 Copyright © 2007 <strong>ARM</strong> Limited. All rights reserved. <strong>ARM</strong> DUI 0350AK

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!