Using Devices Multiprocessing navigation bar

Table of Contents > QUARC > User's Guide

Multithreading

Unlike many other real-time products, QUARC fully supports multithreading. Multithreading refers to the ability to run multiple threads of execution. QUARC supports multithreading in a variety of contexts. The most transparent way in which QUARC supports multithreading is in its handling of multi-rate models. A multi-rate model is a Simulink diagram containing blocks with differing sample times. For example, a diagram may contain a fast control algorithm running at 1 kHz and a slower trajectory planning algorithm running at 100 Hz. Since there are two different sample times in the model, QUARC can be configured to automatically create two separate threads - one for each sample rate.

QUARC also provides a powerful new form of multithreading called asynchronous threads. QUARC allows the user to create their own threads in the model using QUARC's Asynchronous Thread block. These threads, however, do not have any sample rate at all - they run completely asynchronously and are aperiodic. Such asynchronous threads are useful for communications, for worker threads or for idle-time processing and are an advanced feature of QUARC.

This page provides information about the multithreading capabilities of QUARC. Please use the following list to refer to each topic:

Multithreading of a Multi-Rate Model

In external mode, two threads are created in the real-time code for communication between the real-time code and the Simulink model. The model itself runs in a third thread at higher priority. Therefore, even a single rate model may contain multiple threads. However, our focus will be on multi-rate models. In QUARC's default mode of operation it divides the blocks in the diagram into groups according to their sample time. For example, in a diagram containing a 1 kHz control algorithm and a 100 Hz trajectory planning algorithm, the blocks running at 1 kHz will be grouped together and run in one thread while the blocks executing at 100 Hz will be grouped into a second thread. The faster 1 kHz thread will be assigned a higher priority so that the slower 100 Hz thread does not interfere with its time-critical execution. QUARC is not limited to two sample rates - it will create separate threads for every sample rate in the model and set the priorities of these threads in ascending priority - the faster the sample rate, the higher the priority of the associated thread. On a CPU with multiple cores, these threads may execute concurrently.

This behaviour may be changed through a parameter called Tasking mode for periodic sample times in the Solver pane of the Configuration Parameters dialog. The tasking mode determines the manner in which multi-rate models are run by QUARC in real-time. The tasking mode may be configured as either single-tasking (running the model in one thread) or multi-tasking (multithreading in real-time and task prioritization in normal simulation). By default, this parameter is set to Auto. In this case, QUARC decides whether to use multithreading based on the number of sampling rates in the model. If the model has multiple sample rates then multiple threads are employed. Otherwise a single thread is used for executing the blocks in the model. The tasking mode does not affect whether threads are created for external mode communications. In normal simulation, this default value causes Simulink to decide whether to use task prioritization for a model, again based on the number of the sampling rates in the model. For more information on this parameter, please refer to the Configuring a Model section of the QUARC documentation.

In normal simulation, multithreading cannot be performed because Simulink does not support this feature. A multi-rate model is run in a single thread and blocks are executed sequentially according to task prioritization. In the above example, Simulink simply runs the 100 Hz blocks every 10th sampling instant of the simulation.

In order to understand multithreading and its benefits compared to single-tasking mode or Simulink's task prioritization, consider the following example. Suppose the model has two sampling rates or tasks: T1 executing every 1 ms and T2 executing at a 3 ms sample period. The base sample rate is the faster of these two, task T1. Suppose that the computation times for T1 and T2 are 0.2 and 2 ms respectively. Our system consists of a single core CPU, meaning that no more than one thread can be run at the same time.

Multithreaded multi-tasking mode with a single CPU

With multithreading, two separate threads are created by QUARC, with one running at 1 ms and the other one at 3 ms. Task T1 is assigned to one thread and task T2 is run in a second thread. The first thread (T1) has higher priority than the second thread (T2). This scenario is illustrated in the timing diagram below:

Multithreaded timing

When the model starts running, T1 gets executed and prevents the execution of T2. After 0.2 ms, T1 finishes its computations and T2 starts executing. After T2 has been running for 0.8 ms, the second sampling instant of T1 occurs. At this time, T1 starts execution and interrupts T2. At 1.2 ms, T1 again finishes executing and T2 resumes execution to run for another 0.8 ms. Once again, the next sampling instant of T1 occurs and interrupts T2. T1 executes for 0.2 ms. At 2.2 ms, T1 finishes executing and T2 again resumes until it completes the last 0.4 ms of its computations at 2.6 ms. At 3 ms, the entire sequence repeats itself as both T1 and T2 have a sampling instant at 3 ms. In this way, T1 interrupts T2 whenever it needs to execute because it has higher priority. As a result, no sampling instant is missed for T1 and the latency in its response is kept to a minimum. Likewise, T2 does not miss any sampling instant either because it can still complete its computations over the 3 ms sampling interval, even with the interrupts from T1. The key point is that T2 can resume execution after being interrupted by T1 due to the use of multiple threads. While the execution of T2 is delayed by 0.2 ms from its intended sampling instant, that delay is not cumulative and remains consistent provided the computation time of T1 does not change. Hence, the jitter in T2's sampling rate is also kept to a minimum.

Single-tasking mode with any number of CPUs

Now consider single-tasking mode. In this mode, only one thread is created for executing the blocks in the model, even when there are multiple sample rates present. Thus, task T1 and T2 both must run in the same thread. The same is true for the task prioritization scheme used by Simulink in normal simulation. The blocks are still grouped into different "tasks" according to their sample times, but these tasks are all executed in a single thread. The task with the sampling time of 1 ms (T1) is assigned a higher priority while the task with the sampling time of 3 ms (T2) is given a lower priority. This single-threaded scenario is depicted in the timing diagram below:

Single-threaded timing

When the model starts running, T1 starts executing because it is the higher priority task. At the 0.2 ms mark, when T1 has finished its computations, T2 starts executing. Unlike QUARC's multithreading implementation, T2 continues to execute until 2.2 ms. Note that T1 cannot interrupt T2 since they are not separate threads. At 2.2 ms, T1 starts executing for the second time. However, notice that T1 has missed an entire sampling instant ! The missed sampling instant is illustrated by the red cross-hatched areas in the timing diagram. Depending on the implementation, this sample will either be missed entirely or T1 will be executed twice in quick succession as shown by the blue cross-hatched area. Either way, T1's sampling rate is effectively only 2 ms now, instead of the desired rate of 1 ms! T2 is not scheduled to run again until the 3 ms mark since T2 has a 3 ms sampling period. At the 3 ms mark the entire sequence repeats itself. Thus, the single-threaded paradigm can result in missed sampling instants due to the fact that tasks cannot be interrupted. To ensure there are no missed sampling instants, there is a restriction on the computational time of T1 plus the computation time of T2. This combined computation time must be less than the sampling time for T1. The general rule for the single-threaded implementation may be expressed as follows: the sum of the computation times of all tasks should be less than the fundamental sampling time . Clearly, this restriction does not apply to models running in multiple threads. This example demonstrates the superiority of QUARC's multithreaded mode of model execution, even for a single CPU platform.

Multithreaded multi-tasking mode with a dual core CPU

Hint Now, consider a system with a dual core processor. In this scenario, two threads are able to run simultaneously, with each thread executing on one of the cores. In our example, the two separate threads may run on the two CPU cores using multithreading and no interruptions occur at all. On the other hand, in single-tasking mode or normal simulation there is only a single thread of execution that would therefore run on only one of the CPU cores. Thus, the process cannot exploit the extra CPU core. This distinction makes QUARC's multithreading far superior to those real-time products that are restricted to a single thread and to the task prioritization scheme used by Simulink in normal simulation.

For targets supporting multiple cores or CPUs, QUARC provides even more flexibility. QUARC allows the set of allowable CPUs to be specified explicitly. Thus, it is possible to restrict a model to run on only a subset of the CPU cores available. For example, it is possible to limit a model to only run on CPU 0 and CPU 2 on a quad-core system. Refer to the Model affinity field of the Code Generation/QUARC tab of the Configuration Parameters dialog for more details.

Asynchronous Threads

QUARC provides a set of blocks with which you can create asynchronous or aperiodic threads and transfer data between the asynchronous threads and the synchronous or periodic threads of the main Simulink diagram. With this blockset, QUARC allows the user to create their own threads in addition to the threads created for multiple rates in the model, hence taking even greater advantage of the multithreading capabilities of QUARC. These blocks may be found under the

QUARC Targets/Advanced/Asynchronous

MATLAB Command Line

Click to copy the following command line to the clipboard. Then paste it in the MATLAB Command Window:

qc_open_library('quarc_library/Advanced/Asynchronous')
library in the Simulink Library browser. This section describes three of those blocks: Asynchronous Thread, FIFO Read and FIFO Write.

The Asynchronous Thread block executes the Function Call Subsystem attached to its output in an asynchronous thread. The thread is created at model start, but does not begin to run until the first execution of the Asynchronous Thread block to ensure that the entire model is initialized prior to the execution of the thread. Thus, if the Asynchronous Thread block is placed in a conditionally executed subsystem then the thread will not begin to run until that subsystem executes for the first time. Execution of the asynchronous thread continues until every block in the Function Call Subsystem has completed execution (unless some are excluded by conditionally executed subsystems), at which point the thread exits. The Asynchronous Thread block can also be configured to run the associated thread every time the block executes. In this case, the attached Function Call Subsystem acts like a "worker thread" that can be activated each time the Asynchronous Thread block runs. For more information about this block, please refer to the Asynchronous Thread block reference page.

The FIFO Write block writes to a FIFO queue every time the block is executed. The name of the block determines the name of the FIFO queue. The name must be unique throughout the diagram. For every FIFO Write block, there should be a corresponding FIFO Read block which reads from the FIFO queue every time the block is executed. To associate the two blocks with the same FIFO queue, simply assign the name of the FIFO queue used by the FIFO Write block to the FIFO Read block. The FIFO queue may then be used to communicate between synchronous and asynchronous threads. For example, it can be used to transfer data back and forth between an asynchronous thread and the main diagram. Just as Rate Transition blocks are required to pass data between blocks of differing sample rates, the FIFO queues are needed to transfer data between asynchronous blocks, which have no sample time, and synchronous blocks which do have a sample time. For more information about these two blocks, please refer to the reference pages for the FIFO Write and FIFO Read blocks.

Limitations

Scopes and Asynchronous Threads

Warning Note that the Function Call Subsystem attached to the Asynchronous Thread block cannot contain any display blocks, such as Scopes, Displays or even To Workspace blocks. Because the designers of Simulink did not conceive of creating asynchronous threads, external mode does not support the streaming of data from asynchronous threads. Parameters within asynchronous threads may still be tuned online however. To plot signals in an asynchronous thread, pass the signals to a display block in the main diagram using a FIFO queue.

Absolute Time in Asynchronous Threads

Warning Note that the Clock and Digital Clock blocks are not supported in asynchronous threads. Simulink Coder does not generate correct code for these blocks, or other blocks that depend upon absolute time, in asynchronous threads because it assumes that all asynchronous subsystems will be attached to a periodic time source, such as an interrupt, which is not the case with asynchronous threads in QUARC. To get the absolute time in an asynchronous thread, use the Time block provided in the QUARC Targets library under the Sources category. The Computation Time and Sample Time blocks supplied by QUARC also work in asynchronous threads, although the Sample Time block reports the time interval between successive executions of the block in this case.

 

navigation bar