rutgers-apl/rlibm

I got confuesed with the header file bfloat16.hpp

timesices opened this issue · 16 comments

typedef struct floatint{
  float f;
  unsigned int x;
};

typedef struct doubleint{
    double d;
    unsigned long long int x;
};
explicit operator float() const {
        floatint temp;
        temp.x = val;
        temp.x <<= 16;
        return temp.f;
    }

    explicit operator double() const {
        floatint temp;
        temp.x = val;
        temp.x <<= 16;
        return (double)temp.f;
    }

you rewrite those two float() and double() to revert the type of the fp number, but you make the temp.x = val while return temp.f.. how does that happer?I can't understand the meaning of these codes. I used c and java before, haven't seen c++ code. Thanks for your time, your paper really inspire me and bring me some ideas..

floatint is a union that we use in the implementation to view the value both as 32-bit bitpattern and as a floating point value.

union floatint{
float f;
unsigned int x;
};

The overloaded operator () when it returns a double needs to be cast to the double type.

floatint is a union that we use in the implementation to view the value both as 32-bit bitpattern and as a floating point value.

union floatint{
float f;
unsigned int x;
};

The overloaded operator () when it returns a double needs to be cast to the double type.

I got it. Just found that my friend modified the source code. If it's a union then everything is clear. Thx, bro!

Bro, the exp() function test code. Here you define a unsigned long long count, but int the class bfloat, you defined a unsigned short mval to store it . when I run this program, there's an exception. Is it because the long long one won't be converted to the narrower type automaticly? Or something else... And i replace the x.val = count; with x = count*1.0; so the count will be converted to bfloat16, and can use it to calculate directly. Is this all right?

unsigned long long count = 0;
    bfloat16 x = 0.0;
    for (; count < 0x10000; count++) {
        x.val = count;
        bfloat16 bres = rlibm_exp(x);
        bfloat16 bmy = MpfrCalculateExp(x);
        
        // if bres is nan and bmy is nan, continue
        if (bres != bres && bmy != bmy) continue;
        if (bres != bmy) wrongBfloatCount++;
    }

Because count is less than or equal to 0xFFFF, it will fit inside of an unsigned short and will be automatically converted to a value in unsigned short.
mval should not be inside of the bfloat class. mval is an MPFR variable that I use within the testing harness to compute the oracle result using the MPFR math library.
"x.val" stores the binary representation of the value "x". If you set x = count * 1.0, then you are really only testing 1.0, 2.0, 3.0, 4,0, ...
What's the exception? Can you post the exception message?
My hunch is that for some reason "mval" is removed, or "mval" is not initialized using the function "mpfr_init2()" function.

The followed message is shown when I use the gdb debug it. When the program run till the rlibm_exp(x), it will receive a floting-point exception. I can't figure it out, I defined a single bfloat16 argument, and test the function, it works well.

66		bfloat16 x = 0.0;
(gdb) n
69		for(; count<0x10000; count++)
(gdb) n
71			x.val = count;
(gdb) n
72			bfloat16 rlibm_res = rlibm_exp(x);
(gdb) n

Program received signal SIGFPE, Arithmetic exception.
0x000000012000201c in rlibm_exp(bfloat16) ()

I write a demo to test the function. And found that the mpfr_exp works well. Still it stopped at the rlibm_exp(). Now the question is that I can't step into the rlibm_exp() to locate the question. I'm trying...

bfloat16 rlibm_exp(bfloat16);

int main(){
        unsigned long long count = 0x50;
        bfloat16 a = 4.0;
        a.val = count;
        bfloat16 rlibm_res = rlibm_exp(a);
// I use gdb to follow the program.. can't step into the rlibn_exp()
Breakpoint 1, main () at test_exp2.cpp:9
9		unsigned long long count = 0x50;
(gdb) s
10		bfloat16 a = 4.0;
(gdb) n
11		a.val = count;
(gdb) 
12		bfloat16 rlibm_res = rlibm_exp(a);
(gdb) si
0x0000000120000e04	12		bfloat16 rlibm_res = rlibm_exp(a);
(gdb) 
0x0000000120000e08	12		bfloat16 rlibm_res = rlibm_exp(a);
(gdb) 
0x0000000120000e0c	12		bfloat16 rlibm_res = rlibm_exp(a);
(gdb) 
0x0000000120000e10	12		bfloat16 rlibm_res = rlibm_exp(a);
(gdb) 
0x00000001200016c0 in rlibm_exp(bfloat16) ()

Hmm, that's interesting. I am not able to reproduce the error. Has the source code been modified?
If you would like to step into rlibm_exp, then you will most likely have to re-build the bfloat16 math library, with "-g" flag and with "-O3" removed in order to clearly see what's going on. Then, you can build the testing harness with "-g" and it should allow you to step into rlibm_exp when you use gdb.
If you try this, where in rlibm_exp (or bfloat16 class) do you encounter the error?

I didn't step into the rlibm_exp(x) yesterday because I lost a -g option of the Makefile in /rlibm-master/..
Now i can step into this function, and found the error happened here.
By the way, I only modify the "#include <mpfr.h>" because it can't find the mpfr.h in my system, so I replace the <mpfr.h> with the absolute path of the mpfr.h and it worked.

63	        bfloat16 bres = rlibm_exp(x);
(gdb) si
0x00000001200012f0	63	        bfloat16 bres = rlibm_exp(x);
(gdb) s
rlibm_exp (x=...) at source/bfloat16/exp.cpp:4
4	    float fInput = (float)x;
(gdb) 
bfloat16::operator float (this=0x11fdc7908) at ../../include/bfloat16.hpp:142
142	        temp.x = val;
(gdb) 
143	        temp.x <<= 16;
(gdb) 
144	        return temp.f;
(gdb) 
145	    }
(gdb) 
rlibm_exp (x=...) at source/bfloat16/exp.cpp:7
7	    if (fInput <= -93.0f) {
(gdb) 

Program received signal SIGFPE, Arithmetic exception.
0x00000001200019f0 in rlibm_exp (x=...) at source/bfloat16/exp.cpp:7

It's really interesting that floating point comparison instruction
fInput <= -93.0f
is having segmentation fault. I've not seen this before. Can you check what the value of fInput is?

Of course. But it’s 23:30 here. My laptop left in the lab. I’ll show you few hours later..tomorrow😂

No rush at all! Whenever you have time just let me know!

Okay, I just use gdb to follow it again. When the count = 0, it works well. This error appeared during the second round of the loop.

rlibm_exp (x=...) at source/bfloat16/exp.cpp:7
7	    if (fInput <= -93.0f) {
(gdb) print fInput 
$2 = 0
(gdb) s
12	    if (fInput >= 89.0f) {

This is the first time get into this loop, nothing wrong.
I'll show you the second time. The "fInput" is 9.18354962e-41. That's strange. Is it because converting long long count 1 to short 1?

61	    for (; count < 0x10000; count++) {
(gdb) 
62	        x.val = count;
(gdb) 
63	        bfloat16 bres = rlibm_exp(x);
(gdb) 

Program received signal SIGFPE, Arithmetic exception.
0x00000001200019f0 in rlibm_exp (x=...) at source/bfloat16/exp.cpp:7
7	    if (fInput <= -93.0f) {
(gdb) print fInput 
$3 = 9.18354962e-41

That's really weird. So It's throwing an error when it's comparing
9.18354962e-41 <= -93.0f
I have never seen this happening before. Can you create a test case on your machine that does this comparison? I'm not sure why this would throw an error :(

I write a very simple demo as followed.. Nothing happened.

#include<stdio.h>
int main(){
        if(9.18354962e-41 >= -93.0f){
                printf("passed\n");
        }
}

sw@sw6a:~/ckq/test/temp$ ./a.out 
passed

But If i write code like this, the same error appeared.

#include<stdio.h>
int main(){
        float a = 9.18354962e-41;
        float b = -93.0f;
        if(a >= b){
                printf("passed\n");
        }
}

That's interesting😀

4		float a = 9.18354962e-41;
(gdb) n
5		float b = -93.0f;
(gdb) 
6		if(a >= b){
(gdb) 

Program received signal SIGFPE, Arithmetic exception.
0x00000001200006cc in main () at compare.c:6
6		if(a >= b){

Maybe the 9.18354962e-41 won't be converted to flaot in my system..? Or something else...

Yeah that's really weird. I have no clue why that comparison is throwing an error. Is your machine a 32-bit machine or maybe big endian machine?

This type of CPU is designed all by my country. I gotta ask the expert of this CPU what happened to this comparison. Thanks a lot, bro😎

if (exp >= -132 && exp <= -127) {
        int prec = 134 + exp;
        mpfr_t r;
        mpfr_init2(r, prec);
        mpfr_set(r, mval, MPFR_RNDN);
        retVal = mpfr_get_d(r, MPFR_RNDN);
        mpfr_clear(r);
        return retVal;
    } else {
        mpfr_t r;
        mpfr_init2(r, 8);
        mpfr_set(r, mval, MPFR_RNDN);
        retVal = mpfr_get_d(r, MPFR_RNDN);
        mpfr_clear(r);
        return retVal;
    }

I'm here again. I can't understand the meaning of this part. Which is in the MpfrCalculateLog() in log function. Especially the precision. Why the prec = 134+exp when -132<=exp<=-127..