Difference between revisions of "Contrib equationReader/Efficiency"

From OpenFOAMWiki
Line 1: Line 1:
''How fast is '''equationReader'''?''
+
== How fast is '''equationReader'''? ==
  
'''equationReader''' takes between 10 to 20 times longer than a hard-coded solution.  This is because it is currently interpretiveI thought the fancy ''function-pointer'' framework I used would be faster, but it isn't.  Don't despair, the next version will actually ''compile'' your equations on the fly... in theory this will make it equal that of a hard-coded solution.
+
The most recent version of '''equationReader''' (''Version 0.5.0'', released September 25th, 2011) handles fields roughly 10x faster than the previous version.  Overall, '''equationReader''' now takes approximately 5.87 times longer than a hard-coded solution when handling <tt>GeometricFields</tt>That's for a simple equationFor more complex equations, '''equationReader''''s performance improves.
  
== Efficiency discussion ==
+
Straight up <tt>scalars</tt> are still much slower.  I haven't benchmarked the latest version, but previous versions were coming in at around 300 x slower.
  
=== Parsing and evaluating ===
+
== Will it get faster? ==
 +
 
 +
'''Yes!'''  The next plan is to have '''equationReader''' ''compile'' your equations at runtime.  In theory, they will execute as fast as a hard-coded solution, less a small amount of overhead with the function call.
 +
 
 +
== Parsing and evaluating ==
 
There is a difference between ''parsing'' and ''evaluating''.  When the equation is first read, it is a ''human-readable'' string expression.  '''equationReader''' translates the ''human-readable'' form into an ''operation list''.  This is ''parsing''.  To calculate the result, '''equationReader''' does a <tt>forAll(operations, i)</tt>.  This is ''evaluating''.
 
There is a difference between ''parsing'' and ''evaluating''.  When the equation is first read, it is a ''human-readable'' string expression.  '''equationReader''' translates the ''human-readable'' form into an ''operation list''.  This is ''parsing''.  To calculate the result, '''equationReader''' does a <tt>forAll(operations, i)</tt>.  This is ''evaluating''.
  
 
''Parsing'' happens only once, and is slow.  ''Evaluating'' happens at every cell index, at every timestep (or however you've used it), and it is fast.
 
''Parsing'' happens only once, and is slow.  ''Evaluating'' happens at every cell index, at every timestep (or however you've used it), and it is fast.
 
=== Burn all conditionals ===
 
Conditionals are slow.  In the framework of '''equationReader''', one <tt>if</tt> or <tt>switch</tt> slows a single equation operation by about 25%.  A word comparison - that slows things by over 1600%.
 
 
'''equationReader''' has a design philosophy: put no conditionals in the way of an <tt>evaluate</tt> function.  To achieve this I implemented a ''function-pointer'' framework.
 
 
=== Function-pointers ===
 
Apparently in C++ you can have pointers to functions.  The syntax looks a little odd:
 
 
        void (Foam::equationReader::*reportScalarOperationFunction_)
 
        (
 
            const label&,
 
            const label&
 
        ) const;
 
 
That's not a function - it's a pointer.  You don't see these too often because C++'s ''virtual functions'' do the same thing - only you need a hierarchy of derived classes.  In theory, ''virtual functions'' have slightly more overhead than ''function-pointers'' because each ''virtual function'' call requires a hash-table look-up, unlike the direct use of ''function-pointers''.
 
 
Anyway, these ''function pointers'' can all be assigned during ''parsing'', and called directly during ''evaluation''.  Essentially this moves all conditionals into the parser, and their result is permanently remembered.  In short: these make '''equationReader''' faster.
 
 
Now, there's not a single conditional encountered during an ''evaluate'' function call.  Even all the <tt>debug</tt> switches have been converted to ''function-pointers''.
 
 
=== Function objects ===
 
Apparently ''function-pointers'' are old-school, and the next best thing are ''function-objects'', or "''functors''".  ''Function-objects'' are better because they can be inlined, unlike ''function-pointers''.  Well, I didn't get the memo until it was too late for this version.  Maybe in another version.
 

Revision as of 20:19, 26 September 2011

1 How fast is equationReader?

The most recent version of equationReader (Version 0.5.0, released September 25th, 2011) handles fields roughly 10x faster than the previous version. Overall, equationReader now takes approximately 5.87 times longer than a hard-coded solution when handling GeometricFields. That's for a simple equation. For more complex equations, equationReader's performance improves.

Straight up scalars are still much slower. I haven't benchmarked the latest version, but previous versions were coming in at around 300 x slower.

2 Will it get faster?

Yes! The next plan is to have equationReader compile your equations at runtime. In theory, they will execute as fast as a hard-coded solution, less a small amount of overhead with the function call.

3 Parsing and evaluating

There is a difference between parsing and evaluating. When the equation is first read, it is a human-readable string expression. equationReader translates the human-readable form into an operation list. This is parsing. To calculate the result, equationReader does a forAll(operations, i). This is evaluating.

Parsing happens only once, and is slow. Evaluating happens at every cell index, at every timestep (or however you've used it), and it is fast.