[질문]list 관련 질문입니다.

oracle_warden의 이미지

제가 이번에 좀 알아볼 게 있어서 실험 하나를 했는데요..
우선, list1, list2, list3 이 3개가 있을 때, 각각의 크기가, 100, 1000, 10000이라고 놓고,
이 3개의 리스트를 nested loop로 순서를 바꿔서 돌려보았습니다.

첫번째 실험은, 크기가 가장 작은 LIST를 가장 바깥쪽에 놓고 실행 시킨 것이고, 두번째 실험은 반대로, 크기가 가장 작은 LIST를 가장 바깥쪽에 놓고 실행시킨 것입니다.
참고로, linux환경에서 ,gcc로 컴파일 했습니다.
첫번째 실험

temp1 = list1;
while(temp1!= NULL){
                temp2 = list2;
                while(temp2 != NULL){
                           temp3 = list3;
                           while(temp3 != NULL){
                                     temp3 = temp3->next;
                           }
                            temp2 = temp2->next; 
                }
                 temp1 = temp1->next;
}

두번째 실험
temp1 = list3;
while(temp1!= NULL){ 
                temp2 = list2;
                while(temp2 != NULL){
                                temp3 = list1;
                                while(temp3 != NULL){
                                                   temp3 = temp3->next;
                                }
                                 temp2 = temp2->next;
                 }
                 temp1 = temp1->next;
}

그냥 머릿속에 생각하기로는 두 가지가 시간 차이가 거의 없을 것 같았는데, 실제로 돌려보니, 놀랍게도 첫번째 실험은 평균 11초 정도가 걸리고, 두번째 실험은 평균 6초 정도 걸리더군요..
왜 이런 차이가 나는지 모르겠습니다. 고수 분들 가르쳐주세요~~

PS. 제가 짠 소스코드를 첨부해놓겠습니다. 그럼 많은 답변 부탁 드립니다.

File attachments: 
첨부파일 크기
파일 test.c1.49 KB
doldori의 이미지

루프 횟수에서 차이가 나니까요. :)

첫번째 실험
temp1 = temp1->next : 10000
temp2 = temp2->next : 10000 * 1000
temp3 = temp3->next : 10000 * 1000 * 100

두번째 실험
temp1 = temp1->next : 100
temp2 = temp2->next : 100 * 1000
temp3 = temp3->next : 100 * 1000 * 10000

litdream의 이미지

루프 횟수는 같은것 같은데요?

(100 * 1000 * 10000 == 10000 * 1000 * 100)

-------

제가 어줍짢게 추측컨데, 페이징 때문이 아닐까요?
list 의 element 가 얼마나 큰지는 잘 모르겠지만,
링크들을 따라갈때, 제일 안쪽 루프가 100 개인것들보다 10000 개
인 것들이 page fault 가 날 확률이 높아보이네요..
그래서... 그런것이.... 아닐... 까...요?

삽질의 대마왕...

gimmesilver의 이미지

litdream wrote:
루프 횟수는 같은것 같은데요?

(100 * 1000 * 10000 == 10000 * 1000 * 100)

-------

제가 어줍짢게 추측컨데, 페이징 때문이 아닐까요?
list 의 element 가 얼마나 큰지는 잘 모르겠지만,
링크들을 따라갈때, 제일 안쪽 루프가 100 개인것들보다 10000 개
인 것들이 page fault 가 날 확률이 높아보이네요..
그래서... 그런것이.... 아닐... 까...요?

temp3의 loop횟수는 두개가 같지만 temp1과 temp2의 처리 횟수는 틀립니다...
그리고 페이징도 가능성이 있긴 한데...list가 페이징에 크게 영향을 받을까요? 잘모르겠군요...

------------------------
http://agbird.egloos.com

oracle_warden의 이미지

temp3의 loop횟수는 두개가 같지만 temp1과 temp2의 처리 횟수는 틀린 것 은 맞는 거 같은데, 달라 봤자, temp의 loop 횟수에 비해서는 작은 값이잖아요..
그런데 시간이 저렇게 차이가 많이 나는 걸까요? 단순히 루프 횟수로 인해서만 시간 차이가 나는 거 같지는 않은데..

angpoo의 이미지

백만개 안에 10개 루프일때와 10개안에 백만개 루프일때를 비교하면
바깥루프에서 안쪽루프로 갔다 오는 작업이 백만번 발생하느냐 10번발생하느냐의 차이인것 같네요.

그냥 for 0..백만 {for 0..10}으로 비교해도 차이가 확실히 납니다.

ymink의 이미지

정확한 지식을 가지고 말씀드리는 것은 아니지만,
branch prediction과 관계가 있는 것은 아닐까 추측해 봅니다.

첫번째 실험은, 100 짜리 loop를 10000*1000번 한 것이고,
두번째 실험은, 10000 짜리 loop를 100*1000번 한 것입니다.

그래서 첫번째 실험에서는 10000*1000번의 prediction fail이 일어나고,
두번재 실험에서는 100*1000번 prediction fail이 일어나는 것이 아닐까 조심스럼게 추측해 봅니다.
branch prediction이 성공하면, branch에 걸리는 시간은 거의 zero cycle에 가깝고, 실패하면, pipeline을 clear해야 하므로, pipeline의 길이에 비례해서 cycle손해를 보게 됩니다.

조금 다르게 설명해 보면...
1부터 10까지 세는 1*10 짜리 loop와 10*1 짜리 loop를 비교해 봅시다.
전자는 '무궁화꽃이 피었습니다' 놀이를 하듯이
1 2 3 4 5 6 7 8 9 10이라고 재빨리 셀 수 있고,
후자는 하나씩 쉬어 가면서,
1 쉬고 2 쉬고 3 쉬고 4 쉬고 5 쉬고 6 쉬고 7 쉬고 8 쉬고 9 쉬고 10
이라고 세는 셈이죠.
실제로 그런 것인지는 잘 모르겠지만...

그리고, 앞선 분들의 의견에 약간 설명을 덧붙여 보자면...

당연히 가장 안쪽 loop 말고는 looping 방법에 따라 시간의 차이가 있더라도, 이 경우에 대략 계산해 보면, 10%이상 차이가 나는 것을 설명할 수는 없습니다.

그리고, cache 및 cache miss문제라면, 오히려 제일 안쪽 루프가 작은 경우에 cache miss가 훨씬 적거나 (아예 안일어나서) 더 빨라야 합니다. Cache miss가 문제되는 상황이라면, 오히려 첫번째 실험이 더 빨라야 하는데 그런 것도 아니고... 아마도, cache prefetch 때문에 안쪽 loop의 크기가 크더라도 그것이 cache miss를 불러오지는 않을 것입니다.

vuccell의 이미지

{ 가 열릴때마다, 새로운 스택을 정의하고, 생성하는데..
두번째가 스택생성이 더 적어서 그런게 아닐까요?

Xine의 이미지

vuccell wrote:
{ 가 열릴때마다, 새로운 스택을 정의하고, 생성하는데..
두번째가 스택생성이 더 적어서 그런게 아닐까요?

2패스 컴파일을 하는 _일반적인_ 컴파일러의 경우 루프내에서의 지역변수에 대해서도 크기에 대한 예측이 가능하기 때문에 함수의 entry 포인트에서 한번에 스택할당을 하는걸로 알고있었는데, 그렇지 않나요?

--
이덕희

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.