Blog | Tag | Local | Guest | Login | Write |  RSS
LookUp Table 연산

지금까지 포인트 단위의 산술연산에 관한 포스팅을 하였습니다.
어렵지 않은 내용이라 모두들 쉽게 이해하셨으리라 생각합니다.
실제로도 많이 사용되는 내용이기도 하고 구현 내용도 어렵지 않기 때문에,,
사람이 생각하기에는 크게 느리지 않은 연산이라고 생각하기 쉽지만..
사실 컴퓨터 입장에서는 각 포인트마다 연산을 다 해주어야 하기 때문에,, 많은 연산을 거쳐야 하는 함수임에 틀림 없습니다.

물론 지금 구현된 내용처럼 이미지가 작거나 (저번포스팅들에서 사용된 이미지는 512*512,256*256 이였습니다.)
하면 크게 속도차이가 보이지 않는것은 사실이지만,,,
사람이 살다보면 작은 해상도의 이미지만을 다루는 것이 아니기 때문에 좀 더 고속으로 연산할 수 있는 방법이 필요합니다.

이를 위해 나온것이 바로 LookUp Table연산 방식입니다.
이번포스팅에서는 저번 포스팅에서 다솜돌이 님께서 언급하셨던 고속 연산방식인 룩업테이블에 대하여 이야기하겠습니다.
(다솜돌이님 ㅋ 포스팅 순서가 있었어요 ㅋㅋㅋ 일부로 안쓴거라고요 ㅋㅋ)

1. 기존의 연산방법

 
   그렇게 느리다고 생각되지 않습니다만,,  이는 이미지의 크기가 작아서 라고 보시면 됩니다. (때마다 달랐지만..13ms)
 코드 보기
       public void Mul(int Const)
        {
            int TempNum;
            for (int X = 0; X < 512; X++)
            {
                for (int Y = 0; Y < 512; Y++)
                {
                    TempNum = TestData[X][Y] * Const;

                    TempNum = TempNum < 0 ? 0 : TempNum;
                    TempNum = TempNum > 255 ? 255 : TempNum;

                    TestData[X][Y] = (Byte)TempNum;
                }
            }
        }



2. LookUpTable을 사용한 경우
 

LUT를 사용한 연산

  같은 내용의 결과를 내는데 걸린 시간이 거의 1/4까지 줄어든 모습을 확인 할 수 있습니다.
  코드 보기
        public void MulUsingLookUpTable(int Const)
        {
            int TempNum;
            Byte[] LUT = new Byte[256];

            // LookUp Table을 완성합니다.
            for (int i = 0; i < 256; i++)
            {
                TempNum = i * Const;
                TempNum = TempNum > 255 ? 255 : TempNum;
                LUT[i] = (Byte) TempNum;
            }

            // LUT를 이용하여 연산을 수행합니다.
            for (int X = 0; X < 512; X++)
            {
                for (int Y = 0; Y < 512; Y++)
                {
                    TestData[X][Y] = LUT[ImageData[X][Y]];
                }
            }
        }



 뭐가 뭔지 모르겠다.
 위나 아래나 for문이 들어갔는데,, 오히려 LookUpTable방식에서는 256번의 for문이 있지않느냐?
 그럼 더 느린것이 아닌가?! 라고 하신다면.. 비밀인 여기입니다.

 연산수를 따져봅시다.
 기존의 방식 LUT의 방식 
 for (int X = 0; X < 512; X++)
            {
                for (int Y = 0; Y < 512; Y++)
                {
                    TempNum = TestData[X][Y] * Const;

                    TempNum = TempNum < 0 ?
                                       0 : TempNum;
                    TempNum = TempNum > 255 ?
                                       255 : TempNum;

                    TestData[X][Y] = (Byte)TempNum;
                }
            }

            for (int i = 0; i < 256; i++)
            {
                TempNum = i * Const;
                TempNum = TempNum > 255 ?
                                   255 : TempNum;
                LUT[i] = (Byte) TempNum;

            }       
      for (int X = 0; X < 512; X++)
            {
                for (int Y = 0; Y < 512; Y++)
                {
                    TestData[X][Y] = LUT[ImageData[X][Y]];
                }
            }
                            곱하기 연산의 수 512 * 512 = 262144
             Saturation을 위한 연산의 수 512 * 512 = 262144
    +                                               대입연산의 수 512
                      ===================================
                                                                     524800
                                                 곱하기 연산의 수 256
                                  Saturation을 위한 연산의 수 256
     +                                               대입연산의 수 512
            ================================
                                                                        1024
결과 : 13ms 결과 : 4ms 

 LUT방식은 미리 연산해야 하는 내용을 미리 연산 한 후 ,
 연산의 결과에 해당하는 값만을 대입하는 방식이므로 위의 결과와 같이 연산의 수를 대폭 줄일 수 있습니다.
 이를 통하여 좀 더 빠른 연산을 할 수 있는것이지요 ^^*
 (그림을 표현해서 설명하고 싶었는데,, 살짝귀차니즘이 ㄷㄷㄷㄷ;;;; 추후에 수정하겠습니다.;)

 사실 구현할때는 귀찮을 수 도 있지만,,
 좀더 빠른 결과를 위해서라면 귀차니즘을 극복하고 사용할 만한 방식인것은 충분합니다..

 이번 포스팅은 이만 마칩니다.