티스토리 뷰

728x90
반응형

안녕하세요. Teus입니다.

 

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

 

이번에는 AVX를 Array로 사용하지않고, Pointer를 사용하는 패턴을 보도록 하겠습니다.

1. _aligned_malloc

_aligned_malloc(size_t data_size, size_t alignemnet_size)

aligned_malloc은 기본적인 malloc과 다르게 alignement_size 만큼 Data끼리의 간격을 보장해주는 Malloc을 의미합니다.

 

일반적으로 16byte, 32byte씩 Data를 띄워주면 SIMD의 Data처리 효율이 증가한다고 알려져 있습니다.

__m256d* arr1 = (__m256d*)_aligned_malloc(sizeof(double) * data_num, 32);

2. Data의 초기화

malloc으로 Data를 할당받을 경우 보통 쓰레기값으로 Data가 차 있습니다.

 

이때 Data를 초기화 시켜야지 내가 원하는 연산을 할 수 있겠죠?

 

이때 초기화 시킬때

  1. 동일한 값으로 채우기
  2. 다른 array를 사용해서 가지고오기

를 생각해볼 수가 있습니다.

 

다른 값으로 채워오기는

함수 Description
_mm256_set1_ps/pd 256bit을 64/32bit의 값으로 broadcast
_mm256_set1_epi8/16/32/64x/ps/pd 해당 Vector를 입력한 값으로 broadcast
_mm256_setzero_pd/ps/si256i type에 맞는 0채워진 Vector를 반환

 

다른 Array에 있는 값을 가지고 올때는 이전에 사용했던 함수들을 사용합니다.

함수 Description
_mm256_set_epi8/16/32/64x/pd/ps 256/data_size 만큼의 Element를 입력하고, 해당 값으로 Vector를 초기화시킴
_mm256_setr_epi8/16/32/64x/pd/ps 위 함수와 reverse순으로 Data를 기록시킴
_mm256_set_m128i/m128d/m128 256bit의 값을 상위 128bit은 첫번째 값, 하위 128bit은 두번째 값으로 채움

주의사항이, set을 사용할 경우 마지막 매개변수가 첫번째 값이 됩니다.
_mm256_set_ps

image.png

그래서 사람이 인지하기 쉽게 하기 위해서 setr이 주로 사용되게 됩니다.

for (int i = 0; i < data_num / 4; i++) {        
/*
simd의 native routine을 사용하는 방법
    _mm256_store_pd((double*)&ret[i], _mm256_setzero_pd());
    _mm256_store_pd((double*)&arr1[i], _mm256_setzero_pd());
    _mm256_store_pd((double*)&arr2[i], _mm256_setzero_pd());
*/
//pointer를 바로 사용할 경우
    ret[i] = _mm256_setzero_pd();
    arr1[i] = _mm256_setzero_pd();
    arr2[i] = _mm256_setzero_pd();
}

3. 연산하기

연산 부분에서는 이제 반복문으로 접근하여

 

Vecotr를 가지고오고, 연산을 하게 됩니다.

 

이전 예제코드에서는 Vector하나만 존재했기 때문에 반복문이 필요 없었지만

 

pointer를 사용하여 연산할 경우 2개 이상의 Vector를 사용하기 때문에

 

Pointer를 사용해서 Data에 접근하고, _mm256_add_pd와 같은 SIMD 연산자를 사용하게 됩니다.

for (int i = 0; i < data_num / 4; i++) {
/*
simd의 native routine을 사용하는 방법
    __m256d first_val = _mm256_load_pd((double*)&arr1[i]);
    __m256d second_val = _mm256_load_pd((double*)&arr2[i]);
    __m256d ret_values = _mm256_add_pd(first_val, second_val);
    _mm256_store_pd((double*)&ret[i], ret_values);
*/
//pointer를 바로 사용할 경우
    ret[i] = _mm256_add_pd(arr1[i], arr2[i]);
}

위까지 사용한 코드를 이제 종합 해 보겠습니다.

 

아래 코드는 Pointer를 사용해서 새롭게 Memory를 할당받고

 

할당받은 Memory를 0으로 초기화하고, SIMD Add연산을 하는 예제 입니다.

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

int main() {    

    __m256d* arr1 = (__m256d*)_aligned_malloc(sizeof(double) * data_num, 32);
    __m256d* arr2 = (__m256d*)_aligned_malloc(sizeof(double) * data_num, 32);
    __m256d* ret = (__m256d*)_aligned_malloc(sizeof(double) * data_num, 32);

    for (int i = 0; i < data_num / 4; i++) {        
        /*
        _mm256_store_pd((double*)&ret[i], _mm256_setzero_pd());
        _mm256_store_pd((double*)&arr1[i], _mm256_setzero_pd());
        _mm256_store_pd((double*)&arr2[i], _mm256_setzero_pd());
        */
        ret[i] = _mm256_setzero_pd();
        arr1[i] = _mm256_setzero_pd();
        arr2[i] = _mm256_setzero_pd();
    }    

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

    for (int i = 0; i < data_num / 4; i++) {
        /*
        __m256d first_val = _mm256_load_pd((double*)&arr1[i]);
        __m256d second_val = _mm256_load_pd((double*)&arr2[i]);
        __m256d ret_values = _mm256_add_pd(first_val, second_val);
        _mm256_store_pd((double*)&ret[i], ret_values);
        */
        ret[i] = _mm256_add_pd(arr1[i], arr2[i]);
    }
}
728x90
반응형

'C언어 잡기술 > SIMD(AVX)' 카테고리의 다른 글

AVX 튜토리얼5. Permuting/Shuffling연산  (0) 2024.04.24
AVX 튜토리얼4. FMA연산  (0) 2024.04.24
AVX 튜토리얼3. mul/divide연산  (0) 2024.04.24
AVX 튜토리얼2. Add/Sub연산  (0) 2024.04.24
AVX 튜토리얼1. DataType  (0) 2024.04.02
공지사항
최근에 올라온 글
최근에 달린 댓글
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
글 보관함