In which cases does dynamic memory allocation occur during evaluation of Blaze expressions?

Issue #207 closed
Mikhail Katliar created an issue

In some parts of my code I want to completely avoid dynamic memory allocation. How do I know whether a dynamic memory allocation (which may be necessary for storing intermediate results) takes place during an evaluation of a Blaze expression involving DynamicMatrix'es and DynamicVectors?

Comments (9)

  1. Klaus Iglberger

    Hi Mikhail!

    Thanks for creating the issue. Unfortunately there is no 100% guarantee to avoid memory allocations as soon as you use DynamicVector and DynamicMatrix. However, still there is several things you can do:

    • Instead of using DynamicVector and DynamicMatrix you can use HybridVector and HybridMatrix. These data structures never allocate since they use static memory. It is necessary to specify the maximum number of elements, but you can freely resize within these bounds.

    • Don't use complex expressions, but only simple expressions (one addition, one multiplication, etc.). Then you have full control over where the result is written to and can control memory allocations. More specifically, if the target vector or matrix provides enough capacity no memory allocation will be triggered. Example:

    DynamicMatrix<int> A, B;
    DynamicVector<int> x, y;
    
    y = A * B * x;  // Requires a temporary vector for the result of B * x
    
    DynamicMatrix<int> A, B;
    DynamicVector<int> x, y, tmp;
    
    // Resize tmp as necessary before it is used
    tmp.resize( B.rows() );
    
    tmp = B * x;  // No temporary required, result is directly written into 'tmp'
    y = A * tmp;  // No temporary required, result is directly written into 'y'
    

    I hope this help and gives you some idea how to use Blaze expressions.

    Best regards,

    Klaus!

  2. Mikhail Katliar reporter

    Hello Klaus,

    Thanks for the explanation. How much work is it to implement something like a traits class, which would give me a boolean value depending on whether the expression involved dynamic memory allocation or not? Such that I could write a code like below:

    DynamicMatrix<int> A, B;
    DynamicVector<int> x, y;
    
    static_assert(DynamicAllocation<decltype(A * B * x)>::value);
    static_assert(!DynamicAllocation<decltype(A * B)>::value);
    
  3. Klaus Iglberger

    Hi Mikhail!

    The functionality you are looking for is already available in the form of the RequiresEvaluation type trait. The semantics are a little different, though:

    blaze::DynamicMatrix<int> A, B;
    blaze::DynamicVector<int> x, y;
    
    static_assert( !blaze::RequiresEvaluation_v< decltype( x + y ) > );  // ( x + y ) does not require an evaluation and therefore does not require a temporary
    static_assert( blaze::RequiresEvaluation_v< decltype( A * B ) > );  // ( A * B ) does require an evaluation and therefore requires a temporary if used as subexpression
    static_assert( blaze::RequiresEvaluation_v< decltype( B * x ) > );  // ( B * x ) does require an evaluation and therefore requires a temporary if used as subexpression
    static_assert( blaze::RequiresEvaluation_v< decltype( A * B * x ) > );  // ( A * B * x ) does require an evaluation since both subexpressions require an evaluation
    

    Please make sure to evaluate RequiresEvaluation on subexpressions and not on the final expression (for instance, A * B and B * x and not A * B * x). Then you should be able to use it like the proposed DynamicAllocation or implement DynamicAllocation in terms of it.

    Best regards,

    Klaus!

  4. Log in to comment