삽입 정렬 소스에서 배열변수와 일반변수

모데스티의 이미지

이재규씨가 집필한 C로 배우는 알고리즘 개념과 기본 알고리즘으로 공부중인 모데스티라 합니다. 이 책 331페이지를 보면 C로 구현한 삽입정렬 소스가 개제되어 있는데요. 아래와 같습니다.

void insert_sort(int a[], int n)
    {
    int i, j, t;
    for (i = 1; i < n; i++)
       {
       t = a[i];
       j = i;
       while (a[j-1] > t && j > 0) /*삽입될 곳을 찾음 */
            {
            a[j] = a[j-1]; /* 뒤로 옮김 */
            j--;
            }
       a[j] = t; /* 삽입함 */
       }
    }
 

저자는 위에 적은 소스에서 변수 t는 불필요하지만 굳이 t를 쓴 이유는 속도향상을 위해서라고 말합니다. 그러면서 a[i]를 쓰면 a의 값(주소)를 읽어서 i를 더하는 식의 복잡한 처리를 하는 반면 t를 쓰면 단순히 t의 값을 읽어오는 것으로 처리가 끝난다는 근거를 제시합니다. 하지만 제가 생각할 때에는 t에 a[i]를 대입하는 과정에서도 a의 값을 읽어와서 i를 더하는 작업이 포함되어 있을 뿐만 아니라 읽어온 a[i]의 값을 t에 대입하는 과정이 추가되기 때문에 a[i]를 그대로 쓸 경우보다 속도가 저하되는 것이 맞지 않을까 싶습니다. 제가 저자보다 초보자이므로 제 판단이 옳았는지 모르겠습니다. 다른 분들은 어떻게 생각하시는지요?

kwonsu의 이미지

:) 님이 하신 말씀을 보고 생각해보건데..
t라는 변수는 a[i]를 대입한것입니다. 그렇다면 그 소스에서 t라는 것이 나온 횟수를 보시면 알겠죠. t = a[i], 이부분을 빼고 t에 있는 자리를 a[i]로 채우면 사용되는 빈도수는 당연히 높아지는 것입니다.
즉 다시 말씀드리자면 t와 a[i]의 수행속도는 누가봐도 t가 빠릅니다.
호줄되는 빈도수는 같을지라도 수행속도 면에서는 당연 t가 빠르다는 것입니다.
그래서 for문 안에 t=a[i] 이 문구를 한번만 넣어주면 밑에서 수행될때는 t에 대한 값만 가지고 실행하게 되지요.. 눈으로 보기에 속도차이는 안나겠지만...

지식의 여인은 옷을 쉽게 벗지 않는다.
잡초인생. 잡초처럼 끈길기게....

모데스티의 이미지

아...저의 오판이었습니다. t가 이중루프의 안쪽루프에서 사용된다는 사실을 간과했네요. 즉 바깥쪽 루프에서 t = a[i]라 한 번만 대입해놓으면 안쪽루프에서는 a[i]대신 t를 써서 속도를 향상시킨다는 의미였더군요. 윗분 답변글 감사합니다.

sliver의 이미지

t를 쓴것과 안쓴것의 차이가 얼마나 나는지 테스트를 해보았습니다.

원래 코드(sort.c):

void insert_sort(int a[], int n) 
    { 
    int i, j, t; 
    for (i = 1; i < n; i++) 
       { 
       t = a[i]; 
       j = i; 
       while (a[j-1] > t && j > 0) /*삽입될 곳을 찾음 */ 
            { 
            a[j] = a[j-1]; /* 뒤로 옮김 */ 
            j--; 
            } 
       a[j] = t; /* 삽입함 */ 
       } 
    } 

int main()
{
        int a[100];
        int i;
        for(i=0;i<100000;i++) {
                int j;
                for(j=0;j<100;j++) {
                        a[j]=100-j;
                }
                insert_sort(a,100);
        }
        return 0;
}

t를 쓰지 않은 코드(sort2.c):

void insert_sort(int a[], int n) 
    { 
    int i, j, t; 
    for (i = 1; i < n; i++) 
       { 
       j = i; 
       while (a[j-1] > a[i] && j > 0) /*삽입될 곳을 찾음 */ 
            { 
            a[j] = a[j-1]; /* 뒤로 옮김 */ 
            j--; 
            } 
       a[j] = a[i]; /* 삽입함 */ 
       } 
    } 



int main()
{
        int a[100];
        int i;
        for(i=0;i<100000;i++) {
                int j;
                for(j=0;j<100;j++) {
                        a[j]=100-j;
                }
                insert_sort(a,100);
        }
        return 0;
}

코드를 보시면 아시겠지만,

역순으로 정렬된 크기 100의 배열을 100000번 루프를 돌며 정렬을 했습니다.

걸린 시간은:

sort.c(gcc sort.c -o sort로 컴파일)
[sliver@ns sliver]$ time ./sort

real 0m16.154s
user 0m12.820s
sys 0m0.160s

sort2.c(gcc sort2.c -o sort2로 컴파일)
[sliver@ns sliver]$ time ./sort2

real 0m1.430s
user 0m0.810s
sys 0m0.030s

엄청난 차이로 sort2(t를 쓰지 않은 코드)가 빠릅니다.

이번에는 -O2 옵션을 주어서 컴파일을 해봤습니다.

sort.c
[sliver@ns sliver]$ time ./sort

real 0m5.892s
user 0m3.440s
sys 0m0.040s

sort2.c
[sliver@ns sliver]$ time ./sort2

real 0m0.288s
user 0m0.190s
sys 0m0.010s

여전히 엄청난 차이가 납니다.

objdump로 역어셈블 결과를 보니

sort.c(원래 코드)의 insert_sort가 sort2.c(t를 쓰지 않은 코드)의 insert_sort보다 약 2 instructions정도 많더군요.

그리고 혹시 main함수가 다르게 컴파일되었나 하고 역어셈블 결과를 비교해 보니 정확히 같았습니다.

근데 이 정도차이로 이렇게 시간차이가 많이나니 참 신기하군요..

그런 정도의 최적화는 그냥 컴파일러에 맡기는게 훨씬 낫다라는 걸 깨달았습니다..ㅎㅎ

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.