Controller Loading - Calc Blocks

I have been told that Calc blocks take up a lot of processing power compared to other blocks, but I can't find any sort of relative comparison.

For instance how many math blocks would use the same processing power as a Calc block? What about action or condition blocks? Ideally I would like to find a table that assigns a value to the processor requirements for each block even if it is just a rough estimate. Does such a thing exist?

  • I should also mention we are using 11.3 on S-Series hardware, in case it matters

  • In reply to Ryan B:

    Ever try the Controller Load Estimator Tool? See books online - Recommended Practices for Configuring Controllers

    I have had this debate before, and from experience I can tell you that calc blocks have been given a bad reputation with regards to loading.  If you need to do a single, simple mathematical or logical function then using a calc block is indeed overkill.  However, you usually need a calc block because you have some rather complicated logic (where wiring together strings of math and logic blocks is significantly more convoluted). In most situations I find that even 5 arithmetic or logic blocks produce more load than 1 calc block, and are more complicated to maintain (scan order etc.)  Others argue a calc block is harder to troubleshoot, visually, but I would argue that debug logic configuration can be added to a calc block rather easily to output watch values.

    The simplest test is to create 1 module for each function block type and drop a single function block in it.  Then perform a comparison on the EXEC_TIME param.  I would try with no expression, and then with 1 single expression accomplishing a simple task, e.g. reading or writing a value, performing arithmetic.

  • In reply to Youssef.El-Bahtimy:

    The thing to realize about a CALC block is that the code is not compiled, but interpreted by the processor. FB's are compiled algorithms.  In addition, floating point math done in the CALC block uses 32 Bit precision, while compiled blocks, such at the INTEGRATOR block uses double precision for the accumulated value.  If you write a 3rd or 4th order polynomial in teh CALC block, the 32 Bit resolution will likely affect curve accuracy, while a signal characterizer block will handle inflections efficiently and with excellent accuracy.  

    The main thing is that if a block already exists, it will be more efficient than an Expression.  When multiple blocks are needed, there is a cost in CPU and memory to wire signals between them.  Not much, but it adds up.  For troubleshooting, it makes sense to build functions into calc blocks and connect these together, rather than build large single CALC blocks.  It is a balance between visuallizing the strategy, reusability of the code.  You can build some pretty complex algorithms in a CALC block.

    So where an existing FB does the work, use it.  Complement them with CALC, Condition and ACT blocks.  For sequencing, you can use SFC's, though if a decision tree needs to be passed in a single exeuction of the module, a CALC block with IF-THEN-ELSE statements might be better.  Boolean logic is more visual with blocks, but bitwise operations are available in the CALC block.

    It's all about choosing the right solution for the problem. Some might be tempted to look at the CALC block as the way to solve any problem.  I sort of look at it as the last resort, for those things that aren't already solved with existing Function Blocks and structures in DeltaV.  Its a power tool, but you shouldn't fix your glasses with a DeWalt Hammer Drill...

    Andre Dicaire

  • In reply to Andre Dicaire:

    As mentioned earlier, EXEC_TIME is the key to comparing any given module’s loading impact versus another.

    With any function block that utilizes an expression, the expression should be adequately designed to handle any and all possible status values on the input.  A much too common error is to write the expression only for optimal conditions and ignoring the possibility of ever encountering an input with a less than good status.  For a true comparison against any given function block, that expression should also be handling status.  Granted one can take the easy way out and just enable the abort on read option, but that option doesn’t always result in the needed functionality either.  Bottom line, if you go the expression route in a CALC, ACTION, CND block (and SFC actions & transitions), handle the status properly.

    To follow up Andre’s post, if you do need the hammer drill, use it properly; wear your safety glasses and don’t defeat your safety ground.

  • In reply to Randy Pratt:

    Unless it has changed in recent revisions, the EXEC_TIME will only be a reliable value if the module is running as High Priority (100 or 200ms).

    If you have to use calc logic, you could use the ACT block which is a little less loading than a CALC block and will function the same way if the IN_D parameter is True except it doesn't have Inputs and Outputs that can be wired. If the IN_D is False the expression logic is not executing which is less execution time. The draw back with this is that it is a little harder to troubleshoot the logic because you can't see and inputs and outputs when online.

  • In reply to Matt Stoner:

    I have not found the EXEC_TIME to be a very reliable measure for loading due to blocks in a module.  It may have been corrected, but with the 7.x to 9.x versions, the EXEC_TIME for a module changed depending on what else the controller was being asked to do.  It also changes from scan to scan especially when linked composites are used in a module.  Because of that, the only way we found to measure efficiency of one configuration technique versus another was to load an unused controller with dozens of instances of a module and record the CPU free time.  When we were checking CALC blocks, loading the same calculation in a CALC block, an ACT block, or separate math blocks did not seem to make that much difference.  What did make a big difference were IF statements.  At least in those versions of DeltaV, IF statements were very heavy.  For example IF X > 10 THEN Y = 1 ELSE Y = 2 is much heavier than the equivalent Y := X > 10? 1: 2 (although it is more readable ;-).  In some case we found that the loading was higher after we added an IF statement to skip some multi-statement calculation when the calculation was not needed.  It actually saved CPU to just perform the multi-statement calculation on every scan.  Go figure!

  • In reply to carllemp:

    Certainly the EXEC_TIME must be interpretted and Carl's suggestion to use multiple instances of a module in a controller rather than just one to determine loading of a given module design.  The EXEC_TIME is a straight look at the Start time and End time of the module execution.  Medium and low priority modules can be "interupted" by higher priority tasks, and therefore their EXEC_TIME becomes skewed, even though their actual CPU usage is the same for all instances.  So if you load a dozen or so modules, through out the higher values that are out of line with the majority, as these indicate the module was interrupted.  

    Randy mentioned that High Priority modules have an accurate EXEC_TIME, and this is because they aren't interrupted by the tasks that affect medium and low priority modules.  In theory, the EXEC_TIME of a module should be the same, no matter its scan rate, but interrupts will extend the EXEC_TIME of affected modules.

    My suggestion is to not worry too much about EXEC_TIME and try to understand the features available in the standard function blocks.  If you need a CALC block, use one, and keep them straight forward. Simpler is better, and more maintainable.  Once you've used up the CPU, you need another controller.  If you are using CHARMS, adding another controller for more CPU is pretty easy.

    Andre Dicaire

  • In reply to Andre Dicaire:

    100% percent agree with Andre. Always try to implement functionality by using function block features and code as the last option. As rule of thum, less code is better.

  • In reply to Andre Dicaire:

    Just to clarify.
    - CM can be interrupted in the middle of the FB exec order by other high priority CM? Is that true?
    In that case have to consider the stability of input/output data, if a high priority CM maybe deliver or read data to/from that medium prio CM.
    Internal struggle if this data is used at several places along the medium priority CM FB execution order. Especially with pulses.
    - How does it works with big CMs , if they maybe can't pass into one time slice of their task priority?
    Sometimes can find such mega modules in projects with a lot of Calc-FB or other huge logics (EQM with embedded CM) :-(
    I heard that every different task (i.e. 1sec) is also split into several time slices from the total internal CPU execution order
    They might be:
    a) split into two execution parts
    b) will the actual time slice for that individual CM run a bit longer? ( to make the view easier, consider only 1sec CM in that controller for the answer)
    For a) , would the interrupted CM be executed further at next or could be that other CM on the same priority run in between that interrupted one?
    Multi-Tasking can make your brain spinning :-)

    The problem can occur, that IF/THEN/ELSE in expression blocks produces different exec-times if the THEN part is much bigger than the ELSE part or Actions run all together for one time during execution. (-> data integrity over the complete CM execution time)

    .-.

    Anyway regarding EXEC_TIME I confirm to Carl Lemp. I have tested diverse constellation of logic by creating the test logic into a composite , add as many composites into one module (-> FB-COUNT <250) and then add as many copy of that modules into an empty test controller until that one start to burn. Check the FRETIM (M-Series) or Control-Expansion (S-Series). There was not always a similar correlation between the Ctrl-Load and Exec-Time of the different solution. But it is good enough for an estimate if the EXEC_TIME is significant different.

    .-.

    From my experience Calc block are not so bad as everybody tell about. There are several ways to tune IF/THEN/ELSE blocks and the Inline IF ( cond ? then : else) is often a good alternative.
    IF VariableA=TRUE
    THEN VariableB := TRUE;
    ELSE VariableB := FALSE;
    can be reduced simply to VariableB := VariableA (don't laugh, I have seen such code many times)
    The very best I have seen was
    IF VariableA=TRUE THEN VariableB := TRUE; ENDIF;
    IF VariableA=FALSE THEN VariableB := FALSE; ENDIF;
    BTW: Eliminate the ".CV" in '^/VARIABLE.CV', use as '^/VARIABLE' save you some byte in the expression.

    .-.

    A last word to the Emerson-Development Team: When do we can compile on our own whole user defined composites, once they are tested, to a new FB?
    Execution might be faster and development knowledge get saved. To make composites invisible is not the option, or let them really closed (no drill down).