|
[Sponsors] |
February 25, 2021, 01:00 |
Can we optimize C++ operator overloads ?
|
#1 |
Senior Member
Sayan Bhattacharjee
Join Date: Mar 2020
Posts: 495
Rep Power: 7 |
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; } 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; } |
|
February 25, 2021, 02:32 |
|
#2 |
Super Moderator
|
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 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 |
|
February 25, 2021, 04:27 |
|
#3 | |
Senior Member
Sayan Bhattacharjee
Join Date: Mar 2020
Posts: 495
Rep Power: 7 |
Quote:
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. |
||
February 25, 2021, 08:04 |
|
#4 | |
Senior Member
Sayan Bhattacharjee
Join Date: Mar 2020
Posts: 495
Rep Power: 7 |
Quote:
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 |
||
February 25, 2021, 08:07 |
|
#5 |
Super Moderator
|
Have you looked at "Expression Templates", see
https://en.wikipedia.org/wiki/Expression_templates It describes almost same situation which you are asking. |
|
February 25, 2021, 12:26 |
|
#6 |
Senior Member
Sayan Bhattacharjee
Join Date: Mar 2020
Posts: 495
Rep Power: 7 |
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; } 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> |
|
February 25, 2021, 15:25 |
|
#7 |
Senior Member
Sayan Bhattacharjee
Join Date: Mar 2020
Posts: 495
Rep Power: 7 |
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. |
|
Thread Tools | Search this Thread |
Display Modes | |
|
|
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 |