Operating System - OpenVMS
1748181 Members
3691 Online
108759 Solutions
New Discussion

How do I get the fortan compiler to consistently align record structures?

 
Glenn Wolf
Advisor

How do I get the fortan compiler to consistently align record structures?

I've been working away at the alignment faults in our Fortran-based application while porting to Itanium, and I've come across what I think is an inconsistency in the compiler.  It's at least behavior that has changed between HP Fortran 77 V8.0-198-48F7C on OpenVMS Alpha V8.2, and HP Fortran V8.2-104939-50H96 on OpenVMS V8.4 on Itanium.

 

I found a poor-man's equivalence that looks like this:

!DEC$    OPTIONS /ALIGN=RECORD=PACKED
    structure /OddSize/
      character*1    Bump1
      integer*4     Long
          character*1    Bump2
          integer*8    quad
          character*1    Bump3
    end structure
!DEC$    END OPTIONS


        structure /UnionOfOddSize/
           union
              map
                 record /OddSize/    first
                 record /OddSize/    second
                 record /OddSize/    third
              end map
              map
                 record /OddSize/    allThree(3)
              end map
              map
                 record /OddSize/    firstAndSecond(2)
                 record /OddSize/    theThird
              end map
              map
                 record /OddSize/    theFirst
                 record /OddSize/    secondAndThird(2)
              end map
           end union
        end structure

        record /UnionOfOddSize/        MishMash

Basically, the programmer wants 3 record structures, and sometimes wants to refer to the first two or the last two as an array of two record structures.  The recod structures themselves must be packed (thus the CDEC$ OPTION lines) because the structures are stored that way on disk.

 

In the alpha environment, the OddSize structure is packed tightly, and both the set of 3 individual OddSize structures and the arrays of these structures are packed - i.e., the second and third structures do not start on a natural boundary.

 

In the itanium environment, the OddSize structure is packed tightly, and the individual OddSize structures each start on a longword boundary, however, the array elements are tightly packed like in the alpha.This means that we can't really use this an equivalence approach.

 

I know how to fix the allignment faults here, but the question is how make the Itanium compiler allocate these data elements consistently?  The issue is that the code as written (many, many moons ago) breaks when compiled on Itanium.  This instance I found because it tripped up one of our regression tests, but I am concerned that there may be others hidden that we DON'T have coverage for in our test suite.  If they show up in production as slow but still working code due to the alignment faults, I at least have a working system, and won't have to roll back.

 

I put together a test progam to illustrate the issue, and it is attached. Here is the output:
 Size of OddSize:                     15
 The first OddSize, by 4 names:
 First:                                  65536  Offset:                      0
 AllThree(1):                            65536  Offset:                      0
 FirstAndSecond(1):                      65536  Offset:                      0
 theFirst:                               65536  Offset:                      0

 The second OddSize, by 4 names:
 Second:                                 65552  Offset:                     16
 AllThree(2):                            65551  Offset:                     15
 FirstAndSecond(2):                      65551  Offset:                     15
 SecondAndThird(1):                      65552  Offset:                     16

 The third OddSize, by 4 names:
 Third:                                  65568  Offset:                     16
 AllThree(3):                            65568  Offset:                     15
 theThird:                               65568  Offset:                     17
 SecondAndThird(2):                      65567  Offset:                     15


11 REPLIES 11
Glenn Wolf
Advisor

Re: How do I get the fortan compiler to consistently align record structures?

Ok, Let's see if I can attach the test program to a reply...

John Gillings
Honored Contributor

Re: How do I get the fortan compiler to consistently align record structures?

Glenn,

 

   What you describe sounds correct. I don't have Fortran compilers to check, but I do remember arguments at Ambassador meetings about changing the defaults for alignment qualifiers between architectures. IIRC the alpha compilers by default do not align, while the itanium ones do. (My prediction was that making the change would lead to user confusion, exactly like you're reporting, so perhaps I was right? However, that's probably a lesser evil than allowing users to inadvertently misalign their data and suffer performance issues).

 

So, the Itanium compiler does what you ask and packs your OddSize object. Since the UnionOfOddSize structure is declared outside the scope of the OPTIONS directives, it will be subject to the compiler default, and therefore aligned on Itanium and unaligned on Alpha.

 

Since you want UnionOfOddSize to be packed, you should tell the compiler by enclosing it inside an OPTIONS /ALIGN=RECORD=PACKED directive. That should make both compilers do the same thing, independently of compiler qualifiers.

 

My preference would be to bracket the declaration inside its own directives, rather than extend the scope of the directives for OddSize.

 

That said, I'd recommend you do some experiments to make sure you're going in the right direction. Just because the data on disk is misaligned doesn't mean you have to operate on it in that state. Check the performance and alignment faults. Depending on the extent of the data you have on disk, you may be able to convert it to aligned data. Another approach is to isolate the unaligned data in your file access subsystem, reading the raw data unaligned and immediately "unpacking" it into aligned structures for processing, then packing it up again to write back to disk. This can all be hidden from the application.

 

You may even want to have a hybrid approach. Write new data aligned, and use some kind of tag to determine if the incoming data is aligned or not. You maintain compatibility with your old data and benefit from the improvements in the new architecture. Best of both worlds.

A crucible of informative mistakes
Glenn Wolf
Advisor

Re: How do I get the Fortran compiler to consistently align record structures?

John:

 

Thanks for you thoughtful comments.  I have continued to experiment with this test case, and the issue that I have is that the alignment options have no effect on the arrays of structures.  If I enclose the UnionOfOddSize definition with !DEC$ OPTIONS /ALIGN=RECORD=PACKED, then the record structures and the arrays are all packed tightly.  But I would rather have the arrays aligned on a longword boundary, and that doesn't seem possible with the any combination of the /ALIGN options.

 

At least I can make the code functional (though still ugly) with the above approach.

 

Glenn

GuentherF
Trusted Contributor

Re: How do I get the Fortran compiler to consistently align record structures?

I just ran into a problem like this with a 25 year old application written for a VAX (nice then).

 

I ended up adding filler fields to the structure definitons. Also avoided the warning message by the FORTRAN compiler.

 

This worked in my case because these records (+arrays) are only created and used in virtual memory. Would not work when reading/writing raw data from/to disk. I had to read a flat buffer and use LIB$MOVC3 to get that data into the record in memory.

 

/Guenther 

Mike Kier
Valued Contributor

Re: How do I get the Fortran compiler to consistently align record structures?

It is unfortunately a very grey area.  The Fortran standard in general tries to be neutral with respect to physical data layout, leaving such things to the compiler engineers.

 

The authors of the standard have been recommending movement away from layout-specific language constructs (like COMMON) toward more generic constructs (like MODULE and user-defined TYPEs).  They do allow the SEQUENCE attribute for user-defined TYPEs but the default is without that.

 

And of course STRUCTURE and RECORD (and UNION and MAP) are DEC extensions to the language and are not covered by the standards anyway.

 

I inherited a bunch of code (our team supports several million lines of Fortran code), some of which was barely post-FORTRAN 68, and the bulk of which was developed on VAX under DEC FORTRAN 77 with extensions (including some with DICTIONARY elements).  The best I try to do is to wrap most of my Structures and COMMONS in !CDEC$ Option /NoAlign and add filler elements where possible to bring the higher-level structures and arrays of structures to a quadword-multiple size.

 

It's not fun, but it minimizes the effect of different compilers or compiler switches.  I'd rather move more toward Fortran 95 constructs but it would be a huge effort and would be a budget buster and there is a lot of resistance among some of the developers to move to Fortran 95 syntax.

Practice Random Acts of VMS Marketing
jreagan
Advisor

Re: How do I get the Fortran compiler to consistently align record structures?

We certainly changed some alignment & packing defaults across the compilers when moving from VAX to Alpha.  However, I don't recall that we changed ANY when moving from Alpha to Itanium.  The only thing different is that the Itanium compilers default to IEEE float instead of VAX float.

 

And can I ask how you know there are alignment faults with the posted code?  When the code generator knows that something is unaligned, it should not generate instructions that cause a fault.  An INTEGER*4 on that starts on byte 17 of some record will simply get a sequence of ld1/ld2/ld2/ld1 instructions that are predicated based on the lower bit of the address.

 

I would go so far as to say the packing of those sub arrays is either a bug or some incompatible change which wasn't thought out very well.

 

Also, if you see the code generator produce code that gets actual alignment faults in spite of it knowing that the item is unaligned, then that is a compiler bug also.  It is up to the frontends to provide GEM the correct alignment and offset values.

GuentherF
Trusted Contributor

Re: How do I get the Fortran compiler to consistently align record structures?

Glenn,

 

you have not told the compiler to use the packed option for the union as well. Wrap the union definiton with the same option as the structure.

 

/Guenther

GuentherF
Trusted Contributor

Re: How do I get the Fortran compiler to consistently align record structures?

John,

 

I just ported an application from Alpha to Itanium and ran into alignment issues. The application was ported from VAX to Alpha around 1997. No idea what version of the FORTRAN compiler they used and which compiler options/qualifiers. I also did a build of the application on V8.4/Alpha and I got the same alignment issues.

 

Maybe, maybe the way the FORTRAN compiler on Alpha back then handled alignment issues differently (i.e. implicitly packed)? I dunno. I wasn't much into FORTRAN those days. :-)

 

/Guenther

abrsvc
Respected Contributor

Re: How do I get the Fortran compiler to consistently align record structures?

Keep in mind that the compiler for the Itanium is an F90/95 compiler and that the Alpha is likely to contain switches that conform the compiler to the F77 level. The default on VAX would not "align" anything. The Alpha compilers would likely use the unaligned LDx/MSK/STx instruction sequences that are common to all Alpha hardware. The newer Alpha systems could use the byte instructions as well. Check the listings to se what the differences were. Compiler switch setting are critical here.

Dan