C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
분야별 포럼
C++빌더
델파이
파이어몽키
C/C++
프리파스칼
파이어버드
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

자유게시판
세상 살아가는 이야기들을 나누는 사랑방입니다.
[13508] 무제... (a와 b의 교환에 대하여)
강신영.Divinespear [kang594] 3074 읽음    2007-11-03 00:24
32비트 정수를 담는 변수인 a와 b가 있다고 하자.
a와 b의 값을 바꾸기 위해 흔히 우리는 여분의 32비트 정수를 담는 변수인 c를 필요로 한다.

그렇다면
c를 사용하지 않고 a와 b를 서로 바꿀 수 있을까? 가능하다면 어떻게 해야 할까?



혹시 이 답을 문제를 보자마자 바로 떠올렸는가?

얼마나 시간이 걸렸나?

10초?
30초?
1분?
5분?
30분?
아니면 1시간?


머릿속에서 번개처럼 답이 떠올랐는가?
오래전에 어디선가 보거나 들은 기억을 가까스로 살려냈는가?
아니면 누구에게 물어보거나 책이나 인터넷에서 찾아냈는가?



어쨌든 답을 알고 있거나 알아냈다면 당신은 대단한 사람 중 하나일지도 모른다.
어쨌거나 답은 의외로 쉬우며, 어른들보다 어린이들이 더 빨리 답을 말할 확률이 높을지도 모른다.

(이 질문에 대한 대답은 아래의 글에서 대략적으로 찾을 수 있다.)






그럼 c를 사용하지 않고 a와 b를 서로 바꿀 때 어떠한 제약이 있을까?
메모리는 실제로 얼마나 절약될까?
c를 사용할 때와 그렇지 않을 때의 CPU 클럭 싸이클의 차이는 어떨까?



만약 레지스터에서 직접 조작한다면 어떻게 될까? (이 경우 a와 b는 보통 EAX와 EDX가 될 것이다. c는 아마 EBX일 것이고..)
레지스터를 직접 조작할 때 위에서 제기된 제약을 피해갈 수 있을까?
피할 수 있다면 그걸 피하는게 쉬울까? 아니면 어려울까?
CPU 클럭 싸이클은 c를 사용할 때와 그렇지 않을 때 어디에 더 유리할까?



11월의 어느 밤에 피로한 상태에서 따뜻한 커피 한잔에 초콜릿 한조각을 음미하며
블로그에 횡설수설을 늘어놓다....


----------------------------------------------------------------------------

혹시나 태클 걸거 있으시면 팍팍 걸어주시기 바랍니다. (백태클은 사절!)

퍼가는건 물론 자유지요. 출처만 학실하게 해주시면 됩니다 ^^
원본은 http://blog.naver.com/kang594/43761012 에 올려두었습니다.
nicekr.황경록 [mpbox]   2007-11-03 04:13 X
x ^= y ^= x ^= y;

- -?
아제나 [azena]   2007-11-03 18:19 X
위의 글이 가능한가요? 1분 생각해봤지만 불가능할거 같은데요 ㅎㅎ
되더라도 데이터는 스택이라던가 어딘가에 들어갔다 나오는거겠죠;;;
김도완 [purplecofe2]   2007-11-03 18:32 X
재미있는 결과를 트랙백시켰습니다. -0-;
쎄미(진창훈) [susemi99]   2007-11-03 20:19 X
a=5
b=3

a=a+b => a=8
b=a-b => b=5
a=a-b => a=3

대충 이러면 되긴 되나요?
쎄미(진창훈) [susemi99]   2007-11-03 20:22 X
a=-10
b=3

a=a+b => a=-7
b=a-b => b=-10
a=a-b => a=-17

절대값으로 계산해야 할까요?
장성호 [nasilso]   2007-11-04 00:03 X
a=-10
b=3

a=a+b => a=-7
b=a-b => b=-10
a=a-b => a=a-b=(-7) - (-10) = -7 +10 = 3   ==> 이렇게 되는것 아닌가요?
장성호 [nasilso]   2007-11-04 00:33 X
x ^= y ^= x ^= y;  에 대해..

위식을 맨뒤부터 하나씩 풀어보면?

1식.   x = x^y ;
2식.   y = y^(1식) = y^(x^y) = y^x^y ; // 여기서 y=x 가 되죠. 왜냐면 XOR두번하면 윈래값으로 되니까
3식.   x = 1식 ^ 2식 = (x^y)^ (y^x^y) =( x^y)^x = y ; 

결국 x와 y값은 swap되죠..

참고
http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tip&no=477
허정주 [tinydew4]   2007-11-04 03:12 X
XOR 연산법은 프세 2002년 8월호 부록에 소개된 방법이죠.
정수외에 CHAR 형도 Swap 이 가능한 방법이죠.
아제나 [azena]   2007-11-04 10:24 X
오호라 저런 방법이 있군요 ㅋ
머리의 한계군요. XOR 2번하면 원래 값이 되는 것은 알고 있지만 아직도 이해가 잘 안간다는... ㅡㅡ+
아제나 [azena]   2007-11-04 11:17 X
머리가 나쁘니 몸으로라도 뛰어야겠죠 ㅎㅎ
실제로 두가지 알고리즘을 가지고 속도를 비교해 보았습니다.
폼에 메모와 버튼만 배치하시고 아래 소스를 돌리면 됩니다.
#include "mmsystem.h"
#define SWAP(a,b)  {(a)^=(b)^=(a)^=(b);}
#define SWAP2(a,b) {int swaptemp=(a);(a)=(b);(b)=swaptemp;}
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    int startTime[2];
    int endTime[2];

    int swapA=1, swapB=2;

    unsigned int loop;

    unsigned int maxLoop=400000000;

    startTime[0] = timeGetTime();

    for( loop=0 ; loop<maxLoop ; loop++ )
        SWAP(swapA,swapB);

    endTime[0] = timeGetTime();

    startTime[1] = timeGetTime();

    for( loop=0 ; loop<maxLoop ; loop++ )
        SWAP2(swapA,swapB);

    endTime[1] = timeGetTime();

    Memo1->Lines->Add( "XOR SWAP 결과" );
    Memo1->Lines->Add( endTime[0]-startTime[0] );
    Memo1->Lines->Add( "STACK SWAP 결과" );
    Memo1->Lines->Add( endTime[1]-startTime[1] );
}
결과는??? 음.. 릴리즈 모드에선 별 차이 없는데 디버그 모드에선 압승이군요;;;
김도완 [purplecofe2]   2007-11-04 15:59 X
레지스터 스왑이 아니라면 의미가 없더군요. -_-;
조상진 [mauri]   2007-11-05 09:44 X
음.. 예전에 KLDP에서 이 내용으로 논란이 있었던 것으로 기억합니다만.... ^^;;;;
이러한 주제를 가지고 너무 깊게 생각하실 필요는 없다고 봅니다.

예전에도 한참 시끄러웠었지만 결국 이말 한마디에 모두 KO였습니다.

정작 중요한 로직이나 알고리즘은 X판으로 짜면서 이런거나 for(;;)냐 while(1)이냐 같은 시스템 전체 성능으로 보면 영향이 아예 없다시피한 것에만 광신적으로 매달린다 였는데요.

고해상도 카운터를 이용한 테스트 입니다.
아제나님이 테스트 하신 스왑1, 2의 디버그, 릴리즈 테스트 결과입니다.

Swap1이 x ^= y ^= x ^= y
Swap2가 int temp 를 이용한 방식으로 각각 만번씩 루프롤 돌렸습니다.

(릴리즈) -----------------
[Swap1] time is = 0.00001369 sec
[Swap2] time is = 0.00000950 sec

[Swap2] time is = 0.00000950 sec
[Swap1] time is = 0.00001369 sec

[Swap1] time is = 0.00001369 sec
[Swap2] time is = 0.00000950 sec

[Swap2] time is = 0.00000978 sec
[Swap1] time is = 0.00001369 sec

(디버그)-------------------------
[Swap1] time is = 0.00008716 sec
[Swap2] time is = 0.00004274 sec

[Swap2] time is = 0.00004274 sec
[Swap1] time is = 0.00008716 sec

[Swap1] time is = 0.00009638 sec
[Swap2] time is = 0.00004218 sec

[Swap2] time is = 0.00004218 sec
[Swap1] time is = 0.00008716 sec


어떠신가요? 굉장히 고효율을 보일듯 하지만 최고와 최저 성능의 차이는 10만분의 4초 차이입니다.

속도로는 오히려 x ^= y ^= x ^= y 이 방식이 효율이 나쁩니다.

나는 10만분의 4초를 느낄수 있고, 신경쓰여! 라는 분이 계신다면 모를까.;;
이건 역시 재미일 뿐 의미가 없다고 봅니다...;;
조상진 [mauri]   2007-11-05 10:04 X
뭐.. 장치제어에서 한정된 자원으로 4바이트를 아끼기위해(물론 속도는 포기하면서) 이걸 사용한다면 모를까.. 과연 이러한 방식이 필요한곳이 어디일까요..ㅡㅡ???

제 생각입니다만.. 이걸 안다고 해서 대단한 사람도 아니고 모른다고 해서 안대단한(?) 사람이 되는 것도 아니라고 생각합니다.

이건 뭐 마치 일본 방송에서본 밥짓기 명인이 하는 소리랑 똑같습니다.
밥지을때 물을 먼저 넣고 그다음에 쌀을 넣어야 맛이 있지, 쌀을 넣고 물을 넣어 씻으면 맛이 없다고 하는데..

다들 거기서 "오오오~~ 대단하다. 그런 비밀이~!!"라고 탄성들을 외치는데..ㅡㅡ;
그명인 잡아다가 저 2가지 경우 밥지어놓고 구분하는지 못하는지 시켜보고 싶더군요. ㅡㅡ;
강신영.Divinespear [kang594]   2007-11-05 10:54 X
조상진 //
매우 따끔한 태클이군요.... 흐흐
추가로 설명하자면 대단하다는 의미는 개념파괴 측면에서 이야기 한거였습니다.

김도완 //
시간내서 엄청난 삽질을 대신 해주셔서 감사합니다. (꾸벅)
마침 시간도 잘 안나서 말이죠...흐흐
사실은 제가 좀 귀찮아서... ㅡ_ㅡa

그 외에 다른 분들 //
참여하고 즐겨주셔서 감사합니다.
크레브 [kkol]   2007-11-05 11:54 X
사실 몰랐던 내용이지만.. ^^;
그리 알고 싶은 내용도 아니었습니다.
개발일을 어느정도 했던 사람이라면.. 알아봤자 크게 도움이 될만한 내용은 아니라는것을 금방 짐작할 수 있었을 것입니다.
심심풀이로 올리신것같은데 과민 반응 보이실 필요는 없을것 같은데요.
그래도 리플 올라온거 보니.. 재밌네요.. ㅎㅎ
남병철.레조 [lezo]   2007-11-05 13:34 X
캬~ 내용도 재밌지만 경계하는 마음까지 담아내는 볼포 게시판의 위력...
학생과 직장인이 함께 숨쉬는 공간만 좀 더 갖추어 진다면 더 멋지고 활력 넘치는 게시판이 되리라 봅니다. ㅎㅎ

소자 단위에서는 if문 역시 오류를 발생시킬 확률이 있다는 내용을 CPU 설계 시간에 했었는데 ㅋ.. 그 수업을 않듣고 게임 프로그래밍 수업을 들었었네요 ㅠ.ㅠ
지금 생각하면 아쉽습니다. ㅎㅎ

이런 글이 종종 올라오는것이 좋아 보입니다.
볼포는 아직 자게 말고는 편히 이야기할 곳이 마땅치 않기에 좀 아쉽지만.. ㅎㅎ
조상진 [mauri]   2007-11-05 15:52 X
강신영.Divinespear님//
KLDP에서 대략 한 3~4년 전쯤 논란이 됬던글을 다시 보게되서 허걱? 했습니다.. ;;

그리고 쓴김에 한말씀 더 드리자면..

물론 다른 분들에게 동기부여가 되고, "아.. 해보니 별차이 없구나"라는걸 직접 해보게 만드는 의도도 좋습니다만..

---------------------------------------------------------------------------
그럼 c를 사용하지 않고 a와 b를 서로 바꿀 때 어떠한 제약이 있을까?
메모리는 실제로 얼마나 절약될까?
c를 사용할 때와 그렇지 않을 때의 CPU 클럭 싸이클의 차이는 어떨까?
만약 레지스터에서 직접 조작한다면 어떻게 될까? (이 경우 a와 b는 보통 EAX와 EDX가 될 것이다. c는 아마 EBX일 것이고..)
레지스터를 직접 조작할 때 위에서 제기된 제약을 피해갈 수 있을까?
피할 수 있다면 그걸 피하는게 쉬울까? 아니면 어려울까?
CPU 클럭 싸이클은 c를 사용할 때와 그렇지 않을 때 어디에 더 유리할까?
---------------------------------------------------------------------------

이러한 내용을 장황하게 써 놓으시려면 시간이 안나셔도 직접 해 테스트와 분석을 해보신 후에 문제제기를 하시는 편이 더 좋지 않을까 싶습니다.

글을 보면 "당신들이 알지 못하던 대단한 사실이 숨겨져 있다"라고 보입니다만..;
실제로 해보니 한번당 십억분의 4초가 오히려 더 "느리다"면 굉장히 실망들 하시지 않을까요?

게다가 글만 읽고서 리플을 보시지 않은 분들이 막연히 "아~ 이런 멋진 방법이~"라고 계속 생각하고 계실지도 모릅니다.. ;;
아제나 [azena]   2007-11-06 00:24 X
기가메모리 시대에 4바이트를 아끼자고 저렇게 하는게 우습긴 하지요 ^^
하지만 저처럼 내용을 모르는 사람도 있었으니까 글쓴님의 글을 폄하하고 싶은 뜻도 없네요.
제가 테스트 결과를 공개 안한 것도 그런 이유에서 였지요.
해보니까 XOR이 더 느렸거든요;;;
인류의 과학의 발전이 전쟁을 통해서 이루어 졌듯이 항상 똑같은 일상에선 자기 발전을 얻을 수 없는 것 아닐까요... 좋은 글 감사합니다.

+ -

관련 글 리스트
13508 무제... (a와 b의 교환에 대하여) 강신영.Divinespear 3074 2007/11/03
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.