Multithreading
It can be quite frustrating... You have an unbelievable powerful computer with the latest CPU. However, when using CAESES, you need to wait for your model to update (or your project to load) while you see that only one of those eight CPU-cores is actually busy and the others are playing a round of poker?! If you know this feeling, this post is for you! (If you do not know this feeling... read the post anyway... big things are coming our way ;) )
Those that attended last year's European User's Meeting already got a short glimpse into CAESES' future from Stefan Harries' talk. So, I figured, I could elaborate a little...
So, deep down in our "labs" we are working on the "next generation" of CAESES (I will, from now on, refer to it as ngCAESES, in lack of a better name just to make it easier for me - no, I will not throw any versions number out there). While this "next generation" does not include awesome new features (well, of course it does, but we don't need a "next generation" for that, we just throw those great new features out there as they come along ;) ), there are a lot of changes on the inside - the heart of CAESES. However, it is not only different, but also better. The main benifit for you - the user - is, that everything will be a lot faster (provided that you have a multicore CPU).
Before going into some (boring - and maybe also painful) details, I want to give you some numbers... You probably know the "Bulk Carrier 55000 Tdw" sample that is shipped with CAESES (if you don't, you are probably not a naval architect, but even then you should check it out; it's a great model built by one of our most talented engineers). So, in the current release (3.0.17 Windows 64 Bit) the model takes about 14 seconds to load on my machine. When I open that project in the ngCAESES I am up and running after 2.5 seconds! (Disclaimer: The mentioned version is in "hot" development, i.e. a lot is happening and the current state is very temporary. The mentioned timing will most probably change for the actual release - hopefully it will go down even further). Of course, this does not only affect project loading but also model update times and overall responsiveness, but project loading is the easiest thing to measure....
So what do we do to achieve this? Does this mean the ogCAESES ("old generation") did bad things and we finally fixed that? No! It wasn't bad, it's just that now it's better ;).
Ok, so we actually took several steps (and are still taking more) to achieve this. The main idea is to utilize the available hardware as much as possible.
Watch out! Geek-Speak ahead!
The thing about that hardware is, that modern CPUs are not very fast considering clock rate. Well... of course they are blazingly fast compared to old 486 CPUs, for example, but compared to, for example, the Pentium 4 Prescott CPU from !2004! which had clock rates from up to 3.8 GHz, the clock rate did not go up at all in the last 10 years (I know, today there are more instructions per cycle, higher FSB, yadda, yadda, yadda... still, the point is valid). There are several reasons why the clock rate could not be increased anymore. The two main points were (and are) thermal problems and energy consumption (of course, the two go hand-in-hand). So, instead, CPU manufacturers figured it would be a better idea, to put several processors on one chip. That way, they cannot process a single task faster, but perform multiple tasks at the same time at the same speed as the single task.
For us software developers this was "black friday". Afterall, it means that we do not get speed improvements for free anymore, but we actually need to work for it, because in order for the CPU to execute our software faster, it needs to be split into several individual task that can be run in parallel.
End Geek-Speak (for now... maybe more later ;))
The following picture (which was also shown at last year's User's Meeting in Berlin) tries to illustrate the difference:
So, what we can see is, in the current version (up top in the picture) objects are updated serially - ordered by their dependency. Some objects already make use of the multiple cores the CPU provides, as they calculate some stuff in parallel (the last box), but that is rare. NgCAESES (bottom - labeled as CAESES 4, but I, personally, don't want to throw any version numbers around) builds a graph of dependent objects, and different branches of that graph are then updated in parallel. Additionally, a lot more objects have their internal algorithms parallized. This - as you can clearly see in the picture - leaves you - the engineer - a lot more time to travel, relax, and party ;)
With great power comes great responsibility
Yep... that's true. It cannot be all gold and shiny. But, the nice thing is, the drawbacks will only affect those people who were already told by us that what they are doing is "evil" or "out of the specification" in the past - I am pretty sure that (if they are reading this) they will know that I am addressing them...
Ok, so we needed to limit the freedom and flexibility the user had so far a little. You cannot use features to "mess everything up anymore" ;). The major change for the user (which "average Joe" will not even notice) is that we introduced the notion of "constness". Those of you that know C++ (or C#, or Ada, or D, or one of the other programming languages that make an explicit distinction between constant and mutable expressions) will know that this can be quite painful, but also very good for guaranteeing that nothing bad is happening in your code.
So, what did we actually change for the user? What is not possible anymore?
You cannot call a command that modifies the object it is called on anymore, if that object is labeled as "const" and the command isn't.
You cannot pass an object that is labeled as "const" as an argument to a command that takes a non-const argument.
That's it..... I can literally see your face right now: :blink: :blink: :wacko: :unsure: :wacko: :blink: :blink:. So. please let me explain:
When is an object const?
I think that is best explained through an example: You can ask a F3DPoint for it's global vector by using the command
FVector3 FPoint.getGlobalVector()
The return value of that command is (now) const. Why? Easy: The command returns a value that is a derivative of the point's input values (the x, y, and z coordinate). Changing that return value would not result in a change of those values. They are what define the point and also the global vector. To make this clear, the return value is now marked as const and will result in an error when trying to modify it. So in the past it was actually possible to write nonsense like this (provided there is a F3DPoint called p1):
p1.getGlobalVector().setX(8)
It was valid, but didn't do anything. Of course, the "didn't do anything"-part means it didn't do any harm, but if the user (i.e. YOU) would execute something like this and not get an error message, the understandable assumption would be that it DOES do something, is quite understandable.
But, not only is the return value of "getGlobalVector" const, but the command itself is also const, because it does not modify the object it is called on (i.e. the point). So in ngCAESES the complete signature for that command is
const FVector3 FPoint.getGlobalVector() const
The first "const" refers to the return type. The returned object cannot be modified. The "const" at the end refers to the command in respect to it's receiver (i.e. the point it is called on).
As stated, that example is harmless, but there are several not so harmless cases, that lead to undesired behavior. One more example:
Let's assume you have a point p1. Let's further assume you have a parameter pm1 that defines the x-coordinate of that point. Now, for whatever reason, the user enters the command "p1:x = 9" in the console which is supposed to set the x-coordinate to the value 9. Well... it does set the x-coordinate to the value 9 (i.e. the point will actually be there), but it will leave you with the following undesired state:
So what do we have here? The parameter pm1 has the value 1, the x-coordinate of the point is still set to be said parameter, but the actual value is 9?! That can't be right! So what happened? Well, without going into too much detail: p1:x returns a FDouble, which is then assigned to using the '=' operator. Nothing bad about that.
BUT! p1:x does not really have a double as a value, but an FParameter. That FParameter is (automagically) converted into an FDouble (while the conversion is pretty straight forward in this case, it's still neccessary). So the p1:x actually returns a temporary FDouble that is the result of the conversion of the parameter pm1 to a (temporary) FDouble.
And now, the operator '=' assigns the new value '9' to exactly that temporary FDouble. In turn, this means that the wrong state is resolved after changing the parameter (because the temporary FDouble will be replaced by a new temporary FDouble) or after re-opening the project, but it's still bad that this state can occur.
Ok, to be honest, I probably lost most of my readers (if you even got this far) with that last paragraph... Read it again... It might just make sense eventually...
So, the main point is: we are trying to protect you from experiencing something unexpected when using our software! We are well aware of the pitfalls, but we are also aware of the great power and flexibility we offer. So, we want to keep the flexibility and power while reducing the possible pitfalls (now that's something the C++ commity should have decided at least 10 years ago). That's why in ngCAESES stuff like assigning a value to p1:globalX will not be possible anymore.
How does this affect me?
Short answer: It doesn't (or it shouldn't). If you do get an error because of this (and you should not), it means that in the past you were doing something that had (in the best case) no effect (like the .getGlobalVector().setX(9) case) or really, really bad effects (like the p1:x = 9 case).
With regards to Features there are some things, however, that used to work and will no longer work.To be honest, those things are things, that we never promoted and even told those that used them that they shouldn't. I am kind of hesitating to include them in this post, since I do not want to give those people that didn't do this or didn't know that they could do this any bad ideas...
Ok, I am still gonna do it...
First of all, it will no longer be possible to change (i.e. call non-const commands on) arguments of a Feature within the Feature. Why?
Watch out! Geek-Speak ahead! (but this time all CAESES users should understand it...)
Well, technically, the Feature is a client of the argument. When the argument changes its value, the Feature needs to update. So, changing the argument value within the Feature actually creates an untracked recursion. The only reason it worked until now was that there was a safety-net in the code that made sure that objects cannot go out of date while they are updating. But... it also left the whole model in an undefined state. Some other objects that were clients of the object that the feature changed may have already been up to date, and they never noticed that the object has already changed its state... This is not good!
Kind-of done with geek-speak, but the following may still be kind of tech-heavy!
So... we are totally disallowing to change arguments of a feature within a feature. This will not be the case in the upcoming 3.1 release, but I hope, it will be in the one after that!
Ok, so those Features that I know that did change their arguments did this for one - and only one - reason: display the user some additional info.
Since we know and understand, that that is a good thing, we have introduced a new thing (not yet, but in the release that will include all that "const" stuff): You can now tell a feature argument that it can act as a label. The "advanced options" of feature arguments have 5 more fields (names are subject to change - so don't quote me here):
- "Display as label command": Here you can specify under which circumstances the given argument is supposed to display a value and nothing but a value... The value displayed has nothing to do with the value of the argument. If it's supposed to be a value only, you would set this to "true" or if it depends on the state of the model or other input of the feature you can use the usual command syntax. If this command evaluates to "true", the editor for this argument will be hidden and a label will be displayed instead.
- "Label Content Command". If the above determines that this argument is displayed as a label... here you can say what the label is supposed to display. This can be just a string, or any other object. If it's anything but a string, the usual display as a string will be used that applies to the type (e.g. if it's a fvector3, it will be displayed as [1,2,3] if it has x = 1, y = 2, z = 3). This label is very flexible! It can even display HTML! So, go crazy with it!
- "Keep Label UpToDate" If this is set to true every object that is needed to determine the value of the previous two commands is automatically updated as soon as their value changes (same as automatic update for parameters/constraints/features: I do not recommend to use this option - or better: use at your own risk!)
- "Hide Check Box for Label". If the attribute has a "Display as label Command" (see above) and that command evaluates to "true", the checkbox (see the documentation about the advanced options of feature arguments in versoin 3.1) will be hidden.
- "Hide Buttons For Label" If the attribute has a "Display as label Command" (see above) and that command evaluates to "true", all buttons configured for the attribute (see documentation about the advanced options of feature arguments in version 3.1) will be hidden.
Wow... this is a terribly wrong post.... To all of you that are still here... HAVE A COOKIE!!! OR TWO!!!
I just wanted to share some of the new development with you - that I am personally very excited about. Also, I wanted to warn some of you Feature-Artists that some of the freedom is coming to an end ;)
0 Comments
Recommended Comments
There are no comments to display.
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now