잡담

SIMD Intrinsic을 이용한 성능 개선?

SIMD(Single Instruction, Multi Data)는 여러 데이터를 하나의 명령어로 연산 수행이 가능한 CPU 명령어 종류이다. 주로 멀티미디어 환경 개선을 위해 사용되고 있고, Intel/AMD의 x86, x86_64 CPU는 물론이고 ARM CPU에서도 지원하고 있다. 물론 형태는 제각각 조금씩 다르긴 하지만.

특히 게임에서 SIMD를 활용한 성능 개선이 가능한데, 벡터 연산과 행렬 연산, 물리 연산 등에 SIMD 명령어를 사용하면 성능을 조금 더 개선이 가능하다. 물론 효과는 좀 미미하긴 하지만 이 미미한 차이가 다른 곳에 신경을 덜 쓰게 하냐 더 쓰게 하냐의 문제가 되니 개발자 입장에서는 쓸 수 밖에 없는 것이다.

컴파일러에서 자동으로 SIMD 명령어로 빌드를 해주는 것도 가능하긴 하지만 어디까지나 운에 맡겨야 하고 코드도 컴파일러가 “이 코드는 SIMD 명령어로 치환하는게 가능하겠는걸?”이라고 인식할 수 있는 정도의 규칙도 맞춰줘야 한다.

때문에 개발자들은 보통 SIMD 명령어 등을 사용하기 위해 어셈블리 코드를 직접 작성하거나 Intrinsic 코드를 작성하는데, 전자는 IA32/AMD64의 두 경우에 있어서 각각의 어셈블리 코드를 따로 작성해줘야 하고 특히나 Visual C++은 64비트 빌드에 대해서 인라인 어셈블리를 사용할 수 없어서 편의성에 문제가 있다. 이에 반해 Intrinsic 코드는 몇 가지 헤더파일만 포함하면 함수 형태로 명령어를 사용할 수 있다.

뭐 이런 이론은 대충 넘어간다고 치고, 그래서 나도 벡터와 행렬을 Intrinsic을 이용해 작성해보기로 했는데, 무슨 이유인지 모르겠으나 C++로 작성한 코드가 Intrinsic으로 작성한 코드보다 빠르다.

Vector4 Get Length
Time by Intrinsic code: 0.933216
Time by C++ code: 0.768878
Vector4 Multiply
Time by Intrinsic code: 0.212694
Time by C++ code: 0.194507
Matrix4x4 Multiply
Time by Intrinsic code: 0.710493
Time by C++ code: 0.504729

도대체 왜 이런지 모르겠고, 디스어셈블리 해서 코드도 봤는데 전혀 이유를 모르겠음이다. 이유를  찾을 수 있으면 좋을텐데.

뭐, 이미 오픈소스로 SIMD 벡터/행렬 라이브러리가 있긴 하다. 그러나 이미 있는 걸 그냥 가져다 쓰느냐 내가 이해하고 그 이외의 다른 부분에도 적용할 수 있냐는 다른 문제기 때문에 그걸 해결하고 넘어가보고 싶은 것. 작년 중순부터 한 번씩 시도해보고 있는 것인데 아직도 성능 문제가 해결이 안 된다. 어떻게 해야 할까…

+ 시간이 아니라 CPU 사이클을 측정해보니 Intrinsic 코드가 좀 더 사이클 수가 적다. 왜 시간은 더 걸리는지 모르겠는 일…

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Google photo

Google의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중

This site uses Akismet to reduce spam. Learn how your comment data is processed.