Multitask, Concurrent Execution und OpenMP
In Simulink® können Sie Ihre Modelle für die Ausführung auf Multicore Target Systemen konfigurieren. Details entnehmen Sie dazu der MathWorks®-Dokumentation. Beckhoff Targets bieten in der Regel eine Multicore-Architektur, welche mit TwinCAT 3 effizient genutzt werden kann. Dies ist auch mit dem TwinCAT Target for Simulink® möglich, wie im Folgenden gezeigt wird.
Es wird in dieser Beschreibung unterschieden zwischen Multitask, Concurrent Execution und OpenMP.
- Bei Multitask wird ein TcCOM-Objekt erzeugt, welches mehrere Tasks zur Verfügung hat. Alle Tasks müssen auf demselben Core ausgeführt werden. Es wird nicht parallelisiert.
- Bei Concurrent Execution wird ebenfalls ein TcCOM-Objekt mit mehreren Tasks erzeugt, die auf unterschiedlichen Cores verteilt werden können. Rechnungen können tatsächlich parallel ausgeführt werden.
- Bei OpenMP wird ein TcCOM-Objekt mit einem Task-Kontext erzeugt. Darüber hinaus können mehrere JobTasks, die auf unterschiedlichen Cores verteilt liegen, die Code-Fragmente parallelisiert ausführen, welche als OpenMP-Code generiert wurden.
Multitask und Concurrent Execution
Für die Beschreibungen zu den Optionen Multitask und Concurrent Execution wird das folgende Multirate System in Simulink® betrachtet. Das Modell besitzt eine explizite und eine implizite rate transition.

Wählen Sie unter Configuration Parameters den Punkt Solver aus. Hier können Sie auswählen zwischen:
- Treat each discrete rate as separate task
- Allow tasks to execute concurrently on target

Treat each discrete rate as separate task: Multitask
Wird ein TcCOM-Objekt mit aktivierter Option Treat each discrete rate as separate task erstellt, erhalten Sie ein Objekt, welchem Sie mehrere Task-Kontexte zuweisen können. In diesem Fall 3 Tasks.

Die Ein- und Ausgänge sowie alle weiteren DataAreas werden in die unterschiedlichen Kontexte geteilt, sodass in diesem Fall 3 Input DataAreas und 3 Output DataAreas existieren.

Die zyklischen Tasks müssen in diesem Fall alle auf demselben Core gelegt werden. Es findet keine parallele Verarbeitung der Tasks statt.
Der Vorteil gegenüber einem TcCOM mit nur einem Task-Interface liegt darin, dass nun nicht alle Berechnungen innerhalb der schnellsten Task-Zykluszeit abgeschlossen werden müssen (siehe Scheduling). Würde obiges Simulink-Modell mit Standardeinstellung ohne Treat each discrete rate as separate task erstellt werden, wäre nur eine Task mit 10 ms (schnellste Task) verknüpfbar. Das bedeutet, dass dann alle Rechnungen innerhalb dieser Zeit abgeschlossen werden müssen. Durch Verteilung auf mehrere Tasks auf demselben Core, wird diese Regel außer Kraft gesetzt, da Tasks sich gegenseitig unterbrechen können (siehe Prioritäten).

Eigenschaften:
- Es wird kein Funktionsbaustein in der PLC unterstützt.
- Die TwinCAT Usermode Runtime wird nicht unterstützt.
- Alle Tasks sind demselben Core zugewiesen.
- Der schnellsten Task muss die höchste Priorität (kleinster Priority-Wert) zugewiesen werden. Der zweitschnellsten Task die zweithöchste Priorität usw.
Scheduling Details:
Untere Grafik beschreibt ein Beispiel, wie die Rechenzeiten verteilt sein können. Die schraffierten Flächen zeigen an, dass in dieser Zeit eine Task durch eine höher priorisierte Task nicht arbeiten darf. Die volle blaue Fläche zeigt an, dass die Task arbeitet. Beachten Sie, dass die Flächen nur zur Förderung der Verständlichkeit nachträglich über die Realtime Monitor Aufnahme gelegt wurden und keine realen Aufnahmen sind.
- In Tick 1 werden Task 2, Task 3 und Task 4 nacheinander auf demselben Core ausgeführt. Die Ausführung von Task 2 und Task 3 laufen dabei ohne Unterbrechung. Die Ausführung von Task 4 wird von der höher priorisierten Task 2 im Übergang zu Tick 2 unterbrochen.
- In Tick 2 wird zunächst Task 2 ausgeführt. Die Ausführung von Task 4 wird nach Beendigung von Task 2 wieder aufgenommen.
- In Tick 3 beginnt wieder Task 2 und es folgt Task 3.

Falls es zu Zykluszeitüberschreitungen kommt und das Scheduling nicht eingehalten werden kann, wird die Ausführung des jeweiligen Task-Kontexts so lange übersprungen, bis alle relevanten Kontexte im passenden Zustand sind. Im TcCOM-Objekt kann dieses Verhalten über den Online-Parameter SkippedExecutionCount
beobachtet werden.
Allow tasks to execute concurrently on target: Concurrent Execution
Wird ein TcCOM-Objekt mit aktivierter Option Allow tasks to execute concurrently on target erstellt, erhalten Sie ein Objekt, welchem Sie mehrere Task-Kontexte zuweisen können. In diesem Fall, wie im obigen Beispiel, 3 Tasks.
Auch hier werden die DataAreas aufgetrennt in die unterschiedlichen Kontexte. Unterschied zum Multitask-Objekt ist, dass Sie nun die Tasks auf unterschiedliche Cores verteilen können, sodass die Abarbeitung tatsächlich parallelisiert wird.

Eigenschaften:
- Es wird kein Funktionsbaustein in der PLC unterstützt.
- Die TwinCAT Usermode Runtime wird unterstützt.
- Tasks können unterschiedlichen Cores zugewiesen werden.
- Der schnellsten Task muss die höchste Priorität (kleinster Priority-Wert) zugewiesen werden. Der zweitschnellsten Task die zweithöchste Priorität usw.
Scheduling Details:
Untere Grafik beschreibt ein Beispiel, wie die Rechenzeiten verteilt sein können. Die volle blaue Fläche zeigt an, dass die Task arbeitet. Beachten Sie, dass die Flächen nur zur Förderung der Verständlichkeit nachträglich über die Realtime Monitor Aufnahme gelegt wurden und keine realen Aufnahmen sind.
- In Tick 1 werden Task 2, Task 3 und Task 4 parallel auf unterschiedlichen Cores ausgeführt. Die Ausführung von Task 1 muss bis zu Beginn von Tick 2 beendet sein.
- In Tick 2 wird Task 2 wieder ausgeführt. Task 3 und Task 4 dürfen weiterhin arbeiten. Die Ausführung von Task 2 und Task 3 muss bis zu Beginn von Tick 3 beendet sein.
- In Tick 3 werden Task 2 und Task 3 wieder ausgeführt. Task 4 darf weiterhin arbeiten. Die Ausführung von Task 2 und Task 4 muss bis zu Beginn von Tick 4 beendet sein.

Falls es zu Zykluszeitüberschreitungen kommt und das Scheduling nicht eingehalten werden kann, wird die Ausführung des jeweiligen Task-Kontexts so lange übersprungen, bis alle relevanten Kontexte im passenden Zustand sind. Im TcCOM-Objekt kann dieses Verhalten über den Online-Parameter SkippedExecutionCount
beobachtet werden.
OpenMP
Der Simulink CoderTM bzw. der MATLAB CoderTM können openMP Code erzeugen. In welchen Fällen das genau passiert, entnehmen Sie bitte der MathWorks®-Dokumentation.
Im Folgenden wird ein Beispiel mit einer MATLAB® Function in Simulink® betrachtet. Ein MATLAB®-Beispiel finden Sie in Verbindung mit dem TE1401 TwinCAT Target for MATLAB® in den Beispielen:
TwinCAT.ModuleGenerator.Samples.Start('Code parallelization with OpenMP').

In der MATLAB® Function wird das parfor-Kommando genutzt, um die for-Schleife zu parallelisieren. In diesem Fall wird die Anzahl der parallelen Worker auf 4 begrenzt.
function y = MyFunction(u) %#codegen
A = ones(20,50);
t = 42;
parfor (i = 1:10,4)
A(i,1) = A(i,1) + t;
end
y = A(1,4) + u;
Für das TwinCAT-Target sind keine besonderen Einstellungen hinsichtlich openMP vorzunehmen. Sie generieren Ihre TwinCAT-Objekte wie gewohnt. Der Simulink Coder übersetzt diese Code-Stelle in openMP Code, sodass das der C/C++ Code entsprechend auch parallelisiert wird. Der Embedded Coder wird für dieses Feature nicht benötigt.
In der TwinCAT XAE können Sie nun das erstellte TcCOM oder den PLC-FB instanziieren und entsprechend konfigurieren. Die Objekt-Instanz bietet unter dem Reiter Context wie gewohnt nur ein zyklisches Task-Interface an. In diesem Beispiel wird eine Task 2 mit 200 ms Zykluszeit erstellt und dem Objekt zugewiesen.
Unter Parameter (Init) befindet sich ein Parameter JobPoolID. Hier wird, soweit durch den C/C++ Code bekannt auch angezeigt, wie viele Worker parallel arbeiten können. Ein JobPool ist eine Organisationseinheit für JobTasks, welche im Knoten Tasks angelegt werden können.

Es ist entsprechend unter TcCOM Objects mit „Add new item“ ein Objekt von Typ TcJobPool hinzuzufügen. Unter Parameter (Init) auf dem TcJobPool-Objekt ist die JobPoolId einzutragen und eine Gruppe von JobTasks zu referenzieren. Definieren Sie zunächst wie viele JobTasks der Pool zusammenfassen soll und wählen Sie dann mit dem Drop-Down-Menü die JobTasks aus.
Unter System > Realtime können Sie JobTasks auf unterschiedliche Cores verteilen.

Die Ausführung in der oben abgebildeten Konfiguration findet dann wie folgt statt. Task 2 wird auf Core 4 ausgeführt und triebt zyklisch das openmp-Objekt an. Die Codefragmente die als openMP Code generiert wurden, können dann über den JobPool Aufgaben an die konfigurierten JobTasks auslagern. Haben die JobTasks mit ihren Berechnungen beendet werden alle Teilergebnisse wieder gebündelt und Task 2 auf Core 4 führt den Code zu Ende aus.