CFD Online Logo CFD Online URL
www.cfd-online.com
[Sponsors]
Home > Forums > General Forums > Main CFD Forum

Can we optimize C++ operator overloads ?

Register Blogs Members List Search Today's Posts Mark Forums Read

Like Tree2Likes
  • 1 Post By praveen
  • 1 Post By praveen

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
Old   February 25, 2021, 01:00
Default Can we optimize C++ operator overloads ?
  #1
Senior Member
 
Sayan Bhattacharjee
Join Date: Mar 2020
Posts: 495
Rep Power: 7
aerosayan is on a distinguished road
Dear C++ experts, can we optimize the C++ operator overloads by preventing creation of temporary variables?



Generally C++ operator overloads are frowned upon due to performance degradation caused by dynamic memory allocation used while creating and deleting temporary objects in operations such as veca + vecb - vecx * vecy.


Code:
VECTOR operator+(VECTOR& a, VECTOR& b)
{
    VECTOR c; // sloooooooowwwwww

    c[0] = a[0]+b[0];
    c[1] = a[1]+b[1];

    return c;
}
This is of huge concern when the elements take up a large amount of memory (say a 1000*1000) matrix.


Now, what if we were able to use pre-allocated objects instead of creating new ones?



Code:
VECTOR operator+(VECTOR& a, VECTOR& b)
{
    auto& c = global_array_of_preallocated_objects[iobject]; // fast?

    c[0] = a[0]+b[0];
    c[1] = a[1]+b[1];

    iobject++;  // iobject is in global scope  and available everywhere

    return c;
}
Would that be a good optimization, or am I shooting myself in the foot here?
aerosayan is offline   Reply With Quote

Old   February 25, 2021, 02:32
Default
  #2
Super Moderator
 
Praveen. C
Join Date: Mar 2009
Location: Bangalore
Posts: 342
Blog Entries: 6
Rep Power: 18
praveen is on a distinguished road
You can define an add function

Code:
class VECTOR
{
void add(VECTOR& a, VECTOR& b);
};

VECTOR a, b, c;
a.add(b, c); // a = b + c
but not a good solution if you have to add several vectors in one line.

I think Chapel can do in place updates. See slide 13 here

https://chapel-lang.org/CHIUW/2020/C...-Chapel101.pdf

which shows a similar operation as in your question.

I wrote some simple example codes in Chapel here

https://github.com/cpraveen/cfdlab/tree/master/chapel
aerosayan likes this.
praveen is offline   Reply With Quote

Old   February 25, 2021, 04:27
Default
  #3
Senior Member
 
Sayan Bhattacharjee
Join Date: Mar 2020
Posts: 495
Rep Power: 7
aerosayan is on a distinguished road
Quote:
Originally Posted by praveen View Post
You can define an add function

Code:
class VECTOR
{
void add(VECTOR& a, VECTOR& b);
};

VECTOR a, b, c;
a.add(b, c); // a = b + c
but not a good solution if you have to add several vectors in one line.

I think Chapel can do in place updates. See slide 13 here

https://chapel-lang.org/CHIUW/2020/C...-Chapel101.pdf

which shows a similar operation as in your question.

I wrote some simple example codes in Chapel here

https://github.com/cpraveen/cfdlab/tree/master/chapel

I'm planning to use a free mathematical functions like you showed for some operations, if the C++ operator overload can't be optimized, and I don't have enough RAM to store the intermediary vectors or matrices in the method I mentioned.


some operation like `res = a+b+c+d+e+f+g+h` could be simplified into add(res, a,b,c,d,e,f,g,h), without needing to write loops, but I have to see what new features of C++ I can use to do it and make the function take arbitrary number of arguments. Probably through variadic templates, it will be possible.



Of course, the final aim would be to be able to write very complex operations like `res = a.dot.b + b.cross.c + div(delta)` etc in a compact form, but I don't know if it's possible.
aerosayan is offline   Reply With Quote

Old   February 25, 2021, 08:04
Default
  #4
Senior Member
 
Sayan Bhattacharjee
Join Date: Mar 2020
Posts: 495
Rep Power: 7
aerosayan is on a distinguished road
Quote:
Originally Posted by praveen View Post
You can define an add function

Code:
class VECTOR
{
void add(VECTOR& a, VECTOR& b);
};

VECTOR a, b, c;
a.add(b, c); // a = b + c
but not a good solution if you have to add several vectors in one line.

I think Chapel can do in place updates. See slide 13 here

https://chapel-lang.org/CHIUW/2020/C...-Chapel101.pdf

which shows a similar operation as in your question.

I wrote some simple example codes in Chapel here

https://github.com/cpraveen/cfdlab/tree/master/chapel

I have a reaaaaaalllyyy bad idea on how we can get "similar" compact mathematical form of Fortran, in C++.


Code:

#define xa  [IVAR] +
#define xs  [IVAR] -
#define xm  [IVAR] *
#define xd  [IVAR] /
#define xe [IVAR]



#define IVAR i

for(int i=0; i<n; ++i)
{

    c = a xa b xa c xs d xm e xe;
    e = a xs b xe;
    c = c xm e xe;

}

#undef IVAR
This might seem stupid (and might actually be), but I think it can be useful.
aerosayan is offline   Reply With Quote

Old   February 25, 2021, 08:07
Default
  #5
Super Moderator
 
Praveen. C
Join Date: Mar 2009
Location: Bangalore
Posts: 342
Blog Entries: 6
Rep Power: 18
praveen is on a distinguished road
Have you looked at "Expression Templates", see

https://en.wikipedia.org/wiki/Expression_templates

It describes almost same situation which you are asking.
aerosayan likes this.
praveen is offline   Reply With Quote

Old   February 25, 2021, 12:26
Default
  #6
Senior Member
 
Sayan Bhattacharjee
Join Date: Mar 2020
Posts: 495
Rep Power: 7
aerosayan is on a distinguished road
Quote:
Originally Posted by praveen View Post
Have you looked at "Expression Templates"

I created an Expression Template library last year. Not worth the effort. Highly overrated in my humble opinion, as it becomes very difficult to find optimization possibilities in the code.


I came up with a hack to make it a little bit easier to work with such long expressions. I just want to write simple code for N dimensional arrays, like in Fortran 95, but in C++.


Looks like the operator overloading may not be the best solution.


This hack works for now, I guess.



Code:
#include <iostream>
#include <vector>
#include <array>

using namespace std;

// Short form of a for loop
//
#define DO(IX, START, END) for(int (IX)=(START); (IX)<(END); ++(IX))
#define DO2(IX, START1, END1, IY, START2, END2) DO((IX), (START1), (END1)) { DO((IY), (START2), (END2)) {

// Short form to close multiple braces
//
#define END }
#define END2 }}

// Access array with index
//
#define ix [i]
#define jx [j]
#define kx [k]

// Access 2D arrays with index
//
#define ix0 [i][0]
#define ix1 [i][1]
#define ix2 [i][2]

// Access 2D arrays with DO2 loop
#define ijx [i][j]

int main()
{
    //-----------------------------------------------------------------------//
    //                              EXAMPLE-1                                //
    //-----------------------------------------------------------------------//

    // No. of elements
    int n = 100;

    // 3 arrays
    int a[n], b[n], c[n];

    // Fill up values of a and b
    DO(i,0,n)
    {
        a ix = 1;
        b ix = 2;
    }

    // Do addition : c = a + b
    DO(i,0,n)
    {
        c ix = a ix + b ix;
    }

    // Print results
    DO(i,0,5)
    {
        cout << a ix << " + " << b ix << " = " << c ix << endl;
    }

    //-----------------------------------------------------------------------//
    //                              EXAMPLE-2                                //
    //-----------------------------------------------------------------------//

    // Vector of arrays
    std::vector<std::array<double, 2>> va(n), vb(n), vc(n);

    // Fill up values of a and b
    DO(i,0,n)
    {
        va ix0 = 1.0;
        va ix1 = 2.0;

        vb ix0 = 1.0;
        vb ix1 = 2.0;
    }

    // Add the two vectors elementwise : vc = va + vb
    // NOTE : We are writing only one equation, and both elements are used
    //
    DO2(i,0,n, j,0,2)
        vc ijx = va ijx + vb ijx;
    END2

    // Print results
    DO(i,0,5)
    {
        cout << "<"
        << va ix0 << ", " << va ix1 << "> + <"
        << vb ix0 << ", " << vb ix1 << "> = <"
        << vc ix0 << ", " << vc ix1 << ">"<< endl;
    }
    return 0;
}
Output :
Code:
1 + 2 = 3
1 + 2 = 3
1 + 2 = 3
1 + 2 = 3
1 + 2 = 3
<1, 2> + <1, 2> = <2, 4>
<1, 2> + <1, 2> = <2, 4>
<1, 2> + <1, 2> = <2, 4>
<1, 2> + <1, 2> = <2, 4>
<1, 2> + <1, 2> = <2, 4>
aerosayan is offline   Reply With Quote

Old   February 25, 2021, 15:25
Default
  #7
Senior Member
 
Sayan Bhattacharjee
Join Date: Mar 2020
Posts: 495
Rep Power: 7
aerosayan is on a distinguished road
My macro based "hack" might actually be a very good solution.
It feels good to write, it feels fast to write, it feels easy to read, and it doesn't break anything as far as I know.



Using it in my codebase from now on.
aerosayan is offline   Reply With Quote

Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are On


Similar Threads
Thread Thread Starter Forum Replies Last Post
How to optimize computation time in fluent Doflamingo FLUENT 1 April 9, 2020 14:07
Optimize Membrane ANSYS alexsupertump ANSYS 1 October 28, 2017 18:31
[Other] howto optimize OpenFOAM for Core i7 CPU using extended instruction set cutter OpenFOAM Installation 6 December 28, 2015 21:19
Optimize for laminar flow, assume it valid for turbulent flow? Chander CFX 15 November 6, 2011 06:06
Optimize for laminar flow, assume it valid for turbulent flow? Chander Main CFD Forum 2 October 24, 2011 08:43


All times are GMT -4. The time now is 12:08.