In Process Simulate SCL scripts execute periodically. The period is provided by the sampling rate - "LB update rate" as we know it. Users can configure it in the range from 10ms to 100ms. This is quite limiting since cases that require faster update rate cannot be covered. Also when changing the sampling rate the whole study logic starts to work at this rate. Often what users need is to make specific logic work at a faster rate while the rest works at the 'normal' rate. So we should kind of have two or more update rates during simulation... and not only that - the faster update rate should not slow down the rest of the simulation... this inevitably leads to multi-threading. However there is a catch here: Time synchronization. e.g. we should make sure that each thread that we run shares the simulation time and is in sync with it. You see. This makes the task quite challenging.
The solution in our case is the ability to run SCL scripts concurrently at a higher update rate. This is a new feature in development (v2408 EAP). You enable it with a toggle button in SCL editor. The update rate (ms) for the script is specified in the spin control next to it.
When enabled the script will be executed by a dedicated thread. The thread invokes the script periodically until it reaches the next time sync point. The (main) thread running the simulation sets the time sync points on LB update rate intervals. In short for the time of a single LB update rate the script is called multiple times (number of calls = LB update rate / script update rate).
Next I would like to discuss why the time should be synchronized between all threads.
Imagine the situation where time is not synchronized and the main thread is faster than the SCL thread (T0 > T1). In this case the main thread will see old values (R3) for the calculations done in the SCL thread. In the case where the SCL thread is faster (T1 > T0), the main thread will see values from the future. In both cases we have a time drift and the values won't be correct. e.g. they cannot be related to time in the main thread.
When the time is synchronized the values from the SCL thread can be related to time in the main thread.
Now the bad news: Time synchronization does have a cost - it ruins the performance that we tried to gain by using multiple threads on the first place. This is due to the fact that the main thread has to wait (suspend until a condition is met) for other threads to reach the same time. This we cannot avoid. Waiting is always a problem with time critical code. In general we should not wait at all if we want to keep the timing correct. This is our approach as well. However if we do not wait the CPU consumption will never settle down. Not only because the script is execute more rapidly but also because of the busy waiting (spinning) that should happen between threads. In other words: Time critical scripts consume more CPU time compared to regular scripts. This is the price we have to pay to achieve the higher sampling rates.
The performance penalty depends on:
1. The execution time of the script (real time)
2. The update rate of the script (virtual time)
3. LB update rate (virtual time)
4. Number of time critical scripts
Roughly you can expect this kind of performance:
Script time < Script update rate - faster than real-time
Script time = Script update rate - real-time
Script time > Script update rate - slower than real-time
This kind of oversampling solution has another drawback - signals connected to the script are exchanged only at a sync point. Meaning that the values are exchanged using the sampling rate of the main thread. This seems like a pretty natural thing to do since the main thread cannot handle them faster anyway. The problem however is that we loose data. On the picture above we loose the ramps for example. The main thread will only see under sampled values (R1, R2 & R3). For the user this is one more limitation. Only the time critical script will see the actual values.
This limitation also means that signals can be exchanged reliably between the main thread and the time critical script. The opposite is also true. However if you try to exchange signals bi-directionally (in/out) across threads the results may be unpredictable.
When you activate this mode the SCL editor notifies you that Process Simulate specific SCL functions will fail.
Why is that? Process Simulate has always been a single threaded application. Most of the functionality inside is not thread safe. This is the reason for blocking the functions. They simply will crash if you use them in from another thread.
Wait! If we cannot use the functions then what can we do with a time critical script?
Short answer is: Complex logic + external connections.
Long answer is: You can work more closely to a PLC, ensuring fast response times to complex problems.
You may probably ask: Why do we even bother with all this? It seems like there are many limitations.
Well... all this was implemented because of the use case of drive simulation. Drive simulation is quite time sensitive and accurate timing requires fast update rates. It is also quite heavy in terms of processing time. Multi-drive simulation is even harder to get done correctly. The aim is to move this complexity to a set of time critical scripts running concurrently to the simulation.
There are probably other use cases that may benefit from the same idea. I can imagine handling acyclic PLC requests (RFID readers, barcode readers, imaging devices) in the background for example. Actually any script that takes a lot of time can be moved to another thread. Will it be faster this way? It depends...
Multithreading often brings a lot of limitations with it. Especially if you rely on shared state (which is inevitable). The approach with scripting fits quite naturally here since scripts are generally thread safe. The shared state in Process Simulate is the real issue. By 'shared state' I refer to the object model driving the study. This includes parts, resources, kinematics, OLP etc. All these are just not designed for multi-threading. What a pity...
I can imagine this limitation to be solved one day but it is not a trivial thing to do for sure. For now we should live with it. This is why the whole feature stays behind a feature toggle (TIME_CRITICAL_SCL_SCRIPTS)
Try it and see how it works.
See you in the next one.
Comments