Table Of Contents

Separating Tasks to Optimize a Real-Time Application

    Last Modified: April 18, 2016

    Task separation involves running distinct tasks in parallel loops to create a multirate application.

    Separating tasks provides the following benefits:

    • Improved Determinism—To minimize jitter in a deterministic loop, ensure that the loop does not contain potentially non-deterministic code.
    • Improved CPU Efficiency—CPU efficiency is a common design constraint in real-time applications. By running tasks in separate loops at distinct rates, you can maximize CPU efficiency by executing each task only as often as necessary.

    Complete the following steps to separate the tasks you want to run on the real-time controller.


    The tasks and execution rates of those tasks are entirely dependent upon the goals and requirements of your application. The following steps provide some examples, but you must determine the tasks and execution rates that are right for your application.

    1. Without writing any actual code, determine the high-level tasks your application must perform.

      For example, your application might require the following tasks:

      • Control—Control the temperature and level of liquid in a tank.
      • Log—Log a historical record of the temperature and level data collected. The requirement for this task is to log every process variable value collected by the control task.
      • Monitor—Transfer user interface data over the network to receive commands from the user and display continuous data graphs that the user can monitor.
    2. Determine the minimum rate at which each task must execute. If you are uncertain about the rates you need for each task, consider using estimates until you are able to deploy and benchmark the code to create a time budget.

      Continuing the previous example, the tasks require the following minimum rates:

      • Control—The minimum rate for this task is 1 kHz. This translates to a period of 1 ms.
      • Log—There is no minimum rate requirement for this task. In this example, the period is 200 ms.
      • Monitor—The minimum rate for this task is 10 Hz. This translates to a period of 100 ms.
    3. Define the data transfer relationships among the tasks in your application.

      The following image illustrates the data transfer relationships among the tasks from the previous example.

    4. Translate your design into code. Organizing your code so that each task loop runs in a separate subVI helps to keep your application easily readable.
      1. Create a separate subVI for each task you outlined in the previous steps and add the appropriate task loop to each subVI based on whether you want the task to be deterministic.

        Continuing the previous example, use loops as described for the following tasks:

        • Control—Because you need this task to execute exactly every 1 ms, use a Timed Loop.
        • Log—Because this task is not time-critical, you can use a While Loop with a Wait node instead of a Timed Loop.
        • Monitor—Because you don't need this task to execute exactly every 100 ms as long as it executes 10 times per second, you can use a While Loop with a Wait node instead of a Timed Loop.
      2. Create an initialization subVI to handle preliminary tasks that need to occur before your ongoing tasks, such as opening file references and preallocating arrays.
      3. Create a shutdown subVI to switch your application to a shutdown state before turning off your real-time system. A shutdown routine might include the following actions:
        • Setting outputs to known values
        • Closing file references
        • Notifying the operator when they can turn off the real-time system

      The following image illustrates the top-level real-time VI that includes the tasks defined in the previous example.

    Recently Viewed Topics