SIMD 연산은 C언어에서 += 연산과 유사한 동작을 한다


예)


int a,b;


a += b;


와 유사한 연산을 한다





B : byte

W :word            

D : double word  = 4 byte

Q : quad word    = 8 byte


S는 signed US 는 unsiged 를 나타냄으로


PADDUSW 의 경우는?


위 규칙대로 해석한다면 Unsigned Word 타입으로 unsiged short : 16 bit 이며 오버플로우시 + 부호를 유지한다로

볼 수 있다








배열에 값 담아 놓고 c++ 로 더할때와 simd 를 사용해서 더할때와의 속도차 비교

[소스코드 날림 주의.. ㅋ]


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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include <iostream>
#include <fstream>
#include <windows.h>
#include <string.h>
#include <chrono>
 
 
 
int totalSum(int sizeint data[])
{
    int sum=0;
    for(int i=0;i< size++i)
    {
        sum += data[i];
    }
    
    return sum;
}
 
 
int main()
{
 
 
    const int unit = 16;
    const int size = 40002;
    int _package=4, totalByte =0;
 
    int data[size= { 0, };
    int result[4= {0,};
 
    int quotientByte = 0;
    int quotient = (size * _package) / unit;                    // 16 byte로 떨어지는 개수, 소수점 버림
    int remainder = (size * _package) % unit;                // 16 byte 이외의 엽ㄴ
    int total = 0;
 
 
    std::fill(data, &data[size], 2);
 
 
    std::chrono::system_clock::time_point start1 = std::chrono::system_clock::now();
    std::cout<<"C++ total : "<<totalSum(size,data)<<std::endl;        //80004
    std::chrono::duration<double> sec1 = std::chrono::system_clock::now() - start1;
 
    std::cout << "simd 걸린 시간(초) : " << sec1.count() << " seconds" << std::endl;
 
 
 
 
    
    std::chrono::system_clock::time_point start = std::chrono::system_clock::now();
 
    __asm {
 
        pushad
        
        mov eax, 16
        mov ecx, quotient
        mul ecx
        mov quotientByte, eax
 
        lea esi, data
        
        pxor xmm1, xmm1
        mov ecx, 0
 
        loopAdd:
        movdqu xmm0, [esi + ecx]            //16 byte 를 xmm0 에 복사
        paddd xmm1, xmm0
 
        add ecx, unit
        cmp ecx, quotientByte
        jl    loopAdd                                //0이 아니면
 
        movdqu result, xmm1
 
        popad
        emms
    }
 
 
    //일단 지금까지의 합 구하기 (이 구문은 나중에 simd 로 한번에 처리할 수 있음)
    
    for (int i=0;i<_package;++i)
    {
        total += result[i];
    }
 
    //나머지 여분 값 더하기
    for(int i= quotientByte/_package; i< (quotientByte +remainder)/ _package; ++i)
    {
        total += data[i];
    }
 
    std::chrono::duration<double> sec = std::chrono::system_clock::now() - start;
 
    std::cout << "simd 걸린 시간(초) : " << sec.count() << " seconds" << std::endl;
 
 
    std::cout << "SIMD total : " << total << std::endl;        //80004
 
    system("pause");
 
 
    return 0;
}
 
 
 
 
 

cs






simd 연산으로 더한 결과가 훨씬 빠름을 알 수 있다

최종 total 값이 자료형의 범위를 넘지 않는다면 더 작은 바이트(4바이트가 아닌 2바이트)에서 연산 할 경우 더 높은 성능향상을

기대할 수 있다





반응형

+ Recent posts