Storage size of derived-type larger than the sum of storage sizes of individual components

Storage size of derived-type larger than the sum of storage sizes of individual components

Hi,

I've just notice a strange behavior of the fortran 2008 "storage_size" procedure when applied to simple derived-type variables.

If a derived-type is defined with only scalar variables, then the storage size of this derived-type is larger than the sum of the storage sizes of each individual components.

The above program,

Program Main

	  implicit none

	  type          ::      My_Type

	    logical     ::      l0

	    integer     ::      i0

	    real(4)     ::      s0

	    real(8)     ::      d0

	  end type

	  type(My_Type) ::      Var

	  write(*,"('Starting')")

	  write(*,"('Storage_Size(Var%l0)    = ',g0)") Storage_Size(Var%l0)

	  write(*,"('Storage_Size(Var%i0)    = ',g0)") Storage_Size(Var%i0)

	  write(*,"('Storage_Size(Var%s0)    = ',g0)") Storage_Size(Var%s0)

	  write(*,"('Storage_Size(Var%d0)    = ',g0)") Storage_Size(Var%d0)

	  write(*,"('SUM Storage_Size(Var%*) = ',g0)") Storage_Size(Var%l0) + Storage_Size(Var%i0) +Storage_Size(Var%s0) + Storage_Size(Var%d0)

	  write(*,"('Storage_Size(Var)       = ',g0)") Storage_Size(Var)

	  write(*,"('Ending')")

	End Program

gives the following result:

$ ifort main.f90; ./a.out

	Starting

	Storage_Size(Var%l0)    = 32

	Storage_Size(Var%i0)    = 32

	Storage_Size(Var%s0)    = 32

	Storage_Size(Var%d0)    = 64

	SUM Storage_Size(Var%*) = 160

	Storage_Size(Var)       = 192

	Ending

Why such a behavior ? Is there some hidden data stored somewhere in the derived-type ?

10 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

d0 is misaligned, so we added 4 bytes of padding before it. This happens even if you make it a BIND(C) type, though I have to check if C does the same thing (in which case that would be correct.) You could add SEQUENCE to the declaration and that would remove the padding, or use -align norecords

Steve - Intel Developer Support

Ok, thanks.

3 questions:

  • Is the SEQUENCE attribute depreciated ?
  • Is it allowed to define TBP in a derived-type which has the SEQUENCE attribute ?
  • Will there be any impact on performance by using the SEQUENCE attribute ?

 

SEQUENCE is not deprecated. I don't have my references handy but I don't see why SEQUENCE would interfere with TBPs. Yes, there is a performance impact to misaligned values, which is why we pad.

Steve - Intel Developer Support

Quote:

Steve Lionel (Intel) wrote:

SEQUENCE is not deprecated. I don't have my references handy but I don't see why SEQUENCE would interfere with TBPs. Yes, there is a performance impact to misaligned values, which is why we pad.

Based on my reading of Fortran 2003 and 2008 standards (as quoted below), types with SEQUENCE attribute

* cannot have type-bound procedures

Quote:

19 C436 (R425) If SEQUENCE appears, each data component shall be declared to be of an intrinsic type or of a

20 sequence type, and a type-bound-procedure-part shall not appear.

* are not extensible

Quote:

24 C431 (R425) If EXTENDS appears, SEQUENCE shall not appear.

* cannot have the BIND(C) attribute

Quote:

7 C1501 (R425) A derived type with the BIND attribute shall not have the SEQUENCE attribute.

Hence I find SEQUENCE highly limiting and have generally stopped using it.

Ok - as I said I didn't have the standard handy at the time. I also don't care for SEQUENCE as all the standard says is that it prevents reordering of the components. Making sure the components are naturally aligned to begin with is best.

Steve - Intel Developer Support

Steve,

A suggestion: the documentation for SEQUENCE in the Intel Fortran Compiler Help is quite barren.  Will it be possible for your writers to include all the caveats listed in the 2003 and 2008 standards?  It will help many of the users who haven't made a habit of referencing the standards documentation (which can be very dense).

Thanks,

Quote:

User and Reference Guide for the Intel® Fortran Compiler 14.0

SEQUENCE

Statement: Preserves the storage order of a derived-type definition.

SEQUENCE

Description

The SEQUENCE statement allows derived types to be used in common blocks and to be equivalenced.

The SEQUENCE statement appears only as part of derived-type definitions. It causes the components of the derived type to be stored in the same sequence they are listed in the type definition. If you do not specify SEQUENCE, the physical storage order is not necessarily the same as the order of components in the type definition.

If a derived type is a sequence derived type, then any other derived type that includes it must also be a sequence type.

Example

 !DIR$ PACK:1
 TYPE NUM1_SEQ
   SEQUENCE
   INTEGER(2)::int_val
   REAL(4)::real_val
   LOGICAL(2)::log_val
 END TYPE NUM1_SEQ
 TYPE num2_seq
    SEQUENCE
    logical(2)::log_val
    integer(2)::int_val
    real(4)::real_val
 end type num2_seq
 type (num1_seq) num1
 type (num2_seq) num2
 character*8 t, t1
 equivalence (num1,t)
 equivalence (num2,t1)
 num1%int_val=2
 num1%real_val=3.5
 num1%log_val=.TRUE.
 t1(1:2)=t(7:8)
 t1(3:4)=t(1:2)
 t1(5:8)=t(3:6)
 print *, num2%int_val, num2%real_val, num2%log_val
 end

Parent topic: S

See Also

Derived Data Types

Data Types, Constants, and Variables

 

Submit feedback on this help topic

The current thinking is that SEQUENCE should not be used - it doesn't do what most people want, which is to guarantee a particular layout of a derived type. BIND(C) does that better, though you're still subject to the choices made by the "companion C processor".

The age-old advice still stands - arrange your components so that all are naturally aligned, so you won't have to worry about padding.

Steve - Intel Developer Support

Even if all components are naturally aligned you can get padding. Try it with the current example and appropriate arrangement, and various combinations of platform and BIND(C). The reason is the under at least some environments an array of a derived type should have all conponents of all elements aligned so you can't have a 20-byte derived type when one of its components requires 8-byte alignment.

RO is correct, but the important point is that BIND(C) specifies that the layout and storage size must match what the "companion C processor" does for the equivalent struct. If the C compiler pads, then Fortran will too. Intel Fortran has directives and compile options to specify or disable padding, as do most C compilers.

Steve - Intel Developer Support

Leave a Comment

Please sign in to add a comment. Not a member? Join today