프로그래밍 최적화는 기법은 크게 두 가지다.

1. 명시적 기법

2. 묵시적 기법


둘 다 하드웨어 환경, 운영체제에 대한 지식은 갖고 가야 한다.


명시적 기법을 사용할 수 있는 경우는,

inline assembly 나, intrinsic 명령어와, 프레임웍을 사용는 경우다.

엄밀히 C / C++ 은 아니지.


묵시적 기법을 사용하는 경우는,

자신이 구사한 C / C++ 문법의 표현이 무엇으로 해석될지 예측해야 한다.

예측이 항상 성공하기는 힘드니까 적절한 테스트가 반드시 필요하다.

이 경우, 언어 자체보다도 컴파일러의 특성을 잘 이해해야 한다.

왜냐하면

대개의 컴파일러들이 관용적으로 잘 최적화 하는 케이스들과

특정 컴파일러에서 미친듯이 잘 최적화 하는 특별한 케이스로 나뉘기 때문이다.

어쨌든 C / C++ 문법만으로 표현가능한 범위이긴 하다.


자, 문제로 돌아가 보자.


최신 컴파일러는, 메모리의 정렬상태, 접근하는 단위, 크기에 따라

별도의 최적화 코드를 생성한다.


난 sum, min, max, memmove 등을 직접 코딩해 보면서

aligned, unaligned, intrinsic 의 조합들의 성능을 이미 테스트 해 봤다.

궁금한 사람들은 카페로 가서 sum 코드 같은거 받아서 컴파일결과 보셔.

잔버그는 좀 있을지 모름 사실 별로 테스트는 안하고 올린거라서

( 남들이 좀 테스트 해 주지 귀찮음 )


unaligned 와 aligned 가 성능이 비슷비슷한 예는 많아.

문제에 따라서 aligned 를 제대로 구현하자면

아주 유지보수하기 좆같은 코드가 만들어지는게 문제지.

( 뭐 성능을 위해서라면 뭐든 못하겠냐만은 )

그런데, 문제에서 나는 확실히 unaligned 가 유리한 케이스를 예로 들었다.


왜냐고?

정렬되지 않은 주소의 값을 정렬 단위로 읽기 위해서 bitwise 를 사용한다면,

변수를(메모리든 레지스터든) 할당하고,

그곳에 source 주소의 내용을 읽어서 보관해야 한다는거다. 1.

그리고 그다음에 읽어온 word 단위랑 다시 합성해야하지. 2.

그결과가 나오고 나서야(write back) dst 주소에 대입이 가능함.


즉, C 언어 레벨에서 bitshift 를 쓰지 않고, bitfield 나 공용체 등을 사용하지 않은 상태에서

합성 자체가 불가능하니, 시작 주소만 맞추는정도로 끝나는 작업이 아니라

저 녀석이 찡찡 거리는건데,

그게 다 내 손바닥이지.

즉 aligned 를 명시하기 위해서는

컴파일러에게 재량껏 컴파일을 하란 명령 자체를 할 수 없다!

는 함정에 지가 빠진거지.

근데 만약 간단히 for 문 따위로 word 단위 전송을 시도하잖아?

저따위 코드 보다 나을거야 당연히 ㅋㄷ

왜냐하면 컴파일러로 하여금 개발자가 의도하는바가 무언지를 보다 쉽게 알려줄 수 있거든.


그리고!

중요한 부분인데.

아주 사소한 중간과정, 혹은 캐시초과 상태만 있어도, unaligned SIMD 랑 aligned SIMD 는

성능 차이가 나지 않는 경우가 왕왕 있다. ( 첨에도 이야기 했음 )

여러 알고리즘을 짜면서 정렬한 케이스랑 아닌 케이스들 비교해봤지.

대부분 성능차이 안남. 그리고 최신 프로세서일수록 unaligned 쪽이 오히려 (약간)

우세한 경우도 잦음.

오히려 시작주소만 aligned 로 작성했을때에도, SIMD를 쓰지 않고 classic instruction 으로 변환되는 경우도 잦아.


요약하면.

kukyakya는 이미 진게임을 시작한거야.

왜?

무식한게 용감해서.


그리고 자꾸 UB 나불거리는데.

니 입으로 니가 쓴 첫 글에 이야기한거야.

아래는 인용글


성능을 최적화하려면 undefined behavior는 둘째치더라도

unaligned access가 일어나지 않도록 해야하는게 기본인데

성능 최적화 때문에 unaligned access가 꼭 필요할 때가 있다고 우기는게 유머.