2013-10-11 1 views
2

컴퓨터 시스템 : 프로그래머의 관점, 그리고 Macbook Pro에서 제공하는 코드를 Intel Core i7과 함께 실행하려고합니다. .학습을위한 환경 설정 "컴퓨터 시스템 : 프로그래머의 시각 *"

그러나 일부 코드는 책의 제안대로 정확하게 실행되지 않습니다.

이 C 예제는 레지스터에 저장 될 때부터 메모리에 저장 될 때 동일한 부동 소수점이 다를 것임을 보여줍니다.

#include<stdio.h> 

double recip(int denom) 
{ 
    return 1.0/(double) denom; 
} 

void do_nothing(){} /* to clear the register */ 

void fcomp(int denom) 
{ 
    double r1, r2; 
    int t1, t2; 

    r1 = recip(denom); /* stored in memory */ 
    r2 = recip(denom); /* stored in register */ 
    t1 = r1 == r2;  /* Compares register to memory */ 
    do_nothing();  /* Forces register save to memory */ 
    t2 = r1 == r2;  /* Compares memory to memory */ 
    printf("test1 t1: r1 %f %c= r2 %f\n", r1, t1 ? '=' : '!', r2); 
    printf("test1 t1: r2 %f %c= r2 %f\n", r1, t2 ? '=' : '!', r2); 
} 

main(){ 
    int demon = 10; 
    fcomp(demon); 
} 

이 책에서 제안 "O2"옵션, 결과,와 GCC와 비교해야한다 :

test1 t1: r1 0.100000 != r2 0.100000 
test2 t1: r1 0.100000 == r2 0.100000 

는 그러나, 나는이 "=="의를 가지고 왜 궁금해. 책의 환경 설정에 대한 제안 사항이 있습니까? 고마워.

+0

직사광선이 비치는 건조한 책상 위에 책을 보관해야합니다 ... –

+4

중간에 괜찮은 컴파일러는 do_nothing() 호출이 아무 것도하지 않으며 단순히 코드를 내 보내지 않는다는 것을 증명할 수 있습니다. 이 컴파일러는 우연히'r1'과'r2'가 동일한 값을 가져야하고 할당을 최적화하고'printf()'호출에서 삼항 연산자를 바로''= '' '. 또한, 코드에 레지스터에 관한 것이 전혀 없으므로 레지스터에 저장된 값에 대한 가정은 전혀 부인할 수 없습니다. –

+0

뭔가 잘못되었습니다. 이 책은 유명한 사람인 Randal Bryant가 썼습니다. 이 책의 일부는 온라인입니다. 코드 스 니펫이 책에있는 내용인지 확인하십시오. 장, 섹션 및 페이지는 무엇입니까? –

답변

1

인텔 CPU의 x87 FPU의 특정 속성을 목표로합니다 (대부분) :이 FPU 유형의 주요 속성은 (보이는) 80 비트 정밀도의 레지스터 만 제공한다는 것입니다. 따라서 32 또는 64 비트 부동 소수점은 FPU 레지스터에로드 될 때 80 비트 부동 소수점으로 변환됩니다. 더욱이, 통상적으로 산술 연산은 완전한 정밀도로 수행되기 때문에, 나중에 사용하기 위해 FPU 레지스터에 값이 유지되면, 메모리에 복사되어로드 된 값에 대해 수행되는 것처럼 32 또는 64 비트로 반올림되지 않습니다 나중에 다시. 이 때문에 값이 레지스터에 유지되는지 여부가 달라집니다.

그러나 MacBook X (Macbook에서 사용하고 있다고 가정)는 x87 FPU를 사용하지 않으며 SSE 장치를 사용합니다. SSE는 32 비트 및 64 비트 부동 소수점 레지스터와 연산을 제공하므로 no 값이 레지스터에 보관되거나 정밀도와 관련하여 메모리에 저장되는 경우의 차이입니다. 결과는 각 작업 후에 항상 반올림됩니다. 이것은 Windows 및 Linux의 64 비트 익스텐트에 일반적으로 적용됩니다.

예 : 32 비트, 리눅스 또는 Windows 상황이 다릅니다.x87 또는 SSE 장치의 사용은 환경에 따라 다르며, 32 비트 시스템이 SSE2 지침을 지원하지 않을 수 있기 때문에 종종 x87 FPU가 사용됩니다. SSE2가없는 마지막 CPU는 약 10 년 전에 구축되었습니다.

+0

+1 이것은 내 [비 응답]에 대해 경험적으로 발견 한 행동에 대한 훌륭한 설명입니다. (http://stackoverflow.com/questions/19308894/environment-settings-needed-for-learning-computer-systemsa-programmers -pers/19323829 # 19323829) –

0

답이별로 없지만 조금 연구했습니다. 이 책은 fcomp.c http://csapp.cs.cmu.edu/public/1e/ics/code/data/fcomp.c으로, 책의 동일한 예에서 나온 것 같지만 귀하의 버전에는 첫 번째 테스트가 포함되어 있습니다. 어쨌든 나는 다양한 gcc 버전과 -m32 대 -m64를 사용하여 test1 (테스트와 동일)이 적어도 i386 및 x86_64에 대해 항상 동일하게 나타남을 발견했습니다. 내가 할 gcc -m64 -o fcomp fcomp.c로 컴파일 할 때 (10의 악마로 호출 TEST2())

void test2(int denom) 
{ 
    double r1; 
    int t1; 
    r1 = recip(denom);    /* Default: register, Forced store: memory */ 
    t1 = r1 == 1.0/(double) denom; /* Compares register or memory to register */ 
    printf("test2 t1: r1 %f %c= 1.0/10.0\n", r1, t1 ? '=' : '!'); 
    printf("A long double on this machine requires %d bytes\n", sizeof(long double)); 
} 

:

그러나 구조에 의존하는 동작을 보이는 것 같다 하나 개의 테스트 (TEST2)가 이 출력 :

test2 t1: r1 0.100000 == 1.0/10.0 
A long double on this machine requires 16 bytes 

gcc -m32 -o fcomp fcomp.c로 컴파일 할 때 반면에 나는이 출력을 얻을 :

,
test2 t1: r1 0.100000 != 1.0/10.0 
A long double on this machine requires 12 bytes 

레코드의 경우 gcc 3.4.6 및 4.1.2를 사용하여 결과를 얻었습니다.

내가 사용하는 컴파일러/아치에 관계없이 모든 다른 테스트가 동일하게 나타납니다.

+0

-O 옵션을 사용하는 것을 잊었습니다. 모든 테스트는 -O 옵션과 관계없이 x86_64로 전달됩니다. 그러나 i386의 경우 -O0 test2는 실패합니다. -O1 test4 t1 및 t2는 실패하고 -O2는 모든 테스트를 통과합니다. –