So I’m using julia to simulate some systems and develop control algorithms before I will have the hardware available and it’s very cool to be able to use the DifferentialEquations.jl and Cxx.jl together. That lets me develop the control bits in C as would be eventually run on a microntroller (a cool trick I stole from one of the 2019 JuliaCon videos!).
In other applications I want to develop control algorithms when the hardware to be controlled is available, but in a more flexible way than in C land on the microcontroller - so I’m curious what you’re using for I/O to the physical world on your ubuntu box.
One last question - you would like to be able to use julia permanently in your application to do the control rather than port the algorithms to some other platform (e.g. C-code on a microcontroller, or code for a PLC if industrial)?
when using the commands remember to add -a (i think it was taskset) in the options so that all threads of your process are moved to the “closed” core. It gave me a headache to find that out.
i am making a block diagram environment and want to be able to run it everywhere possible, there are PLC:s with rasp-pie as base and I think it is possible to also use the usb port. I haven’t come that far tbh. Do you think i/o from a pc is problematic?
My idea is to run directly from a linux pc, i would like to be able to convert it to C but I think it is too hard for me, i’m a high level language algorithm coder. Maybe in the future my software can create C-scripts also. I don’t like low level languages though…
If my program would be C-compatible I think I would do everything in C, so I would have C-functions and my program would generate a loop with them. This is a future thing though, my focus is high level languages atm and try to come as far as possible with them.
One option for both of us is to use a raspberry pi serving up the gpio over local Ethernet. It really depends on what you need to interface to. I was just curious as to what you had chosen.
That may be, but I don’t think that Julia was designed for hard real time. Well-optimized Julia code may be suitable for what is called “soft” or “near” real-time, but hard RTC is currently beyond the scope of the language, and I don’t think it is achievable without breaking or restricting Julia so much that it will be a different language.
Julia was not designed for this market at all. In a sense, it targets the opposite end of the spectrum: interactive or batch scientific computing, where expressiveness, code reusability, quick prototyping and optimizing on demand are valued, and GC considered a very convenient feature.
Languages for RTC come with specific guarantees, but are much less fun to program in. If you really need hard RTC, Julia may not be the best choice for the final application, but perhaps it can be useful for prototyping algorithms.
We can do 10 seconds of Lisp computation on a 800mhz box and cons less than 5k of data. This is because we pre-allocate all data structures we need and die on queries that exceed them. This may make many Lisp programmers cringe, but with a 250 meg image and real-time constraints, we can’t afford to generate garbage. For example, rather than using cons, we use “cons!”, which grabs cells from an array of 10,000,000 cells we’ve preallocated and which gets reset every query.
A lot of our Lisp is designed to compile into very efficient assembly. We make a lot of use of Lisp’s macro capabilities, but shy away from many other Lisp features like closures, generic functions, complex sequence functions and garbage collection. We’re doing an incredible amount of computation - getting 10 seconds on a modern machine is an incredible gift - but if we’re sloppy at all 10 seconds can turn into ten minutes, not adequate for a travel agent or web site. We disassemble most every Lisp function looking for inefficiencies and have had both CMUCL and Franz enhanced to compile our code better.
We’ve had very little trouble getting non-Lisp programmers to read and understand and extend our Lisp code. The only real problem is that the training most programmers have in Lisp has taught them to code very inefficiently, without paying any attention to the compiler. Of course, with things like STL and Java, I think programmers of other languages are also becoming pretty ignorant.
Let’s be creative. Assume a program is running alone on a cpu-core, nothing can stop its execution. Every sample the exact same amount of calculations is done, no allocations are done. Why isn’t this hard real time?
If Julia just allows the used to turn off the GC and run it manually the situation above is easily achievable. Just turn off the GC and run it once every iteration of the loop. Or run GC after everything is initiated and then turn it off.
I think there should be more ways to define hard real time than the current which is old.
If you don’t, then the solutions outlined above may suffice — you can achieve very little GC activity in some applications.
But if you do need hard RTC, then chances are that something expensive/catastrophic happens in case of an unpredictable delay. In this context, the last thing you want to do is “be creative”.
This suggests that you may not understand how modern x86 architectures work in a typical environment that Julia would be used (running in Linux/OS X/Windows). Please do some reading about RTC, so that you understand the pitfalls and your requirements better.
Give me a pitfall. I’m interested. I managed to get a max 0.3 ms time jitter running octave code in real time with 80 % CPU load using normal linux. I will do more testing but if I run it for one week or month with similar results I can call it hard real time.
People running real time linux get similar results.
Hard RTC is not about empirically demonstrating (lack of) pitfalls, but constructing the language the whole stack so that they are ruled out by construction.
Julia has no such guarantees. This does not mean that you cannot write code that is more or less predictable in practice, it’s just that this is not guaranteed. Also, technically a new version of Julia is free to introduce changes that break this (in practice, things go in the opposite direction, but again, this is not guaranteed).
If you are OK with this, fine. Very few people need hard RTC (in the sense that they are willing to put up with the inconvenience of obtaining it).
Interesting, it seems to be a theory vs practice thing. As an engineer I focus on the pragmatic side of things. I will test and if it works I will call it “Empirical Hard Real Time”.
There are a million examples of when practical methods beats or are equal to theoretical methods.
There are already terms for this approach, eg “soft real time”.
And there are some common practical heuristics for making it robust: eg your analysis loop can check if unprocessed frames are piling up, and then drop some and warn the user.
Note that Julia is not the only variable you have to deal with: eg on typical Linux environment (desktop, but even server to a certain extent) various processes are started all the time, potentially causing tiny lags, so if you eliminate most of Julia’s GC activity and your process is sensitive to delays these can become relatively important. The Linux kernel has some sophisticated schedulers to deal with this.
It’s not just a question of theory vs practice. Let’s say you have to write a program that controls a plane, do you use a language that cannot guarantee that it will not pause randomly ?
i use isolcpu which isolates a cpu-core from the scheduler so it is not used, there is also a command cset --shield that I haven’t got to work yet that is almost as good.
But I can manually put processes in the isolated core. So nothing can stop or interrupt the process execution.
If someone can tell me what could be problematic in this approach it would be useful.
In the example above I was running a heavy soft real time plotter on the other core and it was only a 2 core cpu.
how do you guarantee that there is not a bug in your code so that the engine of the car breaks? or a bug that shuts the jet engine off? or a bug that sprays too much fuel so that it blows up?
how do you guarantee that the landing gear doesn’t break? or the propeller break?
how do you guarantee that the cylinder doesn’t fly in through the window? in engineering you test a lot, so why can’t this very common approach also be used in hard RTC?
You need to communicate with external world, like reading file, writing to console or network socket. Kernel without hard RT guarantees can block you there for some time.
There are methods for formal program verification. There are formal proofs for some small RT kernels. No way to formally verify linux kernel - much lines of code, so it is not done yet and probably never will be.
So you are telling me there are never bugs in hard RT coding? But I have seen bugs.
F35 (fighter jet) is known as a very buggy plane.
I like that you are coming with real examples though. That’s exactly how you guarantee quality in industry, you sit down and go through everything that can go wrong and prevent it.
For general information on getting more control on GC operation, see the docs and look at functions/macros like enable, preserve or safepoint (there may be others too): https://docs.julialang.org/en/v1/base/base/#Internals-1
I recall seeing functions to barrier gc temporarily too.