SVE2(Scalable Vector Extension 버전 2) - LAB 6 파트 2

4792 단어 lab6spo600

소개



SVE2(Scalable Vector Extension 버전 2)의 2부에 오신 것을 환영합니다. 이 게시물의 내용이 확실하지 않은 경우 더 나은 아이디어를 얻을 수 있습니다.

SVE2 적응을 위한 변환을 위한 소스 코드(vol1.c)




#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "vol.h"

int16_t scale_sample(int16_t sample, int volume) {

        return ((((int32_t) sample) * ((int32_t) (32767 * volume / 100) <<1) ) >> 16);
}

int main() {
        int             x;
        int             ttl=0;

// ---- Create in[] and out[] arrays
        int16_t*        in;
        int16_t*        out;
        in=(int16_t*) calloc(SAMPLES, sizeof(int16_t));
        out=(int16_t*) calloc(SAMPLES, sizeof(int16_t));

// ---- Create dummy samples in in[]
        vol_createsample(in, SAMPLES);

// ---- This is the part we're interested in!
// ---- Scale the samples from in[], placing results in out[]
        for (x = 0; x < SAMPLES; x++) {
                out[x]=scale_sample(in[x], VOLUME);
        }

// ---- This part sums the samples.

        for (x = 0; x < SAMPLES; x++) {
                ttl=(ttl+out[x])%1000;
        }

// ---- Print the sum of the samples.

        printf("Result: %d\n", ttl);

        return 0;

}


알다시피 이것은 알고리즘 선택에 대한 vol1입니다.
vol1은 고정 소수점 계산을 사용합니다. 이렇게 하면 정수와 부동 소수점 사이를 반복적으로 캐스팅하는 비용을 피할 수 있습니다.

변환 중


C 컴파일러 옵션



대부분의 컴파일러에는 Armv9 시스템에 대한 특정 대상이 없습니다. 따라서 SVE2 명령어를 포함하는 코드를 빌드하려면 SVE2 명령어도 이해하는 Armv8-a 프로세서용 코드를 내보내도록 컴파일러에 지시해야 합니다. GCC 컴파일러에서 이것은 -march= 옵션을 사용하여 수행됩니다.

Armv8a 프로세서가 SVE2를 이해할 수 있도록 컴파일러에 지시하여 GCC 버전 11에서 자동 벡터화기를 호출해야 합니다. -O3 또는 적절한 기능 옵션을 사용해야 합니다.

gcc -O3 -march=armv8-a+sve2 


우리의 경우에는 vol1로 작업할 것입니다.

gcc -o3 -march=armv8-a+sve2 vol1.c vol_createsample.c -o vol1


그런 다음 QEMU 사용자 모드 시스템으로 에뮬레이션하여 프로그램을 실행할 수 있습니다. 이렇게 하면 하드웨어에서 직접 Armv8a 명령을 실행하는 동안 SVE2 명령을 트랩하고 소프트웨어에서 에뮬레이션합니다.

qemu-aarch64 ./vol1


결과:





변환된 코드




.arch armv8-a+sve2
        .file   "vol1.c"
        .text
        .align  2
        .p2align 4,,11
        .global scale_sample
        .type   scale_sample, %function
scale_sample:
.LFB24:
        .cfi_startproc
        lsl     w2, w1, 15
        mov     w3, 34079
        sub     w1, w2, w1
        movk    w3, 0x51eb, lsl 16
        sxth    w0, w0
        smull   x3, w1, w3
        asr     x3, x3, 37
        sub     w1, w3, w1, asr 31
        lsl     w1, w1, 1
        mul     w0, w1, w0
        lsr     w0, w0, 16
        ret
        .cfi_endproc
.LFE24:
        .size   scale_sample, .-scale_sample
        .section        .rodata.str1.8,"aMS",@progbits,1
        .align  3
.LC0:
        .string "Total Time: %2.9f\n"


변환된 코드 이해



SVE2 명령어




 .cfi_startproc
        lsl     w2, w1, 15
        mov     w3, 34079
        sub     w1, w2, w1
        movk    w3, 0x51eb, lsl 16
        sxth    w0, w0
        smull   x3, w1, w3
        asr     x3, x3, 37
        sub     w1, w3, w1, asr 31
        lsl     w1, w1, 1
        mul     w0, w1, w0
        lsr     w0, w0, 16
        ret
        .cfi_endproc


해당 C 코드




return ((((int32_t) sample) * ((int32_t) (32767 * volume / 100) <<1) ) >> 16);


  • 'movk w3, 0x51eb, lsl 16'에는 'lsl 16' 명령이 포함되어 있으며 비트가 왼쪽으로 16비트 이동되어야 함을 나타냅니다.
  • 'sxth'는 레지스터 w0에게 자신의 최하위 요소에 서명하도록 지시합니다.
  • 'smull x3, w1, w3'은 '볼륨' 값에 32767을 곱한 값을 의미합니다.
  • 'lsl w1, w1, 1'은 끝에서 왼쪽으로 1비트 이동하는 것을 의미합니다.
  • 'mul w0, w1, w0'은 샘플을 곱한 결과를 부호 있는 32비트 정수로 바꿉니다.
  • 'lsr w0, w0, 16'은 최종 결과 정수의 비트를 오른쪽으로 16번 이동합니다.

  • 결론



    우리는 볼륨 조정 알고리즘(vol1)에 대한 SVE2 명령을 실험했습니다. SVE2는 현재 매우 새롭기 때문에 이를 위해 개발된 시스템이 거의 없습니다. 그리고 우리는 프로그램을 실행하기 위해 에뮬레이터를 사용해야 합니다. 어셈블리 코드의 SVE2 성능을 테스트할 방법을 찾지 못했습니다.
    내가 발견한 랩에서 가장 어려운 부분은 C 코드를 SVE2 명령어로 변환한 후 SVE2의 명령어를 원래 C 파일의 코드와 연결하려고 시도했을 때였습니다.

    출처: SVE2

    좋은 웹페이지 즐겨찾기