The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My work

  • My badges

  • Twitter Updates

  • My Flickr Stream

    20140508-Delphi-2007--Project-Options--Cannot-Edit-Application-Title-HelpFile-Icon-Theming

    20140430-Fiddler-Filter-Actions-Button-Run-Filterset-now

    20140424-Windows-7-free-disk-space

    More Photos
  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 1,338 other followers

Delphi/Fortran memory allocation difference: row/column major order makes a big difference. StackOverflow answer.

Posted by Jeroen Pluimers on 2012/08/14

Last week I posted an in depth answer on StackOverflow.com about the memory allocation difference in Delphi and Fortran, or more accurately in two different kinds of languages.

You have:

  • column major order (not only used in Fortran and other science centric languages, but also in the shading languages GLSL and HLSL that can be used in FireMonkey)
  • row major order (used in most other languages, for instance Delphi, C, etc)

A very important aspect is the order of for optimized loops. For column major order, the optimum is inside out (as the inner arrays/records are in consecutive memory locations), but for row major order, it is the exact inverse.

One of the consequences is that in Fortran it is a very fast operation to pass an array of inner fields as parameter to a method.

This is what I wrote:

I’m posting this as an answer because the comments are a bit too limited to phrase this.

This answer tries to explain the differences in memory layout of arrays and records in FORTRAN and Delphi and amends the answer by Todd Grigsby and the answer by Remy Lebeau (I upvoted both).

FORTRAN and a few other calculation centric languages stores nested arrays in column major order. Delphi and many other languages use a row major order.

From a memory perspective, a record is nothing else than an array of fields that:

  • have a name and not an index
  • might have different types

For calculation intensive operations, it can make sense to store nested arrays column major order when your algorithms favour the columns. Same for row major order. So in loops, you need to match the order of your indexes with the order of your storage.

Given this record and array definition in FORTRAN:

TYPE WallInfo
  CHARACTER(len=40) :: Name
  REAL              :: Azimuth
  REAL              :: Tilt
  REAL              :: Area
  REAL              :: Height
END TYPE WallInfo

TYPE(WallInfo), ALLOCATABLE, DIMENSION(:) :: Wall

and the functional equivalent definition in Delphi:

type
  WallInfo = record
    Name: array[0..39] of Char;
    Azimuth: Real;
    Tilt: Real;
    Area: Real;
    Height: Real;
  end;

var
  Wall: array of WallInfo;

and an array of 3 WallInfo elements, this is how the memory layout would look (they would all be continuous memory areas, I split them in lines to keep it readable):

in FORTRAN:

Name[0,0]...Name[0,39], Name[1,0]...Name[1,39], Name[2,0]...Name[2,39],
Azimuth[0], Azimuth[1], Azimuth[2],
Tilt[0], Tilt[1], Tilt[2],
Area[0], Area[1], Area[2],
Height[0], Height[1], Height[2],

in Delphi:

Name[0,0]...Name[0,39], Azimuth[0], Tilt[0], Area[0], Height[0],
Name[1,0]...Name[1,39], Azimuth[1], Tilt[1], Area[1], Height[1],
Name[2,0]...Name[2,39], Azimuth[2], Tilt[2], Area[2], Height[2],

So this FORTRAN call:

CALL HeatFlow(Wall%Area, Wall%Azimuth)

would just pass the pointers to the Area[0] and Azimuth[0] memory locations and length of those memory areas to the function.

In Delphi, that is not possible, so you have to

  1. construct new Area and Azimuth arays
  2. copy them from the info in the array of WallInfo record instance called Wall
  3. send them to the function
  4. if these are var parameters: copy the changes from the two arrays back to Wall

Todd Grigsby and Remy Lebeau showed the first three steps in their answer using straight Delphi code, or Delphi record RTTI.
Step 4 works in a similar way.

Both solutions use generics that were introduced in Delphi 2009.
Until Delphi 2010, RTTI on records was very minimal), so you got the right Delphi version for both answers.

Note (again): when translating your algorithms from FORTRAN to Delphi, make sure you watch for loops and other indexing in the arrays because of the column/row major change.

–Jeroen

via: delphi – Given an array of records, how can I get an array representing a field from each one? – Stack Overflow.

4 Responses to “Delphi/Fortran memory allocation difference: row/column major order makes a big difference. StackOverflow answer.”

  1. Cool, you’re working on heat loss calculations. Good topic, Thx.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

Join 1,338 other followers

%d bloggers like this: