xinflate 라는 deflate 알고리즘의 압축 해제 라이브러리를 만들면서 "속도"를 위한 최적화 프로그래밍에 대해서 많은것을 생각하게 되었다.

재미있게도 극단적인 속도를 위한 프로그래밍에서는 전통적인 프로그래밍의 규칙들을 다 무시해야 한다.

* 인라인 함수 대신 매크로를 사용해라.
: 경우에 따라서는 인라인 함수보다 매크로가 훨씬 빠를 수 있다.

예를 들어서 swap 함수는 다음과 같이 작성할 수 있다.
inline void swap(int &a, int &b)
{
 int temp = a;
 a = b;
 b = temp;
}

여기서 int temp 와 같은 로컬 변수를 사용하게 되므로 만일 루프 내에서 
while(조건)
{
 ....
 swap(a, b);
}

와 같이 사용할 경우 이 inline 함수는

while(조건)
{
  ...
  int temp = a;
  a = b;
  b = temp;
}

와 같이 바뀔 것이다.

이걸 매크로로 바꿔보자.

#define SWAP(a, b) temp = a; a = b; b = temp;

어떤가 비슷해 보이는가?

int temp;
while( 조건)
{
 ....
  SWAP(a, b)
}

이렇게 보면 좀 달라 보인다. int temp 가 루프 바깥에 위치하게 된다.
물론 컴파일러에 따라서 int temp 가 루프 바깥에 위치하거나 안쪽에 위치하거나 둘다 최적화 시킨 동일한 결과를 얻을수도 있다. 하지만, 코드가 복잡해 지기 시작하면 inline 대신 매크로를 사용하여 변수의 위치를 명시적으로 지정하여 속도를 향상시킬 수 있다.


* 중복된 코드를 줄이지 말고 코드를 풀어써라
: 변수를 사용해서 중복된 코드를 줄이는 것보다, 상수를 사용하고 코드를 늘리는것이 속도가 빨라질 수 있다. 
예를 들자면 
int blockSize;
blockSize = ....;

for(조건)
{
 memcpy(dst, src, blockSize);
}

와 같이 코딩하는것보다

if(blockSize==3)
{
 for(조건)
  {
  memcpy(dst, src, 3);
 }
}
else if(blockSize==4)
{
 for(조건)
 {
  memcpy(dst, src, 4);
 }
}

와 같이 코딩하는것이 속도가 더 빨라질 수 있다.



* const  변수보다 전처리기를 이용한 상수를 사용해라.
: const 변수는 그 값을 (일반적으로) 바꿀 수 없지만, 내부적으로는 "진짜" 변수로 처리되기 때문에 상수보다 속도가 느리다. const 변수대신 상수를 써서 속도를 향상 시킬 수 있다.

예를 들자
cons int a= 10;
이라고 선언을 하면 a 는 바꿀수 없을까?
물론 a=20; 이라고 치면 컴파일러가 에러를 발생시킨다.
하지만 int* p = (int*)&a;  *p = 20; 이라고 하면 별 문제 없이 a 값을 바꿀 수 있게 된다.
즉 const int a = 10 과  #define A  10 은 컴파일러 내부에서 똑같이 처리할 수 없다.

변수에 대한 접근은 메모리에 대한 접근인 반면 상수를 사용하면 메모리에 접근할 필요가 없기 때문에 속도가 더 빨라질 수 있다.


* 컴파일러의 최적화를 믿지 마라.
x = y >> 1 ;
 x = y /2  ;
둘중 어느 코드가 더 빠를까? 대부분의 컴파일러는 이 명령문을 동일한것으로 판단해서 동일한 코드 ( x = y >> 1) 를 생성하게 된다. 따라서 의미론적으로 /2 명령을 수행하고 싶으면, 가독성을 위해서 위의 코드보다는 아래의 코드를 사용하라고 일반적으로 이야기 한다.
하지만 내가 테스트해본 결과 visual studio 에서는 수식이 복잡해 지기 시작하면, 나누기 연산자를 더이상 shift 연산자로 처리하지 않는다. 따라서, 수식이 복잡한 경우는 나누기 보다는 shift 연산자가 더 빠르기 때문에 나누기를 사용하는것 보다 shift 연산자를 사용하는 것이 보다 빠른 코드를 얻을 수 있게 된다.


이것 이외에도 속도를 높이기 위한 많은 방법이 존재한다(멤버 변수 대신 로컬 변수를 사용하기 등등.). zlib 와 lzma 의 소스를 일부 본 결과 이 라이브러리 들은 속도를 늘이기 위한 극단적인 방법들을 매우 많이 사용하였다. 물론 위에 언급한 원칙들은 극단적인 경우에만 허용되는 원칙이며 일반적인 코딩에서는 절대 사용해서는 안되는 원칙들이다.



Posted by 키플러
,