Operating System - OpenVMS
1824169 Members
3532 Online
109668 Solutions
New Discussion

Alpha to Integrity application porting - issue

 
SOLVED
Go to solution
Jenwae
Advisor

Alpha to Integrity application porting - issue

Hi All,

 

I have a Fortran application running on Alpha 8.3 re-written in C and now being ported to Integrity.

The application reads from and writes to legacy binary data files on disk.

We have re-compiled the C application with the option /FLOAT=G_FLOAT to support the data files.

Everything seems to run just fine, except for 2 issues we recently encountered:

 

1) On certain occasion, the application will crash with SYSTEM-F-FLTINV, floating invalid operation.

For example, at the source line:

     double my_local_double;

     my_local_double += common_double_variable_read_from_file;

 

2) We have variables declared as float. Apparently, after compiling in g_float, the data in the float changed.

 

So we wrote a small program to test out.

The value changed after passed to a subroutine/function.

For example, in MYPROGRAM.C

    int main() {

       float my_local_float = 12233.00

       printf(" Float value = %f", my_local_float");

       foo(my_local_float);

       return

    }

    

In FOO.C

    void foo(float x) {

      printf(" Float value = %f", x);

      return;

    }

 

The value printed in MYPROGRAM.C is different than in FOO.C

 

Any advice is appreciated.

Thank you,

James

22 REPLIES 22
Eberhard Heuser
Frequent Advisor

Re: Alpha to Integrity application porting - issue

Strange:

 

#include <stdio.h>
    void foo(float x) {
      printf(" Float value = %f", x);
      return;
    }

int main() {

       float my_local_float = 12233.00;
       printf(" Float value = %f", my_local_float);
       foo(my_local_float);
    }

 

$ cc/float=g_float tf.c

$ link tk

$ r tf

 Float value = 12233.000000 Float value = 12233.000000

 

$ cc/version
HP C V7.3-020 on OpenVMS IA64 V8.4

+ all actual patches (i.e. CRTL)

 

Eberhard

abrsvc
Respected Contributor

Re: Alpha to Integrity application porting - issue

One thing that would be helpful here is knowing what the actual difference is.  Please provide the actual output from the programs as listed that show the problem.  Also, you initially describe using double, yet the supplied program uses standard float.  Where is the problem, with double float or float? 

 

If you can show the different values, please also print out the variables in hex.  An examination of the actual stored binary (in hex) will be helpful as well.

 

Dan

Duncan Morris
Honored Contributor

Re: Alpha to Integrity application porting - issue

Look out for your compiler warnings!

 

$ ty test.c
int main() {
       float my_local_float = 12233.00;
       printf(" Float value = %f", my_local_float);
       foo(my_local_float);
       return 1;
    }
void foo(float x) {
      printf(" Float value = %f", x);
      return;
    }

 

produces:

 

$ cc/ver
HP C V7.3-020 on OpenVMS IA64 V8.4
$ cc/float=g_float test
 
       printf(" Float value = %f", my_local_float);
.......^
%CC-I-IMPLICITFUNC, In this statement, the identifier "printf" is implicitly declared as a function.
at line number 3 in file SYS$SYSROOT:[SYSMGR]TEST.C;2
 
       foo(my_local_float);
.......^
%CC-I-IMPLICITFUNC, In this statement, the identifier "foo" is implicitly declared as a function.
at line number 4 in file SYS$SYSROOT:[SYSMGR]TEST.C;2
 
void foo(float x) {
.....^
%CC-W-NOTCOMPATIMP, In this declaration, the type of the function "foo" is not compatible with the earlier implicit declaration of "
foo" at line number 4 in file SYS$SYSROOT:[SYSMGR]TEST.C;2.
at line number 7 in file SYS$SYSROOT:[SYSMGR]TEST.C;2


$ link test
%ILINK-W-COMPWARN, compilation warnings
        module: TEST
        file: SYS$SYSROOT:[SYSMGR]TEST.OBJ;3


$ run test
 Float value = 12233.000000 Float value = 1.811661

 

but

 

$ ty test.c
void foo(float x) {
      printf(" Float value = %f", x);
      return;
    }
int main() {
       float my_local_float = 12233.00;
       printf(" Float value = %f", my_local_float);
       foo(my_local_float);
       return 1;
    }
$ cc/float=g_float test
 
      printf(" Float value = %f", x);
......^
%CC-I-IMPLICITFUNC, In this statement, the identifier "printf" is implicitly declared as a function.
at line number 2 in file SYS$SYSROOT:[SYSMGR]TEST.C;3
$ link test
$ run test
 Float value = 12233.000000 Float value = 12233.000000
$

 

Duncan

abrsvc
Respected Contributor

Re: Alpha to Integrity application porting - issue

If you have shown the same as the original poster, then this is clearly an indication that the "bits" of the variable are being interpreted differently (as one would expect).

The variables are passed by reference. In other words the memory address of the variable is passed NOT the actual variable value. This means that at address A, the bits are interpreted as a G_float using 64 bits and in the FOO routine, address A is interpreted as a float using 32 bits.

All floating numbers are composed of 3 parts:
1) Sign bit
2) Exponent
3) fraction bits

For G_float, bits 0-51 are part of the fraction

Note that the fraction portion of hte G_float will be the only part used if the address is viewed as a standard 32 bit floating variable. Thus the difference in reported value.

Dan
Craig A Berry
Honored Contributor

Re: Alpha to Integrity application porting - issue

@abrsvc wrote:

The variables are passed by reference.
No, in C they are passed by value, but the value placed on the stack is in the format of the caller.  If the function called expects a different format, bad things happen.
For the OP question #1.  Are you absolutely certain the data read from the file are G_FLOAT, not D_FLOAT and that there aren't other problems such as structure member alignment in the move from Fortran to C?  Have you stepped through the program in the debugger and done
examine/g_float common_double_variable_read_from_file
examine/d_float common_double_variable_read_from_file
?
For question #2, are you sure you are recompiling both modules myprogram.c and foo.c with the same floating point options?  If one is compiled with /G_FLOAT and one is not, you will very likely get the symptom you are seeing or worse.
Hein van den Heuvel
Honored Contributor

Re: Alpha to Integrity application porting - issue

 

 

     double my_local_double;
     my_local_double += common_double_variable_read_from_file; 

 

As presented, that's broken / unpredictable code because my_local_double is not initialized.

Try: 

 

double my_local_double = 0;

 

fwiw,

Hein.

Jenwae
Advisor

Re: Alpha to Integrity application porting - issue

Hi All,

 

Thank you for your review and replies.

Here is my response/clarifcation to your queries.

 

To Eberhard:

Yes, strange indeed. If routine Foo is declared in the same file as main, then both float values printed out are the same, REGARDLESS if the compile option /FLOAT=ieee_float or /FLOAT=g_float is used.

 

However, if Foo is declared as a separate C file, then it gets interesting.

 

When compiled with ieee_float, result is normal. With /FLOAT=g_float, the values are mangled

Here what I got when I compiled BOTH the C files (myprogram.c, foo.c) with cc/float=g_float, and linked as link myprogram, foo.

 

 

Float value in main = 12233.000000 (hex)=e48040e7)
Float value in Foo = 1.811661 (hex=fc90401c)

 

 

To ABSRVC (Dan):

We actually encountered 2 issues.

The 2nd issue is with the float variable, which I wrote simple C programs to prove the point.

The output is as displayed above.

 

 

To Duncan:

Yes, if we put the FOO routine in the same file as the main (MYPROGRAM.C), then we don't have a problem (whether we compile with IEEE_FLOAT or G_FLOAT).

 

The float value  changes only when FOO routine is in its own file (FOO.C), and we compile both files (FOO.C and MYPROGRAM.C) with G_FLOAT. Why is this not documented by HP, or maybe I'm overlooking something.

 

 

To Craig:

Yes, I compiled both C files with the same /FLOAT option. With /FLOAT=IEEE_FLOAT, no problem, but with /FLOAT=G_FLOAT, I get mangled float variable values.

 

For your 1st query, yes, those FP data are G_FLOAT.

I did step through, and when I examine in BINARY, it shows zeroes.

 

examine/binary common_double_variable_read_from_file

 

I will examine in g_float and d_float and let you know the outcome.

 

 

To Hein:

I did init the local variable double.

But I think the FLTINV exception is triggered by the common_double_variable_read_from_file.

 

     double my_local_double = 0;

     my_local_double += common_double_variable_read_from_file;

 

 

Any clarification is appreciated. I'm trying to avoid doing Database conversion,

 

Thank you so much!

Joel

 

 

 

John Gillings
Honored Contributor

Re: Alpha to Integrity application porting - issue

James,

 

>We have re-compiled the C application with the option /FLOAT=G_FLOAT to support the data files.

 

I'd recommend you bite the bullet and convert everything to the native floating format of your new system (IEEE). Making the application non-standard for the sake of some legacy data files is a bad tradeoff. You risk the consequences of floating format mismatches (which is almost certainly what's going on here), as well as potential performance issues.

 

Build yourself a small program to convert the data in any existing files. In theory this should be very simple and very easy to validate. Tag the data files so you can tell if they're in the wrong format. The extra effort will be well worth it in the long run, even if there's a lot of data. You don't need to convert everything up front, just as needed. (Indeed, you could even build a conversion step into the application itself, making it transparent to users). 

A crucible of informative mistakes
jreagan
Advisor

Re: Alpha to Integrity application porting - issue

How did you compile the Fortran application? 

 

Don't forget that the default changed from VAX F/G on Alpha to IEEE S/T on Itanium.  It changed for BOTH Fortran and C.  And the /IEEE_MODE changed from FAST to DENORM.

Steven Schweda
Honored Contributor
Solution

Re: Alpha to Integrity application porting - issue

 
Richard Brodie_1
Honored Contributor

Re: Alpha to Integrity application porting - issue

I think the moral is that it is easier to get your code to compile without warnings, than it is to work out what the consequences of not doing so are.

Richard Brodie_1
Honored Contributor

Re: Alpha to Integrity application porting - issue

It is documented in the language reference guide:

 

"Arguments to functions that have no prototype in scope are not converted to the types of the parameters. Instead, the expressions in the argument list are converted according to the following rules:

  • Any arguments of type float are converted to double .

 

http://h71000.www7.hp.com/commercial/c/docs/6180profile_014.html#func_arg_convert_sec

 

Jenwae
Advisor

Re: Alpha to Integrity application porting - issue

Hi All,

 

Thank you for helping in our issues. It helps to have so many expertise around.

 

To Richard and Steven, thank you, Your explanation provided the solution to Issue #2 regarding the float variable. By doing proper prototyping, the mystery is resolved. (We had prototype the function foo, but without the argument type).

 

We are still mystified with Issue #1.

Although we have compiled our application with /FLOAT=g_float, sometimes when computing on certain double variable (read from the file), it crashed. I have debugged and examine the value /binary, and it all shows zeroes. I think the FLTINV is triggered on the double field read from the file.

 

I reproduce my query below.

 

1) On certain occasion, the application will crash with SYSTEM-F-FLTINV, floating invalid operation.

For example, at the source line:

     double my_double = 0;

     my_double = 1st_common_double_field_read_from_file + 2nd_common_double_field_read_from_file;

 

 

Thank you,

James

abrsvc
Respected Contributor

Re: Alpha to Integrity application porting - issue

RE: FLTINV message

 

Per the definition/format of a G_Float number, the above message will likely appear if the sign bit is set and the exponent bits are zero(0).  This would appear as 80000000 hex if you look at a register value and 00000080hex if in memory.  This is per the Alpha arch reference pg 2-5.

 

I realize that this is on an I64 machine, but I believe that the same rules apply regarding the sign bit and exponent portion.  Verify the bit layout with the debugger.

 

Dan

Steven Schweda
Honored Contributor

Re: Alpha to Integrity application porting - issue

 
Dennis Handly
Acclaimed Contributor

Re: Alpha to Integrity application porting - issue

>We had prototype the function foo, but without the argument type.

 

This is a K&R prototype, next to useless.  It might be helpful if you port your application to C++ or C99, at least to get the strong type checking.

Ph Vouters
Valued Contributor

Re: Alpha to Integrity application porting - issue

As a side note, running the VMS debugger and doing DBG> SHOW SYMBOL/TYPE variable might have helped you pinpoint the problem quicker. Be aware that I did not test on your actual case. This is just a free advice.

Ph Vouters
Valued Contributor

Re: Alpha to Integrity application porting - issue

About dealing with VAX Floats on Itanium, this document proves that it is always better to deal with IEEE floats if code performance is an issue. The document is viewable at :

http://vouters.dyndns.org/tima/OpenVMS-IA64-VAX-IEEE-floats-Performances_on_double_operations.html

 

Philippe

jreagan
Advisor

Re: Alpha to Integrity application porting - issue

Note that Ph's analysis of D vs T is the worst case.  D_FLOAT conversion is very ugly compared to G to T (and T to G).  The layout of D float requires more code to detect various invalid floatings, NaNs, etc.  The D-to-T routine is much more complicated (more instructions and more registers) than G-to-T.  The S-to-F isn't a picnic either to handle all the edge conditions. 

 

IEEE is much preferred on Itanium (which is why we changed the default) but if you have to use a VAX floating format, G would be my pick.

 

Jenwae
Advisor

Re: Alpha to Integrity application porting - issue

Hi All,

 

Thank you so much for the wealth of information.

I have read them through all, and implemented a few suggestions as per your advice.

The correct prototyping has helped to resolve the float issue when float type (not double) arguments are passed

 

We have decided to do a database conversion, changing all g_float values to ieee float values.

 

One question I have left is, do I need to convert data of type float?

Eg,

float timer;

We seem to encounter problems reading float values (because we are only converting double variables).

We have converted our data files with double variables to ieee values, but did not convert the float variables.

The float variables read in from the legacy data files (which are in g_float) showed 0, or ome incorrect values.

 

Question is, is it necessary to convert float variables? If so, does the CVT$ calls support converting float values?

 

Thank you,

James

 

John Gillings
Honored Contributor

Re: Alpha to Integrity application porting - issue

James,

 

   I'd recommend converting everything to use IEEE types. Put the work in now, rather than spend time later trying to track down obscure bugs due to mismatches.

 

   Regarding your "float timer", maybe you're using the RTL routine LIB$WAIT? It takes a floating point value in seconds. The default floating point is F_FLOAT for compatibility with the original VAX version. There's a new, optional 3rd argument to specify the floating point type. If you're finding that delay times using LIB$WAIT are incorrect, check the data types, and add a float-type argument to match.

 

See

 

$ HELP RTL LIB$ LIB$WAIT arguments

 

CVT$CONVERT_FLOAT can convert any floating point type to any other (including up and down precision, and even some non-OpenVMS types). You just specify the data type using the type code arguments for input and output

 

 

                                                                 Size in
           input_type_code          Format                       Bytes

           CVT$K_VAX_F              F_Floating                   4
           CVT$K_VAX_D              D_Floating                   8
           CVT$K_VAX_G              G_Floating                   8

           CVT$K_VAX_H              H_Floating                   16
           CVT$K_IEEE_S             IEEE_S_Floating              4
           CVT$K_IEEE_T             IEEE_T_Floating              8
           CVT$K_IEEE_X             IEEE_X_Floating              16
           CVT$K_IBM_LONG           IBM_Long_Floating            8
           CVT$K_IBM_SHORT          IBM_Short_Floating           4
           CVT$K_CRAY               CRAY_Floating                8

 

           Declarations for the input_type_code argument are in the $CVTDEF
           module found in the system symbol libraries.

 

A crucible of informative mistakes
jreagan
Advisor

Re: Alpha to Integrity application porting - issue

You want to convert both double and single precision in your data files.  Doing just the doubles will get you IEEE T for doubles, but VAX F for floats.  There is no qualifier on the compilers that allows that combination.

 

Yes, for your C application, you'll want to call CVT$CONVERT_FLOAT (it is documented in the LIB$ manual).

 

If you have all your data files, you can convert/update them (don't forget to make a backup first) or you could decide to convert on the fly when you read in the data.

 

Depending on the layout of your data and if you have the Fortran compiler, you could write a conversion program in Fortran.  It has some support for doing automatic data conversion when reading/writing binary datafiles.