티스토리 뷰

728x90
반응형

안녕하세요. Teus입니다.

 

이번 포스팅은 SIMD(Single Instrunction Multi Data)를 다룹니다.

 

이번에는 AVX2의 기본 연산 중 쓸만한 함수 중 add/sub연산을 정리합니다.

1. Add/Sub

두 Vector를 SIMD로 더하거나 빼는 연산 입니다.

Data Type Description
_mm256_add_ps/pd Add two floating-point vectors
_mm256_sub_ps/pd Subtract two floating-point vectors
_mm256_add_epi8/16/32/64 Add two integer vectors
_mm236_sub_epi8/16/32/64 Subtract two integer vectors

단순하게 두개의 Vector를 만들고, 이 두 Vector를 Elementwise하게 더하거나 빼는 연산을 지원합니다.

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <xmmintrin.h>
#include <immintrin.h >
int data_num = 1000000;
int thread_cnt = 8;


int main() {    
    int* arr1_ori = (int*)_aligned_malloc(sizeof(int) * 8, 32);
    int* arr2_ori = (int*)_aligned_malloc(sizeof(int) * 8, 32);
    for (int i = 0; i < 8; i++) {
        arr1_ori[i] = 32;
        arr2_ori[i] = 92;
    }
    __m256i arr1 = _mm256_load_si256((__m256i*)arr1_ori);
    __m256i arr2 = _mm256_load_si256((__m256i*)arr2_ori);    
    __m256i ret = _mm256_adds_epi8(arr1, arr2);
    int* my_ret = (int*)&ret;

    for (int i = 0; i < 16; i++) {
        printf("idx : %d, i : %d\n", i, my_ret[i]);
    }
}

위와같은 ElementWise Operation외에

 

선형대수 연산을 위한 수평Add, Sub 연산을 지원해 줍니다.

Data Type Description
_mm256_hadd_ps/pd Add two floating-point vectors horizontally
_mm256_hsub_ps/pd Subtract two floating-point vectors horizontally
_mm256_hadd_epi16/32 Add two integer vectors horizontally
_mm256_hsub_epi16/32 Subtract two integer vectors horizontally
_mm256_addsub_ps/pd Add and subtract two floating-point vectors

image.png


그래서 이걸 코드로 확인해보면 아래와 같습니다.

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <xmmintrin.h>
#include <immintrin.h >
int data_num = 1000000;
int thread_cnt = 8;


int main() {    
    __m256i arr1 = _mm256_setr_epi32(2, 4, 6, 8, 10, 12, 14, 16);
    __m256i arr2 = _mm256_setr_epi32(1, 3, 5, 7, 9, 11, 13, 15);    
    __m256i ret = _mm256_hadd_epi32(arr1, arr2);
    int* my_ret = (int*)&ret;

    int* _arr1 = (int*)&arr1;
    int* _arr2 = (int*)&arr2;
    for (int i = 0; i < 8; i++) {
        printf("idx : %d, arr1[%d] = %d, arr2[%d] = %d\n", i, i, _arr1[i], i, _arr2[i]);
    }

    for (int i = 0; i < 16; i++) {
        printf("idx : %d, i : %d\n", i, my_ret[i]);
    }
}

image.png


해당 연산은 특이하게 정수, 실수에 따라 연산 방법이 달라집니다.
(intel intrinsic guide를 보면 명시되어있네요)
_mm256_hadd_epi32

image.png


_mm256_hadd_pd

image.png

실수일때는 아래를 참고해 주세요.

image.png

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <xmmintrin.h>
#include <immintrin.h >
int data_num = 1000000;
int thread_cnt = 8;


int main() {    
    __m256d arr1 = _mm256_setr_pd(0.5, 0.9, 0.1, 0.4);
    __m256d arr2 = _mm256_setr_pd(0.1, 0.3, 0.7, 0.4);    
    __m256d ret = _mm256_hadd_pd(arr1, arr2);
    double* my_ret = (double*)&ret;

    double* _arr1 = (double*)&arr1;
    double* _arr2 = (double*)&arr2;
    for (int i = 0; i < 4; i++) {
        printf("idx : %d, arr1[%d] = %f, arr2[%d] = %f\n", i, i, _arr1[i], i, _arr2[i]);
    }

    for (int i = 0; i < 8; i++) {
        printf("idx : %d, i : %f\n", i, my_ret[i]);
    }
}

image.png

728x90
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함