Opened 4 years ago

Last modified 4 years ago

#6220 new defect

Small array optimizations: stack allocation

Reported by: mahge930 Owned by: mahge930
Priority: normal Milestone: NeedsInput
Component: Run-time Version:
Keywords: Cc: casella, sjoelund.se, adrpo, AnHeuermann

Description (last modified by mahge930)

Arrays of OpenModelica runtime are defined as the following struct

struct {
  int ndims;
  _index_t *dim_size;
  void* data;
  m_boolean flexible;
};

Here is a very basic "small static" array of 1 dimension that can be a starting point for implementation.

#define SMALL_ARRAY_1(name, type, dim1) \
      struct { \
        int ndims; \
        _index_t *dim_size; \
        void* data; \
        m_boolean flexible; \
        _index_t dim_size_d[1]; \
        type data_d[dim1]; \
      } name = {1, arr1.dim_size_d, arr1.data_d, 0, {dim1}, {0}};

Basically it is the normal array struct with additional members added at the bottom so that it can be "sliced" when casted as the normal array struct. The pointer members are initialized to point to the data allocated on the stack by the last two members respectively.

I am not sure how point of declaration is enforced with C but if it does not work we will find out pretty soon.

It can be used as

SMALL_ARRAY_1(arr1, modelica_real, 3);

to declare an arr1 array of modelica_real with 1 dimension of size 3.

This matches the expected interface for normal (non-static) arrays while keeping its data on stack. That is, it can be passed to functions that we already use for the normal arrays. Of course there are warning about incompatibility of passed pointers and so on. For example this can be passed to "getter" functions as

real_array_get(arr1, 1, _i) = 1;

We need to figure out a way to safely copy these and normal arrays between each other (if that turns out to be needed).

There are many things that can go wrong with this. We will find out.

If you have suggestions, ideas, tricks, concerns ... please let me know :). We want to implement this with as small change as possible to code generation and Modelica compilation.

Change History (6)

comment:1 Changed 4 years ago by mahge930

  • Description modified (diff)

comment:2 Changed 4 years ago by mahge930

  • Description modified (diff)

comment:3 Changed 4 years ago by mahge930

  • Description modified (diff)

comment:4 Changed 4 years ago by casella

  • Cc sjoelund.se adrpo AnHeuermann added

Seem to me like a good idea, but my C programming skills are quite rusty :)

I cc: some people that may give you suggestions.

comment:5 follow-up: Changed 4 years ago by AnHeuermann

I'm not sure if I understand it correctly, but you plan to use a macro for the implementation, right?

I would pfeffere a way without macros. They are usually very hard to debug and a bit error prone. Some years ago speed was one of the reasons for using macros, but that is no longer the case. Inline functions are similar fast and even without inline it shouldn't really matter (at least with a modern compiler).
So for this example we could generate the C code directly. Of course with the obvious downside that we have a lot of redundant code.

comment:6 in reply to: ↑ 5 Changed 4 years ago by mahge930

Replying to AnHeuermann:

I'm not sure if I understand it correctly, but you plan to use a macro for the implementation, right?

I would pfeffere a way without macros. They are usually very hard to debug and a bit error prone. Some years ago speed was one of the reasons for using macros, but that is no longer the case.

Yes the macros are more of a (ironically) readability addition here. We can of course generate the exact contents of the macro for each declaration. I am afraid that would be even more confusing in this case. This is, of course, personal preference and something we can change anytime.

Macros are, unfortunately, part of our main tool box here. We are dealing with C (and C89 for that matter). We can not even overload the utility functions. If you look at the generated and/or runtime code, it is still full of macros that mimic the jobs of overloaded functions. That is also the reason why we need a "slicable" struct that matches the interface of the normal array.

Inline functions are similar fast and even without inline it shouldn't really matter (at least with a modern compiler).

[Inline] functions are not an option here since the data is supposed to be on stack. That eliminates using functions since the data would be invalid on return from the allocation function, i.e, the stack is poped and memory can be overwritten

Note: See TracTickets for help on using tickets.