ILNumerics - Technical Computing Tools

High Performance Framework for Visualization

and Computing in Industry and Science

 

tgt

Writing Algorithms in ILNumerics®

This section introduces an important aspect in ILNumerics: very few yet important function rules establish an efficient memory management for your algorithms. The rules are listed in the following:

  • Array Types for Function Declarations
  • using() blocks as artificial scopes
  • Handling with output parameters
  • Example of a computational function in ILNumerics
  • Best Practices for Writing ILNumerics Functions.

Array Types for Function Declarations

ILNumerics provides distinct array types - in terms of content and lifetime. Usually, the user only handles common local arrays, like ILArray<T>, ILCell and ILLogical. All array variables declared in the function body are of one of those types.

However, in need of an efficient memory management we added certain array types which are used only in the parameter list of function declarations:

  • "Input arrays" are used as general, readonly, input parameters of a function.
  • "Output arrays" serve as additional, optional, output parameters of a function.
  • "Return arrays" are always used as return value of a function.

All array types are easily distinguishable by name. The general naming scheme is as follows:

IL[|In|Out|Ret][Array<T>|Cell|Logical]

Let's assume, a function receives two dense matrices as input parameters and returns a cell array. The function signature may look as follows:

The following table lists all array types existing in ILNumerics and describes their lifetimes:

 
Content Local Array Input Parameter Output Parameter Return Value
Dense Array ILArray<T> ILInArray<T> ILOutArray<T> ILRetArray<T>
Cell Array ILCell ILInCell ILOutCell ILRetCell
Logical Array ILLogical ILInLogical ILOutLogical ILRetLogical
 
Lifetimes
Used in function .. body head head head
Disposed automatically ... when current scope was left when function scope was left when calling scope was left after the first use
Mutability fully mutable immutable fully mutable immutable
 
Functionality
Assignments to variables of that type: A = ... inA = ... [1] outA.a = ... (no variables)[2]
 

[1] Not recommended for best performance, see: Optimizing Performance for details. [2] Return values are volatile and converted to other array types or immediately disposed after first use.

All those array types share the same set of functionality. They provide the same set of member functions for read access and can arbitrarily be given to any ILNumerics function as parameter. ILNumerics deals with implicit conversions between compatible types automatically. The only exception: Input arrays and return arrays are immutable. This means, they lack of any member function or setter property which could be used to alter the content of the array. Also, obviously, these types cannot be converted to output parameters.

 

using() blocks as artificial scopes

Function bodies of any computational function must be enclosed with a construct according to the following scheme:

In Visual Basic, a corresponding Using ... End Using block needs to be used.

The ILNumerics.ILScope.Enter() function creates an artificial scope with the following functionality:

  • All arrays created inside the scope are disposed once the block was left.
  • Input parameters are disposed after the block was left.

Therefore, the ILScope.Enter() function receives all input parameters (i.e. all parameters of type ILInArray<T>, ILInCell or ILInLogical) which may appear in the parameter list.

 

Output parameters

Output parameters are used whenever a function must return more than one array. In ILNumerics, output parameters act as a reference to another (local) array in the calling scope. If a function receives a valid object reference for an output parameter (i.e. an empty array or anything but null), this signals the function to actually perform all computations required to provide the parameter. Otherwise null is returned and the function can choose another, more efficient way of computation without providing the output parameter.

Modifications and assignments to output parameters immediately alter the underlying source array. In order to make this work, output parameters can be modified in one of the following ways only. Consider an output variable named frequencies from the example below:

  • frequencies[0,full] = ... - use the setter properties to alter parts of the array. All subarray access rules are permitted. Alternatively, the SetRange() method may be used if the language used does not support those properties.
  • frequencies.a = ... - reassign a new array to the output parameter. It is important not to forget to use the .a setter property. For languages which do not support such properties (f.e. Visual Basic .NET) the frequencies.Assign() method of an array can be used instead.

By using output parameters in ILNumerics, neither the out nor the ref keyword (C#) are required. The user can easily decide, which parameter to request from a function, by simply giving any local array or null or even just a parameter. It is not necessary to declare any dummy variables, if a specific output parameter is not required.

 

Example of a computational function in ILNumerics®

Example of a computational function in ILNumerics

Note that only local array types are declared in the body - all other types are placed inside the function head. Also note that the parameter list may just as well contain any parameter type useful for the function. In the example, a parameter of system type double is used next to our array types.

 

Best Practices for Writing ILNumerics® Functions

In contrast to the obligatory rules, the following hints are optional. The user may decide to use them in order to create more readable and convenient code.

All parameters - where applicable - should be defined as optional parameters (see: C# language reference) at the end of the parameter list. Default value for all array parameters should be null. This allows the user to pick only those output parameters, which are really needed in long parameter lists.

Prepend the appropriate prefixes 'in' and 'out' to parameter names. This makes parameters easily distinguishable from local variables.

Input parameters are immutable - it is impossible to change their content. In the context of input parameter checking, the following scheme has proven to be efficient:

  • For every input parameter, a corresponding local parameter should be declared.
  • The check() function from the ILMath class is convenient to check against any parameter being null and to define constraints for them. Input parameters are therefore transformed into their corresponding local variables, including all neccessary parameter checks.
  • Optimally, the check function would be the only place to reference any input parameter in the function body.

Example of efficient parameter checking in ILNumerics:

By following these hints, assignments to input parameters are avoided completely. By doing so, ILNumerics is able to further optimize memory usage. See Optimizing Performance for details.