Thursday, April 4, 2019

Digest for comp.lang.c++@googlegroups.com - 16 updates in 4 topics

Bonita Montero <Bonita.Montero@gmail.com>: Apr 04 01:59PM +0200

Hm, maybe I should add fences to help g++ not to reorder memory
-operations. MSVC doesn't need this as _InterlockedCompareExchange
has implicit acquire and release behaviour.
Bonita Montero <Bonita.Montero@gmail.com>: Apr 04 05:49PM +0200

> Hm, maybe I should add fences to help g++ not to reorder memory
> -operations. MSVC doesn't need this as _InterlockedCompareExchange
> has implicit acquire and release behaviour.
 
Is there any gcc-"intrinsic" for _logical_ barriers? I.e. an intrinsic
that keeps the compiler away from reordering loads and stores, but not
by _physically_ having a barrier like "xchg [mem], reg". The physical
barrier is already done by the __sync_val_compare_and_swap-intrinsic.
I know that I could do a "__asm__ __volatile__ ("" ::: "memory");",
but that's a full barrier and I rather need an aquire and release
-barrier.
David Brown <david.brown@hesbynett.no>: Apr 04 09:14PM +0200

On 04/04/2019 17:49, Bonita Montero wrote:
> I know that I could do a "__asm__ __volatile__ ("" ::: "memory");",
> but that's a full barrier and I rather need an aquire and release
> -barrier.
 
Have you considered using a C++11 fence?
 
In gcc, asm volatile ("" ::: "memory") is a compiler barrier. It tells
the compiler to make sure anything that is due to be written out to
memory from registers, gets written out, and it forgets anything about
data read in from memory to registers. If you think of the cpu
registers as a "level -1 cache", it is a level -1 cache flush operation.
 
This is /not/ the same as fences, which affect the order and
synchronisation of data between threads.
 
The gcc compiler barrier is usually a cheap barrier - it does no
hardware synchronisation or instructions, and mostly stores data that
would have been stored sooner or later anyway.
 
If you need a barrier that only affects certain variables, that is also
possible.
"Chris M. Thomasson" <invalid_chris_thomasson_invalid@invalid.com>: Apr 04 01:16PM -0700

On 4/4/2019 2:56 AM, Bonita Montero wrote:
> I've re-implemented the class more usable and POSIX-compilable:
[...]
 
Need to actually compile this, and take a closer look. However, one
little point. Beware of the fact that sem_wait can return EINTR, and
needs to be waited on again in a loop.
 
https://pubs.opengroup.org/onlinepubs/7908799/xsh/sem_wait.html
 
 
> {
>   return sem_wait( &m_sem ) == 0;
> }
[...]
"Chris M. Thomasson" <invalid_chris_thomasson_invalid@invalid.com>: Apr 04 01:18PM -0700

On 4/4/2019 1:16 PM, Chris M. Thomasson wrote:
 
> Need to actually compile this, and take a closer look. However, one
> little point. Beware of the fact that sem_wait can return EINTR, and
> needs to be waited on again in a loop.
 
More precisely sem_wait can fail and errno can be equal to EINTR. This
means we have to try the sem_wait again.
 
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Apr 04 03:20PM -0400

In the code I write, there is a natural hierarchy of algorithms being
broken out to simplify code. However, there is information conveyed
that the compiler cannot assume without taking some big assumptions,
such as if func1() calls func2() with some parameters validated in
func1(), the compiler can't safely recognize that the parameters passed
in to func2() have already been validated, so there's no reason to
check for a NULL pointer, or something invalid.
 
While this doesn't prevent things from compiling, code analysis is not
possible as it should be because the compiler does not have that
information.
 
As such, I propose adding a new childof keyword, which will indicate
that a function is the direct child of the parent function. This will
convey information that untested parameters are assumed to have already
been tested in the calling function.
 
int func1(void)
{
int* p;
 
if ((p = populate_the_pointer()))
return func2(p);
 
return -1;
}
 
int func2(int* p) childof func1
{
// Direct use without NULL testing
*p = *p + get_step_size();
}
 
In this way, the compiler is able to know that func2() is designed to
be explicitly called from func1(), and is not a stand-alone function
able to be runtime-linked to some other location, or assigned as the
target of a function pointer, thereby requiring examination of the
input parameter p prior to use.
 
-----
In CAlive I use named_functions() along with iNamed_functions() for
child functions, and then iiNamed_functions() for those which do not
need to test those parameters. However, if inside of iiNamed_functions()
I need further discriminate and call iiNamed_functions_apples() and
also iiNamed_functions_oranges(), then there's no real way to indicate
that those ii() functions are children of any specific thing without
doing a call analysis, and even then they can still be the target of
the aformentioned function pointer or dynamic runtime linking.
 
By using the childof keyword, the direct ancestry of any functions can
be determined when they have been explicitly added to be that kind of
breakout code to simplify the algorithm into more manageable units.
 
-----
I'm curious about people's thoughts on the introduction of this new
information into C/C++?
 
--
Rick C. Hodgin
Bart <bc@freeuk.com>: Apr 04 08:34PM +0100

On 04/04/2019 20:20, Rick C. Hodgin wrote:
 
> I'm curious about people's thoughts on the introduction of this new
> information into C/C++?
 
What's the difference between this and nested functions?
 
(It is possible to implement nested functions without necessarily
sharing access to an outer function's stack-frame variables, which is
where the problem areas lie in implementation.)
 
 
int func1(void)
{
int func2(int* p)
{
// Direct use without NULL testing
*p = *p + get_step_size();
} int* p;
 
if ((p = populate_the_pointer()))
return func2(p);
 
return -1;
}
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Apr 04 03:43PM -0400

On 4/4/2019 3:34 PM, Bart wrote:
>             return func2(p);
 
>         return -1;
>     }
 
Nested functions inherit the encapsulating parent function's scope
as well, don't they? Childof functions would be separate entities
without the parent context, and they could theoretically be the
child of multiple parents, including itself through recursion.
 
--
Rick C. Hodgin
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Apr 04 09:01PM +0100

On 04/04/2019 20:20, Rick C. Hodgin wrote:
 
> -----
> I'm curious about people's thoughts on the introduction of this new
> information into C/C++?
 
Rather than the keyword "childof" I would prefer the keyword
"preconditions" if the idea itself wasn't so fucktarded.
 
/Flibble
 
--
"You won't burn in hell. But be nice anyway." – Ricky Gervais
 
"I see Atheists are fighting and killing each other again, over who
doesn't believe in any God the most. Oh, no..wait.. that never happens." –
Ricky Gervais
 
"Suppose it's all true, and you walk up to the pearly gates, and are
confronted by God," Bryne asked on his show The Meaning of Life. "What
will Stephen Fry say to him, her, or it?"
"I'd say, bone cancer in children? What's that about?" Fry replied.
"How dare you? How dare you create a world to which there is such misery
that is not our fault. It's not right, it's utterly, utterly evil."
"Why should I respect a capricious, mean-minded, stupid God who creates a
world that is so full of injustice and pain. That's what I would say."
David Brown <david.brown@hesbynett.no>: Apr 04 03:29PM +0200

On 02/04/2019 14:48, Öö Tiib wrote:
> On Tuesday, 2 April 2019 14:23:40 UTC+3, Alf P. Steinbach wrote:
>> On 02.04.2019 12:59, Öö Tiib wrote:
 
<snip>
 
> checked pointers right away as part of dereference operations. For
> lot of people that has been sort of dream to improve safety of pointers
> for long time.
 
None of these sorts of limitations of valid access are really about
"perverse processors". There are several advantages of saying that you
may not access a multidimensional array as though it were a large
unidimensional array - with many other kinds of banned (or undefined, or
invalid) behaviour having similar points.
 
1. Code that accesses data in a weird way, is usually wrong. By making
it explicitly wrong (by declaring it to be invalid or undefined
behaviour), compilers, debuggers and other tools are able to spot
mistakes and help the user correct them. If these out-of-bounds
accesses were defined behaviour, tools could not tell if the programmer
had a bug in their code or was intentionally mistreating their arrays.
 
2. It aids optimisation. The limits on the behaviour means the compiler
knows more about possible aliasing, meaning it can do better at
automatically vectorising code, or re-arranging accesses for better
scheduling.
 
3. It gives the compiler more scope to re-arrange things. There is no
need to have the arrays contiguous in memory - it can store the
sub-arrays in SIMD registers, or arrange them for better cache locality.
On platforms with multiple independent ram blocks, it could put
different parts in different blocks to improve throughpput.
 
4. It makes logical sense to restrict allowed access, so that your code
does what it appears to say it will do. Code that defines arrays of a
particular size, then pretends they are something different, is
inevitably going to be harder to follow.
 
 
C and C++ let you define multidimensional arrays. They let you define
unidimensional arrays. They let you define structures that support both
accesses. It makes a lot more sense to write code correctly, using
appropriate structures and features, rather than trying to write
something that is inconsistent and against the explicit rules of the
language.
jameskuyper@alumni.caltech.edu: Apr 04 06:51AM -0700

On Thursday, April 4, 2019 at 9:30:00 AM UTC-4, David Brown wrote:
...
> may not access a multidimensional array as though it were a large
> unidimensional array - with many other kinds of banned (or undefined, or
> invalid) behaviour having similar points.
...
> sub-arrays in SIMD registers, or arrange them for better cache locality.
> On platforms with multiple independent ram blocks, it could put
> different parts in different blocks to improve throughpput.
 
The standard explicitly requires that arrays be allocated contiguously
(9.2.3.4p1). Violating that requirement for well-formed code requires
invoking the as-if rule. Since the array bounds rule gives undefined
behavior to many of the simplest kinds of code you could write to prove
that an array is not contiguous, it does open up the scope for applying
the as-if rule, but it's not an open-ended release from that
requirement. For instance, if std::memcpy(), std::memset(),
std::memcmp(), std::istream::read(), std::ostream::write() or sizeof are
applied to more than one row of such an array, they must have behavior
consistent with that requirement.
David Brown <david.brown@hesbynett.no>: Apr 04 04:00PM +0200

On 02/04/2019 14:46, Alf P. Steinbach wrote:
>> the same segment?
 
> It isn't and it couldn't, since you can do p+N by repeated application
> of indisputably well-defined P+1.
 
Yes, but you can't do p + N + 1 that way. Nor can you access data via
(p + N).
 
A compiler /could/ split a multidimensional array across memory
segments, if all access was done using the array pointers. But it is
legal to access the whole array as one object using char pointers, or
memcpy, and it would be rather difficult to maintain logical correctness
while having the data physically split up.
 
 
 
David Brown <david.brown@hesbynett.no>: Apr 04 04:08PM +0200

>> different parts in different blocks to improve throughpput.
 
> The standard explicitly requires that arrays be allocated contiguously
> (9.2.3.4p1).
 
I started writing an explanation of how non-contiguous arrays could
work, but I see you've covered it nicely yourself.
 
I don't know if compilers actually do this, but they are certainly
allowed to (with the restrictions you list).
 
"Öö Tiib" <ootiib@hot.ee>: Apr 04 09:14AM -0700

On Thursday, 4 April 2019 16:30:00 UTC+3, David Brown wrote:
> mistakes and help the user correct them. If these out-of-bounds
> accesses were defined behaviour, tools could not tell if the programmer
> had a bug in their code or was intentionally mistreating their arrays.
 
Yes, sure an UB encourages tool writers to check for particular UB.
Fortunately the tools do not limit to such but have also tendency to
warn us about when there are no UB but the situation feels otherwise
questionable.
 
> knows more about possible aliasing, meaning it can do better at
> automatically vectorising code, or re-arranging accesses for better
> scheduling.
 
It is always possible that there is some optimization about aliasing
but it feels unlikely about pointers to same type. The restrict keyword
was likely added to C because assumptions like that A[-2] and B[3]
are different objects does indeed help to optimize but compiler is in
difficulties to find any reasons to assume that. It feels not much
better when A and B are pointers of multidimensional array. Can
you bring any example of such optimizations?
 
> sub-arrays in SIMD registers, or arrange them for better cache locality.
> On platforms with multiple independent ram blocks, it could put
> different parts in different blocks to improve throughpput.
 
When compiler is sure that it is such local array that it may rearrange
then the compiler is also free to do it when that UB was not in standard.
 
> does what it appears to say it will do. Code that defines arrays of a
> particular size, then pretends they are something different, is
> inevitably going to be harder to follow.
 
I do not see how. The huge pile of potential UBs on every step is not
helping us to write code that does what it appears to say it does.
We see how even most advanced specialists argue if something is
UB or nonsense hearsay. I fail to see with what that helped (if
we leave aside that you brought in 1) that it encourages tool makers
to diagnose it).
 
Note that standard clearly allows us to access and to do pointer
arithmetics over whole array of arrays with char pointers when we
intentionally want/need to be so unusual there.
 
David Brown <david.brown@hesbynett.no>: Apr 04 08:21PM +0200

On 04/04/2019 18:14, Öö Tiib wrote:
> Fortunately the tools do not limit to such but have also tendency to
> warn us about when there are no UB but the situation feels otherwise
> questionable.
 
That's true, of course. But it's easier when there is clarity in the
situation - if the compiler can see you've stepped outside the valid
ranges for the array, it can give the warning. If the behaviour had
been allowed, but questionable, then you'd need more optional flags, or
ways to help the compiler distinguish false positives from intentional
coding. (I'm thinking here of things like writing "if ((x = a))..."
with extra parenthesis, so that the compiler knows the legal but
questionable code is intentional.)
 
> difficulties to find any reasons to assume that. It feels not much
> better when A and B are pointers of multidimensional array. Can
> you bring any example of such optimizations?
 
It is often difficult to think of examples - and just because a compiler
/can/ use information for optimisation, does not mean that it /will/.
But basically, with the rules laid out in the standards, the compiler
knows that A[i][j] and A[x][y] cannot alias if i != x, no matter what j
and y are. This could have an effect in some code, such as in-place
matrix operations.
 
I don't imagine it will often give optimisation opportunities, but
sometimes it will - and if it means you can use vector operations, it
can be significant.
 
>> different parts in different blocks to improve throughpput.
 
> When compiler is sure that it is such local array that it may rearrange
> then the compiler is also free to do it when that UB was not in standard.
 
True. But the UB means that it already knows certain types of access
can't happen, which can make it easier to be sure the re-arrangement is
safe.
 
Again, I can't tell you if compilers do this sort of thing, or if it is
often significant. All I can say is that the UB gives the compiler more
information about what can't happen, and that can open more optimisation
and rearrangement possibilities.
 
>> inevitably going to be harder to follow.
 
> I do not see how. The huge pile of potential UBs on every step is not
> helping us to write code that does what it appears to say it does.
 
Yes, it does. By having rules that say you are not allowed to write
code in such-and-such a way, people are less likely to write code that way.
 
> UB or nonsense hearsay. I fail to see with what that helped (if
> we leave aside that you brought in 1) that it encourages tool makers
> to diagnose it).
 
I don't think anyone is arguing that out-of-bounds sub-array access is
UB or not - the standards are entirely clear on the matter. There is
some disagreement about whether it /should/ be UB, and whether compilers
should take advantage of that or whether they should consider it to be
defined behaviour (compilers can always give a definition of particular
undefined behaviours).
 
 
> Note that standard clearly allows us to access and to do pointer
> arithmetics over whole array of arrays with char pointers when we
> intentionally want/need to be so unusual there.
 
Yes.
 
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Apr 04 02:01PM +0100

On 04/04/2019 11:54, Rick C. Hodgin wrote:
> your course.
 
> There's so much more available to you than what you see today,
> Leigh ... if only you'd be willing to receive it.
 
Nonsense.
A) Your bible is false.
B) Your god the existence of which is predicated on your bible being true
is, given (A), also false.
 
/Flibble
 
--
"You won't burn in hell. But be nice anyway." – Ricky Gervais
 
"I see Atheists are fighting and killing each other again, over who
doesn't believe in any God the most. Oh, no..wait.. that never happens." –
Ricky Gervais
 
"Suppose it's all true, and you walk up to the pearly gates, and are
confronted by God," Bryne asked on his show The Meaning of Life. "What
will Stephen Fry say to him, her, or it?"
"I'd say, bone cancer in children? What's that about?" Fry replied.
"How dare you? How dare you create a world to which there is such misery
that is not our fault. It's not right, it's utterly, utterly evil."
"Why should I respect a capricious, mean-minded, stupid God who creates a
world that is so full of injustice and pain. That's what I would say."
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: