When I try to assign a variable x within the body of an if-statement I get unexpected results if the variable also occurs in the condition of the if-statement.
For example, the code
model algorithmTest_25p05p2021
Real x(start=0);
Real y(start=0);
algorithm
y := sin(time);
x := sin(time);
if x < 0 then // replace with y < 0 --> x is correctly truncated
x := 0;
end if;
end algorithmTest_25p05p2021;
results in
I used OMEdit in OpenModelica 1.17.0, simulation time 120s, maximum step time of 1s.
I can't wrap my head around what is going on here.
In my understanding, the algorithm section implies that x is initialized to its start value 0. After initialization, I thought the statements in the algorithm section are executed in order. So, before the if-statement, x is set to the value of x=sin(time).
Afterwards, I expected that the if-statement would set x=0 if sin(time) < 0 and leave x to be x=sin(time) if sin(time)>=0.
You see what happens instead: x stays zero after the condition triggers for the first time.
What confuses me even more is that replacing the "x<0"-condition with a "y<0"-condition fixes the issue.
What have I missed here? Any pointers to the Modelica specification?
EDIT (27.05.2021):
As this behaviour appears to be a bug in OpenModelica 1.17.0, I posted it on their Github, see
https://github.com/OpenModelica/OpenModelica/issues/7484
It must be a bug.
Clearly there should be an event for x<0, but the event-logic is only important when x is close to zero and thus should have a minimal impact on graph.
The relevant sections of the specification I can find are:
If-statements are only evaluated if true
https://specification.modelica.org/maint/3.5/statements-and-algorithm-sections.html#if-statement
If the condition and the hidden state is inconsistent an event is generated:
https://specification.modelica.org/maint/3.5/equations.html#events-and-synchronization
Conceptually x is initialized with its start-value, but it doesn't matter since it is unconditionally assigned https://specification.modelica.org/maint/3.5/statements-and-algorithm-sections.html#execution-of-an-algorithm-in-a-model
Related
I don't think that the following do concurrent Fortran loop is valid, as acc is modified in every iteration. However, gfortran is not giving me any kind of warning, and the resulting value in acc is correct at 55. Is it valid or not?
integer :: acc, i
acc = 0
do concurrent (i=1:10)
acc = acc + i
end do
The loop is indeed not valid. The compiler is not required to detect this and report the reason in this case.
In Fortran 2008 8.1.6.5 ('Restrictions on DO CONCURRENT constructs') we have as one restriction:
A variable that is referenced in an iteration shall either be previously defined during that iteration, or shall not be defined or become undefined during any other iteration. A variable that is defined or becomes undefined by more than one iteration becomes undefined when the loop terminates.
acc is such a variable that becomes defined (being on the left-hand side of an intrinsic assignment statement) by more than one iteration (all of them). The loop is thus a bad one (and at the end of the loop construct acc is undefined, so checking its value is also naughty).
As noted in the comments, and similarly to other invalid Fortran programs, you may still appear to get the correct answer without any complaints here. In this case, a DO CONCURRENT construct could be implemented in exactly the same way as a normal DO construct to give exactly the same answer. Only when running in parallel (say with autoparallelization or on GPUs), or with very strict compiler checks, would the data dependency result in a race condition and a wrong answer or abort.
I was reading Bjarne Stroustrup's C++11 FAQ and I'm having trouble understanding an example in the memory model section.
He gives the following code snippet:
// start with x==0 and y==0
if (x) y = 1; // thread 1
if (y) x = 1; // thread 2
The FAQ says there is not a data race here. I don't understand. The memory location x is read by thread 1 and written to by thread 2 without any synchronization (and the same goes for y). That's two accesses, one of which is a write. Isn't that the definition of a data race?
Further, it says that "every current C++ compiler (that I know of) gives the one right answer." What is this one right answer? Couldn't the answer vary depending on whether one thread's comparison happens before or after the other thread's write (or if the other thread's write is even visible to the reading thread)?
// start with x==0 and y==0
if (x) y = 1; // thread 1
if (y) x = 1; // thread 2
Since neither x nor y is true, the other won't be set to true either. No matter the order the instructions are executed, the (correct) result is always x remains 0, y remains 0.
The memory location x is ... written to by thread 2
Is it really? Why do you say so?
If y is 0 then x is not written to by thread 2. And y starts out 0. Similarly, x cannot be non-zero unless somehow y is non-zero "before" thread 1 runs, and that cannot happen. The general point here is that conditional writes that don't execute don't cause a data race.
This is a non-trivial fact of the memory model, though, because a compiler that is not aware of threading would be permitted (assuming y is not volatile) to transform the code if (x) y = 1; to int tmp = y; y = 1; if (!x) y = tmp;. Then there would be a data race. I can't imagine why it would want to do that exact transformation, but that doesn't matter, the point is that optimizers for non-threaded environments can do things that would violate the threaded memory model. So when Stroustrup says that every compiler he knows of gives the right answer (right under C++11's threading model, that is), that's a non-trivial statement about the readiness of those compilers for C++11 threading.
A more realistic transformation of if (x) y = 1 would be y = x ? 1 : y;. I believe that this would cause a data race in your example, and that there is no special treatment in the standard for the assignment y = y that makes it safe to execute unsequenced with respect to a read of y in another thread. You might find it hard to imagine hardware on which it doesn't work, and anyway I may be wrong, which is why I used a different example above that's less realistic but has a blatant data race.
There has to be a total ordering of the writes, because of the fact that no thread can write to the variable x or y until some other thread has first written a 1 to either variable. In other words you have basically three different scenarios:
thread 1 gets to write to y because x was written to at some previous point before the if statement, and then if thread 2 comes later, it writes to x the same value of 1, and doesn't change it's previous value of 1.
thread 2 gets to write to x because y was changed at some point before the if statement, and then thread 1 will write to y if it comes later the same value of 1.
If there are only two threads, then the if statements are jumped over because x and y remain 0.
Neither of the writes occurs, so there is no race. Both x and y remain zero.
(This is talking about the problem of phantom writes. Suppose one thread speculatively did the write before checking the condition, then attempted to correct things after. That would break the other thread, so it isn't allowed.)
Memory model set the supportable size of code and data areas.before comparing linking source code,we need to specify the memory model that is he can set the size limitsthe data and code.
I have a simple for-loop in C++ and the initialization statement is:
for (int n = 0; n < this->fileLines.size(); n++) {
For some crazy reason, the value of n is being set not to 0 but to 249758, which causes the for-loop to evaluate wrong.
Any ideas why this is initializing wrong (i.e., not to 0)?
I think you need to verify after the for loop what the value of n is, I don't see any way this could non-0. Check the value at the start of the switch. Your breakpoint may have interrupted before n was actually set.
Have you tried sticking
std::cerr<<n<<std::endl;
inside of the for loop? This seems a more direct way of observing the value during the running of the program to verify whether or not it is doing what you think, and optimization will not give you problems with this output.
Perhaps your program is multithreaded and someone is inappropriately writing to that memory location?
So sample loop:
do i=1,1
print *,i
enddo
print *,i
gives me 2 as the final value of i. How can I set up Intel Fortran for Visual Studio on Windows to give me a final value of 1 for i?
This has been the way that Fortran loops work for decades and you can't simply change this with a compiler option. The Fortran standard clearly states:
8.1.4.4.1 Loop initiation
(2) The DO variable becomes defined with the value of the initial parameter m1.
(3) The iteration count is established and is the value of the expression
MAX (INT ((m2 – m1 + m3) / m3), 0)
Here m1, m2 and m3 are the three parameters in the loop-control: [,] var = m1,m2[,m3], Given your example of i=1,1 (m3 is implicitly 1 if omitted) the iteration count is MAX(INT((1-1+1)/1),0) which evaluates to 1, i.e. the loop should get executed once. i is initialised to 1 as per (2).
8.1.4.4.2 The execution cycle
The execution cycle of a DO construct consists of the following steps performed in sequence repeatedly until termination:
(1) The iteration count, if any, is tested. If the iteration count is zero, the loop terminates and the DO construct becomes inactive. If loop-control is [ , ] WHILE (scalar-logical-expr), the scalar-logicalexpr is evaluated; if the value of this expression is false, the loop terminates and the DO construct becomes inactive. If, as a result, all of the DO constructs sharing the do-term-shared-stmt are inactive, the execution of all of these constructs is complete. However, if some of the DO constructs sharing the do-term-shared-stmt are active, execution continues with step (3) of the execution cycle of the active DO construct whose DO statement was most recently executed.
Fortran tests if the remaining iteration count is greater than zero, not if the DO variable is less than (greater than) the end value.
(2) If the iteration count is nonzero, the range of the loop is executed.
(3) The iteration count, if any, is decremented by one. The DO variable, if any, is incremented by the value of the incrementation parameter m3.
The DO variable is always incremented as an iteration of the loop is being executed. Thus after the first execution i becomes incremented by 1 which evaluates to 2.
Except for the incrementation of the DO variable that occurs in step (3), the DO variable must neither be redefined nor become undefined while the DO construct is active.
8.1.4.4.4 Loop termination
When a DO construct becomes inactive, the DO-variable, if any, of the DO construct retains its last defined value.
The last defined value is 2. Thus after the DO loop has ended, i is equal to 2.
I've pulled the text out of ISO/IEC 1539:1991 (a.k.a. Fortran 90) but one can also find pretty much the same text in §11.10.3 of ISO/IEC 1539:1980 (a.k.a. ANSI X3J3/90.4 a.k.a. FORTRAN 77; sans the WHILE stuff which is not present in F77) as well as in §8.1.6.6 of ISO/IEC 1539-1:2010 (a.k.a. Fortran 2008).
You can't, because that's how DO works; it stops when the control variable exceeds the limit.
In general, in pretty much any language with a FOR/DO counting loop, you should only use the loop control variable inside the loop body, and treat it as undefined elsewhere, even if you can't actually limit its scope to the body.
In your case, I would use a different variable to keep track of the actual last value of i in any iteration:
lasti = 0
do i=1,1
print *,i
lasti = i
enddo
print *,lasti
I have a class with the only constructor like this:
IntroScreen::IntroScreen(Game *game) :
View(game), counter(0.0f), message(-1), continueAlpha(255),
continueVisible(false), screenAlpha(255), fadeIn(false), fadeOut(false)
{
}
And somewhere in a method I have this if-statement
if (counter > 10.0f)
And Valgrind says for that line:
Conditional jump or move depends on uninitialised value(s)
But I initialized it in my initializer list! And I think I believe Valgrind. Because, sometimes everything goes correct and sometimes nothing happens.... So, maybe counter gets a wrong value and so it takes long until the counter reaches 10.
I already check my code where I use counter for some errors. But I think you can't "un-initialize a value" with a C++ statement...
These are ALL the lines (except in the initializer list) where I use counter:
counter += speed;
counter = 20.0f;
counter += game->getSpeedFactor();
if (counter >= 15.f)
counter = 15.f;
if (counter > 10.0f)
Valgrind gives the same output for screenAlpha.
Both variables are private and I have no friend classes....
So, what is going on? What the problem could be?
Edit:
I printed the value out:
In the constructor, it was correnct: 0
In my method, it was rubbish. It prited random values like:
-97298.8...
-106542.2...
The print statement is the first line of the method where all assignments to counter are in.
Second Edit:
Can this be the problem!!??
In my Game class, I initialize that IntroScreen like this:
Game::Game() : /* Some other stuff .... */ , view(new IntroScreen(this))`
{}
view is here a pointer to an abstract super-type of IntroScreen called View.
Did you accidentally shadow counter with a local variable that's uninitialized?
Otherwise, it's possible that valgrind is mid-diagnosing this in an object that was already deleted (using sentry values perhaps).
Or valgrind could just be wrong.
Not enough code to reproduce problem.
Generic SO / developer forum advice:
Do provide a minimal code snippet reproducing the problem.
Quite often (about 85% of all cases in my experience) the process of reducing the code snippet already uncovers the bug for you.
Edit: Your addition still doesn't give a compilable example of your problem, but enough information at least to identify then problem - or, at least, one of them:
Game::Game() : /* Some other stuff .... */ , view(new IntroScreen(this))`
{}
I am not sure whether a new() call is even legal in an initializer list. But I am sure that you do not have a fully initialized this at this point, so chances are your IntroScreen constructor does bogus things.
I found it:
getSpeedFactor() returns only the first time I call it a complete wrong number because of time-functions like gettimeofday(). The start value (to time how long it took to update the game) is set initialized to zero and the stop value is micros of the day: which gives a time of the whole day instead of the update time. Once the game loop ran once, the wrong value is corrected (because of the start value gets assigned). But the first time the game-logic was executed, I used getSpeedFactor() to assign counter, so that way counter get a value of -10000...
Thanks all.
Off the top of my head, you may need to define private default and copy constructors that have proper initializers. Haven't used valgrind, but it's a common thing to forget to do.
Just add a debugging printf statement or equivalent, if you have doubts. But I would not believe Valgrind this time.
BTW: delete does not "un-initliase" a value. It deletes object, but the pointer still points to that memory location — it does have a value.