There is some randomness in the placement of dots. The merge-rests-engraver.ly regtest (git-version557dc7) exposes the problem as the output might be one of the two attached pngs. The probability for both results is identical on my system.
Update Nov 5th 2019
Issue 5217: Fix sorting order without outside-staff-priority
If the two Grobs have no outside-staff-priority, the compare function
staff_priority_less() would relate the two pointers. This may lead to
changing sorting orders in subsequent runs, apparently resulting in
"random" positions in the regression tests rest-dot-position.ly and
sometimes merge-rests-engraver.ly.
Solve this by keeping the original order in the vector:
Mark two Grobs without outside-staff-priority as being equal by
always returning false (none is less than the other), and
use vector_stable_sort() to keep equal items in their relation.
I went through the checkins one-by-one ('soft resetting' HEAD on my local git repo each time) and did the make test-baseline/make check for each commit. I have identified that it is from this commit onwards:
when the funny reg test diff starts to show up
That's peculiar since that commit only changes
scm/framework-svg.scm
(apart from a trivial Doc change). That should not even be used unless producing SVG.Last edit: David Kastrup 2017-10-21
So I went back again and tried one more time round - in case I hadn't really reset my branch. Hmmm, it is frustrating. I don't always hit it. I had nothing until I got to this later checkin:
and then, because one example is not 'proof' I ran it again on the same checkin and didn't get anything (I did a distclean etc).
If I port current masters merge-rests-engraver.ly back to the old syntax
and start a regtest loop I see that the problem is already present in
FWIW,
I looked through our regtests searching for { r4. } in simultaneous music and found only:
dot-column-rest-collision.ly
dots.ly
merge-rests-engraver.ly
rest-dot-position.ly
merge-rests-engraver.ly is the single one with three voices
I then modified rest-dot-position.ly :
If you look at the output you see dots moving depending on \voiceXxxx
To make it more obvious colors are applied.
So far I the results are not random, though I always checked in-file and not running the regtests.
Maybe of some help, though.
Btw, some output is really poor, imho, see the dots for short rests in the outer voices.
Well, that dots change the position depending on \voiceXxx is not a problem, although your example clearly shows that some work could be invested into this code. The problem is that we have one input and lilypond randomly choses between two places for that one dot in the second voice.
But is it random? I mean on every patch test I do now I get this this reg test diff pop up. If it were random then this would not happen - (unless I am very lucky!)
50 regression tests with no changes
"1" means "we hit the problem",
"0" means "files are identical"
Result array: 10001100000001100000000110000110001110100000000000
A minor editing at the end of merge-rests-engraver.ly seems to mask the problem here:
Original unstable version:
Stable version:
Ok. That "stable version" above isn't stable .... 2 in 100 regtests exposed the problem again.
I've put my code above as 'aaa-voiced-rest-dots.ly' into the regtest and did a regtest comparison without any changes.
And it is triggered!! (As well as the usual merge-rest-engraver.ly)
See attached.
So I think it's proofed that something else is fishy, not the merge-rest-code/regtest.
Let me emphasize again: merge-rest-engraver.ly was the single regtest with three voices containing simultaneous r4.
Now I added another one, and it is triggered as well!!
I did regression-tests with the attached regtest 'aaa-voiced-dotted-rests.ly' (old syntax, to make it work even for 2.16) with checkouts of previous stables, i.e. 2.18 and 2.16.
(For difficulties getting it work see the thread starting http://lists.gnu.org/archive/html/lilypond-devel/2017-10/msg00144.html)
Results attached as well.
The dots are placed quite randomly for every tested version.
Maybe we should have a regtest for explecitely testing dotted rests for more than two voices. Even if going on everyones nerves until the problem is solved.
Obviously I can't attach more than one file file ...
the regtest
I think I've found the culprit, I needed to revive LilyDev2 which is based upon Ubuntu 10.04 with
GNU Make 3.81
gcc (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3
First bad commit is
commit 1c24c56886cd85f04283ac61e8a0deea172035ed
Author: Mike Solomon mike@apollinemike.com
Date: Wed Jan 18 08:22:31 2012 +0100
This is issue 2180
lilypond-version 2.15.27
And was meant to improve issue 1986
And was changed with issue 2468
Obviously the initially reported problem persisted and persists, but was never detected until merge-rests-engraver.ly introduced simultaneous dotted rests for more than two voices.
There may have been more changes after 2468, ofcourse.
What a mess ...
Huh. It contains a call
+ vector_sort (dots, pure_position_less);
which uses a non-stable sort I guess. One could check whether using vector_stable_sort makes any difference. Not that I have a clue what I am doing here... The problem is that likely even with a stable sort, the order of comparisons is not guaranteed, and the code looks like it triggers some semi-recursive evaluation.
I could give it a try, but not before next weekend ...
I now locally changed
vector_sort
tovector_stable_sort
in dot-column.cc.After doing so I've run make test-baseline and make check:
The dots in input/regression/rest-dot-position.ly are still not consistent positioned.
Thus I think that change doesn't help, at least not solely.
"Thomas Morley" thomas-morley@users.sourceforge.net writes:
Ok, it was worth a try. I may even have concocted that experiment
myself previously but could not remember reliably any more.
Thanks!
--
David Kastrup
I've tried to approach this systematically and made the observation that the moving dots might be related to what other regression tests are built for
check
(and maybe in what order? not sure if that is stable across invocations). Based on that, I've created a small set of input files (see attached archive) that really changes at random on subsequent invocations oflilypond -dread-file-list names.ly
, at least on my system.I went on to understand what is causing the non-determinism. From what I found so far, it looks like some functions might be called in a different order in subsequent invocations of lilypond. I've also put a small diff into above archive which adds a few
printf
s: SometimesDot_column::calc_positioning_done
is called beforeRest_collision::force_shift_callback_rest
, on another invocation it might be the other way around. The problem is thatRest_collision::force_shift_callback_rest
callsGrob::translate_axis
which updates a cache and changes the Y position.At least that's what it looks like to me right now, without knowing which ordering of above functions would be correct. But a changing order at random seems odd, doesn't it? Posting here in case somebody with more experience goes like "hey, that can be easily fixed like this". Otherwise I'll try to understand what's causing the different orders and how it can be turned off.
"Jonas Hahnfeld" hahnjo@users.sourceforge.net writes:
Turn off address space randomization and chances are that things become
more deterministic. As it is, certain data structures like Scheme
hashes are traversed in orders that depend on address allocation orders.
The current situation of random results for successive runs on identical
input is probably not significantly worse than pseudorandom results that
are only deterministic if you change absolutely nothing. Whether
minimal unrelated changes (including compilation with different
compiler/libraries) lead to considerable changes in results or no
changes at all: in practice that does not likely make a lot of
difference. It's only a bit baffling for people used to the consistency
of computers.
--
David Kastrup
I had the same idea, but I still see non-deterministic results for my simple example after running
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
which should turn off ASLR. I'll try the kernel parameter tomorrow and let you know if that changes anything.So the reason is that
staff_priority_less
compares pointers in the default case. I'm not entirely sure why those change even without ASLR, but maybe Guile's garbage collection and / or timing of allocation play a role?"Jonas Hahnfeld" hahnjo@users.sourceforge.net writes:
This is pretty appalling. I see that
has been added in
commit 8eafccec8c45891d8e00366ca2f67f67a9c93cf9
Author: Joe Neeman joeneeman@gmail.com
Date: Sun Jan 21 14:04:13 2007 +0200
and seems of little relation to the commit message. It would likely be
saner to just return false instead of introducing some random order that
serves no point. Of course this will still warrant using a stable sort.
P.S.: I see that you already proposed a patch doing exactly that.
Last edit: David Kastrup 2019-11-05
Issue 5217: Fix sorting order without outside-staff-priority
If the two Grobs have no outside-staff-priority, the compare function
staff_priority_less() would relate the two pointers. This may lead to
changing sorting orders in subsequent runs, apparently resulting in
"random" positions in the regression tests rest-dot-position.ly and
sometimes merge-rests-engraver.ly.
Solve this by keeping the original order in the vector:
* Mark two Grobs without outside-staff-priority as being equal by
always returning false (none is less than the other), and
* use vector_stable_sort() to keep equal items in their relation.
http://codereview.appspot.com/554960043