본문 바로가기
시스템프로그램

[컴퓨터구조개론] 5. Floating Point Arithmetic

by 케찹이 2020. 10. 20.

Floating Point Number Encoding(IEEE 754 Standard)

Floating Point

실수는 아주 큰 숫자 또는 아주 작은 숫자도 포함한다.

-2.34 * 10^56(normalized)

+0.002 * 10^-4(not normalized)

+987.02 * 10^9(not normalized)

위와 같은 표현을 scientific notation이라고 한다. 소수점 앞에 한자리수만 존재하고 0이 아니면 그걸 normalized 그렇지 못하면 not normalized라고 한다.

이진법에서는 +-1.xxxxxx * 2^yyyyy와 같이 표시된다. 중요한건 우리는 xxxxxyyyy정도 그리고 signrestore하면 된다 그러면 이 숫자를 읽어올 수 있다.

 

Floating Point Standard

Defined by IEEE Std 754-1985, 예전에는 각 회사마다 standard가 있어서 호환성 문제가 있었다. 요즘에는 다 IEEE std를 사용하여 통일시켰다. standard defined two kinds of precision level. Single precision(32비트)(.float in c), double precision(64비트) (.double in c)

 

IEEE Floating-Point Format

실수를 저장하기 위해서 3가지가 필요한데 첫번째는 sign이다. Exponentxxxxx를 뜻하는 부분이다. Fractionyyyy부분이다 fraction의 다른 이름은 mantisa이다.

Single precision mode에서는 exponent8비트 fraction23비트이다.

Double precision mode에서는 exponent11비트 fraction52비트이다.

위의 값들을 잘 알고 있다면 이 값을 쉽게 알 수 있다.

X= (-1)^s * (1+Fraction) * 2^(Exponent-Bias)

Fraction1을 더한 이유는 우리가 소수점 이하부분만 기록하였기 때문에 잊고있었던 정수부분을 추가해준 것이다.

Bias는 뭐일까. Biasexponent의 크기에 의해 정해진다. Exponent8비트이면 bias2^7 -1이다. 이는 exponent의 값의 범위이기도 하다. 우리가 exponent을 저장할 때 실제로는 bias값과 exponent의 합을 저장하게 된다. bias더하면 실제의 음수를 저장하지 않고서도 음수라는 것을 표현할 수 있다. 어쩔때 exponentexcess representation이라고 하기도 한다.

 

Single Precision Range

일단 exponents 00000000 11111111은 제한이 되어 있다. 그래서 활용가능한 부분은 0000001~11111110까지이다.

가장 작은 값은 exponent00000001일때이고 actual exponent-126이다. 그럼 exponent의 필드는 2^-126이 된다. Fraction은 모두 0이다 fraction에서는 1이 생략되었으니 significand1.0이다. 결국 가장 작은 값은 1.000 * 2^126 (1.2*10^38)이 된다

가장 큰 값은 exponent11111110일 때이다. 가장 큰 exponent254-127=127이 된다. Exponent의 필드는 2^127이다. Fraction 1111..11이다. 표현할 수 있는 가장 큰 값은 2.0*2^127이 된다. 이는 3.4*10^28이다.

 

Double-Precision Range

Single precision과 비슷하다.

Smallest valued actual exponent-1022이여서 1.0*2^1022 (2.2*10^-308)가 된다.

Largest valueactual exponent1023, 2.0 * 2^1023(1.8*10^308)이 된다.

 

Floating-Point Precision

실수넘버의 precision이라고 하면 결국 중요한 비트를 의미한다. 실수변수는 relative precision을 가지고 있다. 얼마나 크든 얼마나 작든 number of effective digits는 같다.

실수에서 significant base 23 bits. 우리 모두 1 point zero omit one in front of msb of the significand bit. MSB of the significand field has the weight of 2^-1. 23비트의 LSB2^23 weight을 가지게 된다. 그래서 number of effective digit in binary23. 이를 decimal로 바꾸면 6 decimal digits이다.

더블에서는 16 decimal digits of precision. 이게 normalized form이다. Order of actual valueexponent fiel에 의해 결정이 된다. 그래서 숫자가 얼마나 크던 똑 같은 precision을 같게 된다.

 

Floating-Point Example

Represent -0.75

-0.75=(-1)^1 * 1.1 * 2^-1

Normalized form이고 s1이다. Fraction = 1000..00 exponent = -1 + Bias

Single: 101111110000…00

Double: 10111111111101000…00

 

Convert binary floating point value to decimal

1 10000001 01000..00

S=1

Fraction = 01000..00

Exponent = 10000001 = 129

X=(-1)^1 * (1+01)*2^(129-127)

 =(-1)*1.25*2^2

 -5.0

 

Denormal Numbers

Exponent가 모두 0일 때 새로운 방식으로 interprete하게 된다. 이때는 fraction1을 더하지 않고 1-bias(-126)가 된다

Smallest value than normal numbers 이 숫자는 1.00000 * 2^126이다. 가장 큰 수는 0.11111 * 2^-126이다. 점차 숫자가 작아지는 것을 볼 수 있다. 이는 0과 근사해진다고 할 수 있다. 가장 작은 denormalized value+-0.0.

 

Infinities and NaNs

Exponent가 모두 1일이고 fraction이 모두 0일 때 값은 +,-무한대라고 한다. 한번 값이 무한대로 결정이 되면 계속해서 무한대가 된다. 무한대에 어떤 값을 더하거나 빼도 무한대이기 때문

Exponent가 모두 1이고 fraction이 모두 0이 아니면 Not-a-Number(NaN)이 된다. 이를 printf하면 NaN이 출력된다.

 

A Summary of IEEE 754 FP Standard Encoding

 

 

Floating Point Arithmetic

Floating-Point Addition

우리가 9.999*10^1 + 1.610 * 10^-1을 계산한다고 할 때 먼저 봐야할 것은 10power이다. 여기서 10power가 다르기 때문에 같은 power를 갖도록한다.

1.     Align decimal points 9.999 * 10^1 + 0.016*10^1 

2.     Add significands 9.999 * 10^1 + 0.016*10^1 = 10.015 * 10^1

3.     Normalize result and check for over/underflow 1.0015 * 10^2

4.     Round and renormalized if necessary 1.002*10^2 effective digit4개라고 고려

잘 이 단계를 살펴본다면 roundingnormalized form break할 수도 있다. 예를 들어 9.002가 되면 rounding을 하여 10.002가 된다. 이건 normalized form이 아니기 때문에 다시 normalized해야 한다. 그래서 effective number가 바뀔 수도 있다. 그래서 step34가 계속 반복될 수도 있다. 이 과정에서 effective form이 많이 차이가 나지 않도록 조정해야한다.

 

이번에는 4-digit binary예시이다.

1.000*2^01+-1.110*2^-2(0.5+ -0.4375)를 계산한다고 하자

1. 1.000 * 2^-1 + -0.111 * 2^-1

2. 1.000 * 2^-1 + 0.111 * 2^-1 = 0.001 * 2^-1

3. 1.000 * 2^-4 no overflow

4. 1.000 * 2^-4 = 0.0625

 

FP Adder Hardware

실수 adder는 정수 adder보다 더욱 복잡하다. 한 사이클에 끝낼려면 엄청 오래걸린다. 왜냐하면 복잡한 회로는 긴 clock cycle이 필요하기 때문이다. 그래서 in modern cpu, fp adder usually takes multiple stages/cycles. Intel에서 fp add를 실행하면 6clock cycle정도 걸린다. Pipelining을 하면서 fp adder작업을 빨리하게 되었다.

 

Step11~2clock에 끝난다. Step2,step3,step4각각 1clock이 걸린다.

 

Floating-Point Multiplication

1.110 * 10^10 * 9.200 * 10^-5

1. Add exponents 10+ -5 = 5

2. Multiply significands 1.110 * 9.200 = 10.212 -> 10.212 * 10^5

3. Normalize result & check for over/underflow 1.0212 * 10^6

4. Round and renormalize if necessary 1.021 * 10^6

5. Determine sign of result from signs of operands +-1.021 * 10^6

 

Binary example

1.000*2^-1 * -1.110 * 2^-2(0.5*-0.4375)

1. unbiased: -1 + -2 = -3    biased: (-1+127) + (-2 +127) = -3 + 127

2. 1.000*1.110 = 1.1102 -> 1.110*2^-3

3. 1.110*2^-3

4. same

5. -1.110 * 2^-3 = -0.21875

 

FP Arithmetic Hardware

FP adder와 복잡도가 비슷함. FP arithmetic hardware는 덧셈, 뺄셈, 곱하기, 나누기 같이 사용할 수도 있다. FP arithmetic hardware fpinteger conversion할 수 있게 지원해준다.

이러한 기능들은 여러 cycle이 필요하다. 하지만 pipelining으로 속도를 빠르게 해줄 수 있다. 여러개의 반복적인 기능을 요구하면 속도를 빨라지게 할 수 있지만 다양한 기능을 사용했을 때는 효율적이지 않을 수도 있다.

 

FP Instructions in MIPS

Fp unit is Implemented in coprocessor1. Coprocessor1 MIPS에서 실수 instruction을 지원해준다. 처음에 MIPS에서 cpu밖에 없어서 fp instruction지원을 해주지 않았다.

FP 레지스터들은 coprocessor에 따로 지정되어 있다. 32 single-precision: $f0~$f31. 각 레지스터 32비트만큼 길고 각 레지스터는 하나의 single precision point number를 저장할 수 있다.

더블 precision은 어떻게 저장될까. paired된다. $f0/$f1이 페어할 수 있고 $f2/$f3가 페어가 될 수 있다. 페어는 하나의 double precision floating point number를 저장 할 수 있다. MIPS ISA32 * 64비트 FP 레지스터를 지원한다. 이때는 페어가 필요없다.

Fp instructions operate only on FP registers

Fp load and store instructions

Lwc1, ldc1, swc1, sdc1    #w가 있으면 single precision, c1

-ldc1 $f8, 32($sp)           #레지스터 name은 반드시 fp 레지스터여야 한다.

 

Single-precision arithmetic

Add.s, sub.s, mul.s, div.s

Double-precision arithmetic         double operation에는 페어의 첫번째 레지스터가 페어를 대표하게 된다.

Add.d, sub.d, mul.d, div.d

Single-and double-precision comparision

c.xx.s, c.xx.d(xx is eq, neq, lt, le, gt, ge)       coprocessor에 있는 특별한 flag이다.

Sets or clears FP condition-code bit

Bracn on FP condition code true or false

Bc1t, bc1t

Ex) Bc1t TargetLabel       #Flagclear일 때 점프를 한다.

 

Accurate Arithmetic(rounding방법에 대해서…)

1,001이 있을 때 3efficinet만 필요하면 1rounding 해주어야한다. 1 rounding에서 extra digit이다. IEEE에서 arithmetic hardware must have extra bit to use in rounding shcheme. 처음 extra비트는 guard비트 그다음은 round비트 그 다음은 sticky비트라고 한다.

0.1가 있을 때 오른쪽으로 shift하면 0.01이다. 우리가 소수점 두개만 저장가능하다고 하자. 그리고 다시 오른쪽으로 shift하면 1은 저장가능한 공간에서 빠져나가게 된다. 이때 우리는 round를 해주어야 하고 1guard비트이다. 다시 right shift를 한번에 두번 할 때 guard bit1, round 비트는 1이다. 라운딩 스킴은 guard비트를 먼저 볼 것이다. 0이면 round schemeround down을 시킨다. 1이면 0.0010 0.01 0.00사이에 있는 것이다. 이런 상황(0.0010)tie case 라고 한다. 근데 round비트가 1이면 tie case가 아니다. 왜냐하면 0.00110.01에 조금 더 가까이 있어서 round up이 된다. sticky비트는 extension of round비트라고 생각하면 된다. 0.00101이 있을 때 0.01에 가까운데 sticky비트는 round비트 다음에 하나의 digit라고 1이 있으면 sticky비트는 1이다. 0.0010000…숫자에서는 guard1이고 round 1이면 round up이 되고 round0이면 sticky에 의해서 round up/down을 판단한다.

모든 CPU가 위의 옵션을 지원하는 것은 아니다. ? Trade-off between hardware complexity, performance and market requirements…

 

Associativity

컴파일러가 arithmetic operatoroptimize하면서 operator의 순서를 바꾸기도 하는데 FP operands는 건드리지 않는다. 왜냐하면 associativity가 없기 때문이다. Associativity가 없다는게 무슨소리인가? (x+y)+zx+(y+z)가 항상 같지 않다는 것이다.

X,y가 굉장히 큰 수이고 z가 아주 작은 숫자일 때 z는 거의 무시(생략)될 때가 있다.

 

(설명사진은 추후 추가 예정)

댓글