Monday, September 14, 2020

Digest for comp.lang.c++@googlegroups.com - 25 updates in 6 topics

Nikki Locke <nikki@trumphurst.com>: Sep 14 10:23PM

Available C++ Libraries FAQ
 
URL: http://www.trumphurst.com/cpplibs/
 
This is a searchable list of libraries and utilities (both free
and commercial) available to C++ programmers.
 
If you know of a library which is not in the list, why not fill
in the form at http://www.trumphurst.com/cpplibs/cppsub.php
 
Maintainer: Nikki Locke - if you wish to contact me, please use the form on the website.
olcott <NoOne@NoWhere.com>: Sep 14 09:55AM -0500

On 9/14/2020 2:58 AM, Christian Hanné wrote:
> If someone new to C would learn C++ I'd recommend Visual C++
> becuase it's a more visual language. It's rather like Logo.
 
Not not at all not in the least. It is a rats nest of complexity.
 
--
Copyright 2020 Pete Olcott
David Brown <david.brown@hesbynett.no>: Sep 14 05:01PM +0200

On 14/09/2020 16:55, olcott wrote:
>> If someone new to C would learn C++ I'd recommend Visual C++
>> becuase it's a more visual language. It's rather like Logo.
 
> Not not at all not in the least. It is a rats nest of complexity.
 
The poster was surely joking!
Real Troll <real.troll@trolls.com>: Sep 14 05:10AM -1000

On 14/09/2020 14:17, Richard Harnden wrote:
 
> An IBM man-year .. 730 guys trying to get it done by lunch.
 
 
So it was all about too many cooks !!!!  Did they spoil the broth?
olcott <NoOne@NoWhere.com>: Sep 14 10:15AM -0500

On 9/10/2020 7:08 AM, David Brown wrote:
 
> (At least, that is my understanding - IANAL.)
 
> So the real question is, why bother putting a copyright message on the
> post when it is already covered automatically?
 
Because unlike most of the posts on Usenet I need to distinguish that my
posts related to the Halting Problem, Russell's Paradox, Gödel's 1931
Incompleteness Theorem and the Tarski Undefinability Theorem are mostly
brand new ideas originated by myself and not merely a rehash of what
others have said.
 
Although it is technically correct that a copyright arises whenever an
idea is put in fixed form most of the ideas presented on USENET are
mostly rehashes of the ideas of others. Because of this most people
would not generally carefully apply copyright law to USENET posts and
might consider some of my brand new ideas simply as rehashes of existing
ideas.
 
Here is the fundamental flaw in Gödel's 1931 Incompleteness Theorem:
A theory T is incomplete if and only if there is some sentence φ such
that (T ⊬ φ) and (T ⊬ ¬φ).
 
The definition of incompleteness decides that every formal system that
cannot prove or refute self-contradictory sentences is incomplete
entirely on the basis that the formal system cannot prove or refute
self-contradictory sentences.
 
 
--
Copyright 2020 Pete Olcott
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Sep 14 01:20PM -0700

On 9/14/2020 3:55 AM, Real Troll wrote:
> than billion lines of code to be written or re-written using c# so it
> takes time!!.  Microsoft can't hire all the C# programmers to speed up
> the process.
 
I want to see the Kernel written in C#. That would be a trip. Fwiw, here
is the full source code to the WinNT 4 kernel:
 
https://github.com/ZoloZiak/WinNT4
 
Not sure if garbage collection is a "good idea" here.
James Kuyper <jameskuyper@alumni.caltech.edu>: Sep 14 09:58AM -0400

On 9/14/20 8:42 AM, Öö Tiib wrote:
> }
 
> It has no undefined behaviours I hope and where it does compile there
> it seems to work. Demo:
 
"undefined behavior" is defined by the C standard as behavior not
defined by the C standard, even if a particular implementation provides
it's own definition for the behavior.
 
Your code uses the identifier __builtin_ssub_overflow, which is not
defined by the C standard, and is reserved by that standard for all
uses. Declaring or defining that identifier yourself would render the
behavior of your program undefined.
 
Using it when it has been declared or defined by the implementation
(which is presumably the case on your system) has behavior that depends
entirely upon how the implementation defined __builtin_ssub_overflow().
It could be a syntax error, a constraint violation, or have undefined
behavior - or it might do precisely what you expect it to do.
 
Using that identifier in this manner when neither your own code nor the
implementation has provided a declaration or definition for it would be
a constraint violation: at least one diagnostic is mandatory, and
producing an executable program is optional. Should an implementation
choose to generate an executable program, and if you should choose to
execute it, the behavior is undefined.
Ben Bacarisse <ben.usenet@bsb.me.uk>: Sep 14 03:05PM +0100


> I wanted somehow at weekend to find maximum of two int32_t-s without
> branches (like ifs or ? operators) in C++.
 
You are trying to beat the compiler. Both std::max and the simple code
using ?: are optimised by gcc to minimal branch-free code. You function
comes out more than twice as long.
 
> }
 
> It has no undefined behaviours I hope and where it does compile there
> it seems to work.
 
You have implementation-defined behaviour, though, in the signed shift
when d is negative. And you are assuming that int32_t matches int.
 
> <http://coliru.stacked-crooked.com/a/19eca82b689292e5>
 
> However with raw C++ I am in trouble. Does anyone have some idea
> how to do the trick in raw C++?
 
I presume "raw" means no std::max?
 
--
Ben.
David Brown <david.brown@hesbynett.no>: Sep 14 04:16PM +0200

On 14/09/2020 14:42, Öö Tiib wrote:
> <http://coliru.stacked-crooked.com/a/19eca82b689292e5>
 
> However with raw C++ I am in trouble. Does anyone have some idea
> how to do the trick in raw C++?
 
How about:
 
int32_t mad_max2(int32_t a, int32_t b) {
return a > b : a ? b;
}
 
Write the source clearly, and let the /compiler/ generate the
appropriate object code. It is likely to do a better job than you in
most cases.
 
To start with, why do you think avoiding branches is useful?
/Sometimes/ it is - but depending on the target processor, the
predictability of the branch, and the surrounding code, branches can
sometimes be handled in the cpu's decoder units before they even make it
to the execution units. That's zero cost. Let the compiler put in a
branch if that's what suits with the rest of the instructions in the code.
 
The typical code for mad_max2 for generic x86_64 cpus is:
 
mad_max2(int, int):
cmp edi, esi
mov eax, esi
cmovge eax, edi
ret
 
No branches. But since a function like this is likely to be inlined,
the details in practice will depend on the surrounding code.
 
And don't bother with x86 intrinsics. If you know more about the target
processor, and know what instruction sets it supports, then tell the
compiler about them with "-march" flags. Then it will generate pmaxsd
instructions or whatever suits best.
David Brown <david.brown@hesbynett.no>: Sep 14 04:21PM +0200

On 14/09/2020 14:53, Bonita Montero wrote:
>     int32_t mask = a < b ? -1 : 0;
>     return a & ~mask | b & mask;
> }
 
That is a little less bad than the OP's suggestion, as it is reasonably
comprehensible. But it is still a dog's breakfast.
 
It's twenty years or more since it has made any sense to write this sort
of gibberish in anything but the most specialised of circumstances.
"Öö Tiib" <ootiib@hot.ee>: Sep 14 08:12AM -0700

On Monday, 14 September 2020 17:05:50 UTC+3, Ben Bacarisse wrote:
> > it seems to work.
 
> You have implementation-defined behaviour, though, in the signed shift
> when d is negative. And you are assuming that int32_t matches int.
 
That implementation-defined is flaw that I asked ideas of how to get
rid of. If that assumption does not hold then the code is ill-formed
so I did not bother to add additional static_asserts doing same into
example that is not what I wanted to achieve anyway.
 
 
> > However with raw C++ I am in trouble. Does anyone have some idea
> > how to do the trick in raw C++?
 
> I presume "raw" means no std::max?
 
Yes, since it is unknown if that std::max uses branches or does not.
Actually same is unknown about __builtin_ssub_overflow but gcc docs
say they try their best.
Tim Rentsch <tr.17687@z991.linuxsc.com>: Sep 14 08:26AM -0700

> <http://coliru.stacked-crooked.com/a/19eca82b689292e5>
 
> However with raw C++ I am in trouble. Does anyone have some idea
> how to do the trick in raw C++?
 
Neither for() nor if() nor switch() now while() nor ?: is needed
for Turing completeness:
 
static int
give_a( int a, int b ){
return a;
}
 
static int
give_b( int a, int b ){
return b;
}
 
int
no_control_max( int a, int b ){
int (*choose[2])( int, int ) = { give_a, give_b };
return choose[ b > a ]( a, b );
}
 
Compiles cleanly as both C{90,99,11} and C++{98,03,11,14,17}.
scott@slp53.sl.home (Scott Lurndal): Sep 14 03:35PM

>comprehensible. But it is still a dog's breakfast.
 
>It's twenty years or more since it has made any sense to write this sort
>of gibberish in anything but the most specialised of circumstances.
 
Given the intel/amd 'CMOVxx' instruction and the ARM "CSET" instruction,
the compilers will generate the most optimal branchless code for a max
check even without optimization.
"Öö Tiib" <ootiib@hot.ee>: Sep 14 08:46AM -0700

On Monday, 14 September 2020 17:17:08 UTC+3, David Brown wrote:
 
> int32_t mad_max2(int32_t a, int32_t b) {
> return a > b : a ? b;
> }
 
Thanks, that is same what std::max compiles to. Unfortunately there
is branch on RISC-V (for example) while my convoluted gibberish did
not have branch.
 
> mov eax, esi
> cmovge eax, edi
> ret
 
I know, but when the target isn't x86_x64 there can be branches.
 
> processor, and know what instruction sets it supports, then tell the
> compiler about them with "-march" flags. Then it will generate pmaxsd
> instructions or whatever suits best.
 
That was my hope to get rid of whatever (not exactly x86 but gcc)
specific.
Bonita Montero <Bonita.Montero@gmail.com>: Sep 14 05:49PM +0200

>> }
 
> That is a little less bad than the OP's suggestion, as it is reasonably
> comprehensible. But it is still a dog's breakfast.
 
It works if the compiler supports this trick.
But support for this is very common.
"Öö Tiib" <ootiib@hot.ee>: Sep 14 10:01AM -0700

On Monday, 14 September 2020 18:49:29 UTC+3, Bonita Montero wrote:
> > comprehensible. But it is still a dog's breakfast.
 
> It works if the compiler supports this trick.
> But support for this is very common.
 
Yes it works where it works, thanks. David is also correct that what
std::max does (a > b ? a : b) is also often without branches on
such platforms.
Bonita Montero <Bonita.Montero@gmail.com>: Sep 14 07:08PM +0200


> Yes it works where it works, thanks. David is also correct that what
> std::max does (a > b ? a : b) is also often without branches on
> such platforms.
 
std::max normally maps to "a > b ? a : b" and and this results usually
in a branch where a predicated move isn't possible. The trick I've shown
is common with most compilers and today's compilers detect what's going
on there and further replace it with a conditional move. So you have
both: a conditional move on platforms that support it and a non-branched
version on platforms that usually would use a branch.
And I think the SSE-code would be rather slow as you would have to store
the GPR-register into memory and then from memory to the SSE-register
and then the way back.
David Brown <david.brown@hesbynett.no>: Sep 14 08:19PM +0200

On 14/09/2020 17:49, Bonita Montero wrote:
>> comprehensible.  But it is still a dog's breakfast.
 
> It works if the compiler supports this trick.
> But support for this is very common.
 
I can't imagine a compiler that would recognize the pattern you've given
here and generate decent code, but would fail to give at least as good
results for the simple, clean, obvious "max" expression.
 
Code like you've given here should be rejected by any code review if it
is not accompanied with detailed test results showing exactly why the
"max" function is performance critical, and demonstrating that this
source code gives significant measurably better results than the simple
version.
 
Code like the OP's, however, should be rejected outright - with a
suggestion that the programmer re-think his or her priorities in writing
code.
Bonita Montero <Bonita.Montero@gmail.com>: Sep 14 08:22PM +0200

> I can't imagine a compiler that would recognize the pattern you've given
> here and generate decent code, but would fail to give at least as good
> results for the simple, clean, obvious "max" expression.
 
Usually it results in "cmp regA, regB; sbb regC, regC" if the compiler
doesn't detect the data-flow and further replaces it with a CMOV if
possible. I used this pattern a long time ago and it was supported by
MSVC and gcc.
 
> "max" function is performance critical, and demonstrating that this
> source code gives significant measurably better results than the simple
> version.
 
Idiocracy ...
David Brown <david.brown@hesbynett.no>: Sep 14 08:25PM +0200

On 14/09/2020 17:46, Öö Tiib wrote:
 
> Thanks, that is same what std::max compiles to. Unfortunately there
> is branch on RISC-V (for example) while my convoluted gibberish did
> not have branch.
 
Have you done comprehensive tests showing that your function here is
performance critical to the code, that your gibberish is actually faster
than simple branched code, and that this applies even when used in
/real/ code where the simple version can be used for further
optimisation, unlike your gibberish? I strongly suspect not.
 
>> cmovge eax, edi
>> ret
 
> I know, but when the target isn't x86_x64 there can be branches.
 
So what? On many targets, branches are cheap. On those that are not,
the compiler will avoid branches. And if the target port is relatively
young on gcc (like RISC-V) and not well optimised as yet, then messing
around with this stuff is just bikeshedding.
 
"Öö Tiib" <ootiib@hot.ee>: Sep 14 11:52AM -0700

On Monday, 14 September 2020 21:25:28 UTC+3, David Brown wrote:
> than simple branched code, and that this applies even when used in
> /real/ code where the simple version can be used for further
> optimisation, unlike your gibberish? I strongly suspect not.
 
If you think that I somehow considered it as good and useful example
of programming then it is incorrect. Possibly it is miscommunication of
mine that you have such impression. I only wanted to demonstrate that
the weird code gives correct answers and has no branches on platforms
with overflow flag.
 
> the compiler will avoid branches. And if the target port is relatively
> young on gcc (like RISC-V) and not well optimised as yet, then messing
> around with this stuff is just bikeshedding.
 
I know. I did try to mention that I did it at weekend. And shared
without desire to spoil anyone's mood, sorry. ;)
David Brown <david.brown@hesbynett.no>: Sep 14 09:39PM +0200

On 14/09/2020 20:52, Öö Tiib wrote:
> mine that you have such impression. I only wanted to demonstrate that
> the weird code gives correct answers and has no branches on platforms
> with overflow flag.
 
Ah, okay. That makes more sense. My apologies if I misunderstood your
intentions.
 
I have many times seen people write "smart-arse" code, thinking it was a
good idea, when almost invariably it is not. Having had to deal with
such code on occasion, I react strongly against it when I see it. I
must admit I thought it was odd to see it coming from you!
 
>> around with this stuff is just bikeshedding.
 
> I know. I did try to mention that I did it at weekend. And shared
> without desire to spoil anyone's mood, sorry. ;)
 
Fair enough.
 
One thing that might come out of this would be how gcc handles the
simple max code in gcc for RISC-V. If the code is not optimal (I don't
know the RISC-V well enough to tell) and there is a better branchless
pattern, then it could be worth filing it as a missed optimisation bug
in gcc. It's always useful for them to get common patterns into the
peephole optimiser for each target.
Udo Steinbach <trashcan@udoline.de>: Sep 14 05:45PM +0200

void func(std::uint64_t); // not implemented
void func(std::uint32_t);
calls with other types are ambiguous, compile error.
 
or add an indirection.
 
void funcImpl(std::uint32_t);
template<typename T> inline void func(T Value)
{ static_assert(CheckTheType);
assert(CheckTheValue);
funcImpl(Value);
}
 
or make it nonconvertible
 
struct MyValue { uint32_t V; }
void func(uint64_t);
void func(MyValue);
 
func(MyValue{12344});
 
 
But my favorite is: Don't try to solve social problems with tech. Document
it, users have to read and follow.
--
Fahrradverkehr in Deutschland: http://radwege.udoline.de/
GPG: A245 F153 0636 6E34 E2F3 E1EB 817A B14D 3E7E 482E
scott@slp53.sl.home (Scott Lurndal): Sep 14 03:31PM

>CPUs like consecutive memory accesses and dislike memory accesses that
>jump in large steps, or randomly. How OOP has been implemented inevitably
>leads to the latter, which is bad for performance.
 
Where did you get the idea that CPUs like consecutive memory accesses?
 
Modern cache subsystems and store buffers accomodate non-consecutive memory
accesses rather well (with 90%+ hit rates for most applications).
 
>program execution is going to go. If they don't see it, or if they
>"guess" it wrong, it causes a performance penalty. Virtual functions
>largely work against this, causing even more performance hits.
 
Again, modern processors handle this rather well using techniques
such as branch target buffers and return stack caches.
 
>OOP implementations oftentimes hinder compiler optimizations, eg. when it
>comes to autovectorization. It's relatively easy to show practical
>examples of this.
 
Please do. Also note the relatively small number of code sequences that
are actually amenable to autovectorization.
Leo <usenet@gkbrk.com>: Sep 14 06:11PM +0300

On 8/17/20 2:51 PM, Frederick Gotham wrote:
 
> I hear that "glib" is the best library for C that gives the functionality of the C++ standard library and also Boost.
 
> Looking through the 'glib' reference manual here though, I don't see anything similar to "std::next_permutation".
 
> Is glib the best thing to use for porting C++11 code to C if you're looking for functionality similar to <algorithm> <numeric> <functional>?
 
For a microcontroller, you will probably be served better by using a
smaller library and compiling with -Os and -flto to clean up all the
unused stuff.
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: