VC++ 컴파일러가 최적화된 코드를 만들도록 하는 의사코드는?
글쓴이: sjpark / 작성시간: 금, 2007/07/20 - 9:44오전
GCC의 경우, 컴파일 의사 코드를 통해 컴파일러에게 , 이 코드는 이렇게 생성해라 라고 조작할 수 있는 것으로 알고 있습니다.
실 예로는, 예전 커널에서 jiffies 값을 증가시키기 위해 쓰는 방법이 있었습니다.
실제로 VC++ 에서도 저런 코드가 있나요?
int var=0; var ++;
위 코드를 컴파일하면,
레지스터로 var 값을 옮기고, 레지스터의 값에 1 을 더하고, 다시 레지스터를 메모리로 옮기는 과정을 거쳐 var++ 라는 코드를 해석하고 있었습니다.
하지만, 이 방법 대신 inc var 라는 명령 하나로 해석되게 할 수 있는 방법은 없나요?
또, 저렇게 레지스터에 옮기는 작업과 add 명령을 사용하는 것과 inc 명령으로 메모리상의 값 자체를 바로 1 증가시키는 것중,
성능상 어떤것이 더 효율이 높은가요?
예를들어, 메모리 연산자체는 레지스터와는 상대적으로 많은 클럭 연산을 필요로 하기 때문에, 더 느려질수 있다라든지.. 말이죠..
감사합니다.
Forums:
질문에 답이
질문에 답이 들어있네요 좀더 부가설명하면 학부과정의 computer architecture수업을 들으면 다나오는 내용이고 충분히 인터넷에서도 찾아볼수 있는 내용이 되겠습니다.
기술이 발전함에 따라 cpu clock speed는 증가하는데 메모리쪽의 속도는 상대적으로 발전이 느려서 둘간의 차이가 많이 난다고 하는데 요즘 cpu에 따라서 틀리겠지만 일반적으로 레지스터를 조작하는 명령은 1cycle을 소모한다고 했을때 memory read operation는
50 cycle 정도를 필요로 합니다. 현재 컴퓨터 구조상 메모리상에서 산술연산을 직접수행하지는 못하기 때문에 산술연산을 하기위해서는 메모리에서 레지스터로 값을 읽어들인 후 산술연산을 하고 그 결과를 해당 메모리에 쓴다고 할때 대충 계산해봐도 50+1+50정도의 사이클이 소모되야겠네요.
암튼 컴퓨터구조상 메모리에서 직접 산술연산을 할수는 없고 메모리 read/write연산에서의 시간이 상대적으로 너무 오래걸린다 정도가 답이 될 수 있겠네요.
흠..
학부과정에서 나오는 컴퓨터 구조 수업은 저도 들었습니다.
실제로 산술 연산 명령들이 내부적으로 메모리와 어떤 과정을 거쳐 산술 연산을 수행하는지는 모르겠으나, 현재는 메모리값을 오퍼런드로 지정해줄 수 있습니다. (컴퓨터 구조 교과서에 나오는 것은 ALU자체가 레지스터만을 보고 연산을 수행하고 있는 매우 기본적인 구조를 설명하고 있지요)
gcc 를 사용하는 경우, 컴파일러에게 적절한 의사코드를 이용해, 개발자의 의도를 전달해줌으로 하여, 레지스터에 값을 옮긴 후, 1 증가시키고 그 값을 다시 메모리에 써넣는 대신, 메모리의 값을 바로 inc 명령으로 증가시키는 코드를 만들어 주고 있습니다.
명시적으로 생성되는 명령어들을 보면, 확실히 그 명령의 수가 줄어들기에, 혹시나 성능에도 영향을 주지 않을까 해서 이 방법을 찾는 것입니다.
해당 의사코드는 다행히, 많이 알려져서 쉽게 찾아 쓸 수 있지만, 이는 GCC에 한정된 코드였습니다.
VC++에서는 (VC6.0물론 오래전에 나온 것이라 그럴지도 모르지만) 그런 코드를 만들어 내도록 의도적으로 코딩하는 방법이 없나 하는 것이 제가 궁금해 하는 것이었습니다.
감사합니다.
http://nicesj.com
https://nicesj.com
https://blog.nicesj.com
아래와 같은 코드일
아래와 같은 코드일 경우
int var = 0;
read only 영역에 0 이라는 값을 넣어두고, 그 값을 읽어서 레지스터로 올리는 것보다는 레지스터에서 xor eax, eax 식으로 구현하는 것이 훨씬 빠릅니다.
제가 컴파일러 시간에 배운 바로 위와 같은 코드를 optimize 하는 것을 Constant Propagation 이라고 부르며 int var = 1 식으로 최적화 되는 걸로 알고 있습니다.
어셈블리로 프로그램을 짜봤을 때의 경험으로는 load eax, [constant_1] 식의 코드보다 xor eax, eax; inc eax 식이 더 빠를 수도 있었던 것 같은데 뭐가 옳다고 쉽게 얘기드릴 수가 없네요. (cache 가 hit 되느냐 마느냐의 차이로 결과가 뒤집힐 수도 있어서...)
--
오랫동안 꿈을 그리는 사람은 그 꿈을 닮아간다...
http://mytears.org ~(~_~)~
나 한줄기 바람처럼..
오랫동안 꿈을 그리는 사람은 그 꿈을 닮아간다...
http://mytears.org ~(~_~)~
나 한줄기 바람처럼..
다른 분들은 어떻게
다른 분들은 어떻게 하는 지는 모르겠지만 그냥 저런 게 필요한 경우는 AtomicIncrease (맞나? AtomicXXX 연산들)을 썼었습니다.
저는 주로 VC6.0
저는 주로 VC6.0 사용해왔는데, 저정도의 요구사항이 있는 코드를 작성해 본 적이 없어서 그런지 본적이 없는 것 같으네요.
gcc에서는 어떤 식으로 하는지 궁금하네요. 코드 한번 적어주시면 감사하겠습니다.
글고 inc 인스트럭션의 경우에는 operand가 되는 주소를 구하는 인스트럭션도 고려해야 되지 않나요?
로컬 변수라면 스택 레지스터랑 오프셋 더하기를 해줘야 주소를 구할 수 있잖아요.
inc 인스트럭션이 indirect 주소 지정이 가능한지 모르겠네요.(기계어랑 정말 안 친해서리, 요즘 친해질라고 노력중이랍니다.)
전역 변수의 경우라면.. 음 모르겠네요.
세그먼트 레지스터랑 오프셋 이렇게 하는 지. 아니면 그냥 주소가 딱 결정되어 버리는지 모르겟네요.
최적화 문제는 항상 모르는 게 많다는 것만 새삼 느끼게 해주네요.
각 경우 어셈블러로 다 적어주시면 좋겠네요. 그러면 좀 더 판단하기에 좋을 듯.
댓글 달기