Monday, January 16, 2023

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

David Brown <david.brown@hesbynett.no>: Jan 16 11:32AM +0100

On 13/01/2023 22:43, Chris M. Thomasson wrote:
> debugger would show that the vector contained no elements, however, one
> was there. Then there are other oddities.
 
> I have never had this problem with MSVC before.
 
Are you debugging optimised code here? Remember that when
single-stepping or using breakpoints, a debugger is working primarily
with the generated object code. And when looking at variables, it is
mainly using the data in memory or registers. But there is often a
disconnect between the lines of the source code and the generated object
code - a line you step over might /logically/ put an element into a
vector, but the actual change to the data structure could be done far
latter in the code.
 
MSVC has traditionally had quite a simplistic handling for a lot of code
generation - it has done little in the way of re-arranging code. But I
have heard (I don't use the tool myself) that is does more manipulation
these days.
 
When using gcc and a debugger, it is quite normal for single-stepping to
jump around the code, for things to happen long before or long after you
might think from the "current" source line, for variables to be
"optimised out", etc. Debugging optimised code is something of an art.
David Brown <david.brown@hesbynett.no>: Jan 16 11:37AM +0100

On 14/01/2023 23:44, Chris M. Thomasson wrote:
>> Perhaps that
>> was the issue you had?
 
> In debug mode.
 
"Debug mode" is mostly a meaningless concept.
 
Many IDE's set up two different build configurations - one they call
"Debug" with low optimisation and lots of debugger information, and one
they call "Release" with high optimisation and little debugger
information. But there is not really such a thing as "optimised" code
and "unoptimised" code - compilers can enable or disable different
passes and different kinds of optimisations. Some "optimisations" are
done even when compilers are set to "no optimisation", and some
optimisation passes that are possible are not done even on "highest
optimisation" flags. (And some "optimisations" can make code slower in
practice.)
 
At best, "debug mode" reduces the risk of seeing such disconnects
between the source code and the effect of the object code, but it will
not eliminate it.
Muttley@dastardlyhq.com: Jan 16 11:31AM

On Mon, 16 Jan 2023 11:32:34 +0100
>jump around the code, for things to happen long before or long after you
>might think from the "current" source line, for variables to be
>"optimised out", etc. Debugging optimised code is something of an art.
 
And debugging optimised multithreaded code will end up with you gibbering in
a corner shouting "Deadlock!" or "Race!" at any nearby pigeons.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jan 16 11:45AM -0800

On 1/16/2023 2:37 AM, David Brown wrote:
 
> At best, "debug mode" reduces the risk of seeing such disconnects
> between the source code and the effect of the object code, but it will
> not eliminate it.
 
I have a lot of experience with MSVC. Optimization is disabled in Debug
mode by default. I have not artificially altered the optimization
settings. I have never had these problems with the MSVC debugger before.
Your comment just made me check, and it's disabled in Debug mode. Mr.
Flibble is right. The debugger is not up to par. Damn.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jan 16 11:46AM -0800

On 1/16/2023 2:32 AM, David Brown wrote:
>> one was there. Then there are other oddities.
 
>> I have never had this problem with MSVC before.
 
> Are you debugging optimised code here?
 
No. You made me double check the settings for debug mode. They are
disabled. I have never had this problem before in MSVC.
 
 
> jump around the code, for things to happen long before or long after you
> might think from the "current" source line, for variables to be
> "optimised out", etc.  Debugging optimised code is something of an art.
 
The MSVC has always worked really damn good, up until the recent
version... Damn!
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jan 16 11:51AM -0800

>> "optimised out", etc. Debugging optimised code is something of an art.
 
> And debugging optimised multithreaded code will end up with you gibbering in
> a corner shouting "Deadlock!" or "Race!" at any nearby pigeons.
 
MSVC's debugger was always pretty damn good. I have used it to debug
nightmare multi-threaded code created by somebody else, where I had to
pause threads at a specific line, in order to reproduce a certain bug
that would only trip once in a blue moon. Found it during artificially
stress and load testing. This was a long time ago. Actually, I think I
wrote about it here some years ago on this group.
 
Optimization is turned off in Debug mode. Wrt to the IDE:
 
https://i.ibb.co/SV3dMQ7/image.png
 
Never had this problem before.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jan 16 11:52AM -0800

On 1/16/2023 2:37 AM, David Brown wrote:
 
> At best, "debug mode" reduces the risk of seeing such disconnects
> between the source code and the effect of the object code, but it will
> not eliminate it.
 
https://i.ibb.co/SV3dMQ7/image.png
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jan 16 11:57AM -0800

On 1/16/2023 11:52 AM, Chris M. Thomasson wrote:
>> between the source code and the effect of the object code, but it will
>> not eliminate it.
 
> https://i.ibb.co/SV3dMQ7/image.png
 
I wonder if frame pointers has something to do with it. The thing is
that MSVC always just worked. I have never experienced anything like
this in it before. ;^o
Mr Flibble <flibble@reddwarf.jmc.corp>: Jan 16 08:49PM

On Mon, 16 Jan 2023 11:45:16 -0800, Chris M. Thomasson wrote:
 
> settings. I have never had these problems with the MSVC debugger before.
> Your comment just made me check, and it's disabled in Debug mode. Mr.
> Flibble is right. The debugger is not up to par. Damn.
 
As your codebase doesn't look as involved as mine do you think you are in
a position to create a test case and create a MSVC defect report? In the
meantime I recommend downgrading to VS2019.
 
/Flibble
Ralf Goertz <me@myprovider.invalid>: Jan 16 09:46AM +0100

Am Sun, 15 Jan 2023 08:57:24 -0800 (PST)
> > …
 
> Where N is the range and M the number of elements to choose, it's O(N)
> in space and time. So unsuitable if N is very much larger than M.
 
I just tried it out. Both methods (mine with the corrected off by 1
error) applied 100000 times outputting the last result:
 
./rg 10 1 1000
193 198 257 384 474 581 606 620 682 954
0.718732s
 
./rg 990 1 1000

0.715686s
 
./bonita 10 1 1000
919 888 875 567 563 499 323 306 61 34
14.0962s
 
./bonita 990 1 1000

4.7713s
 
 
The problem seems to be the unordered_set. I created it outside the loop
(just like my vector), but I had to empty it at the beginning of the
loop. (Is there another way to reuse it?) So in theory you're right but
I guess the set approach is a heavy burden.
 
My loop:
 
for (int k=0; k < 100000 ; ++k) {
fill( values.begin(), values.begin() + n, 1);
fill( values.begin() + n, values.end(), 0);
shuffle(values.begin(), values.end(), mt);
}
 
bonita's:
 
for (int k=0; k < 100000 ; ++k) {
values.erase( values.begin(), values.end());
//her stuff
}
Ralf Goertz <me@myprovider.invalid>: Jan 16 10:21AM +0100

Am Mon, 16 Jan 2023 09:46:15 +0100
> loop (just like my vector), but I had to empty it at the beginning of
> the loop. (Is there another way to reuse it?) So in theory you're
> right but I guess the set approach is a heavy burden.
 
Surprisingly, Bonita's method also seems to be very dependent on the
range:
 
./rg 10 1 10000
214 2035 2188 3525 4142 5765 6021 6571 7000 8902
7.09215s
 
(No surprise here.)
 
 
./bonita 10 1 10000
7400 7185 5343 4357 2990 2011 1478 1078 859 719
184.93s
 
(Wow!)
Bonita Montero <Bonita.Montero@gmail.com>: Jan 16 01:35PM +0100

Am 16.01.2023 um 10:21 schrieb Ralf Goertz:
 
 
> ./bonita 10 1 10000
> 7400 7185 5343 4357 2990 2011 1478 1078 859 719
> 184.93s
 
Test the algorithm without screen output !
Ralf Goertz <me@myprovider.invalid>: Jan 16 02:42PM +0100

Am Mon, 16 Jan 2023 13:35:57 +0100
> > 7400 7185 5343 4357 2990 2011 1478 1078 859 719
> > 184.93s
 
> Test the algorithm without screen output !
 
I did of course! The timer starts immediately before the loop and stops
after it, before only the last result is output. Your version:
 
 
#include <iostream>
#include <unordered_set>
#include <charconv>
#include <random>
#include <concepts>
#include <chrono>
#include <cstring>
 
using namespace std;
using namespace std::chrono;
 
int main( int argc, char** argv )
{
try
{
if( argc < 4 )
return
cout << argv[0] << " n from to" << endl,
EXIT_FAILURE;
auto parse = []( char const *str, char const *err )
{
size_t value;
if( from_chars_result fcr = from_chars( str, str + strlen( str ),
value ); (bool)fcr.ec || *fcr.ptr )
throw invalid_argument( err );
return value;
};
size_t n = parse( argv[1], "wrong number of values" );
if( !n )
return EXIT_SUCCESS;
size_t
from = parse( argv[2], "wrong from-value" ),
to = parse( argv[3], "wrong to-value" );
if( from > to )
swap(from, to);
if( n - 1 > to - from )
return
cout << "n is too small" << endl,
EXIT_FAILURE;
unordered_set<size_t> values;
mt19937_64 mt;
uniform_int_distribution<size_t> uid( from, to );
steady_clock::time_point t1 = steady_clock::now();
for (int k=0; k < 100000 ; ++k) {
values.erase( values.begin(), values.end());
if( to - from != (size_t)-1 && to - from + 1 < n / 2 )
{
values.reserve( n );
while( values.size() < n )
{
size_t value;
do
value = uid( mt );
while( values.contains( value ) );
values.emplace( value );
}
}
else
{
if( to - from == (size_t)-1 )
throw bad_alloc();
values.reserve( to - from + 1 );
size_t i = from - 1;
do
values.emplace( ++i );
while( i != to );
while( values.size() > n )
for( ; ; )
{
auto itRemove = values.find( uid( mt ) );
if( itRemove == values.end() )
continue;
values.erase( itRemove );
break;
}
}
}
steady_clock::time_point t2 = steady_clock::now();
for( size_t value : values )
cout << value << " ";
cout << endl << duration_cast<duration<double>>(t2 - t1)<<endl;
}
catch( exception const &exc )
{
return
cout << exc.what() << endl,
EXIT_FAILURE;
}
}
 
 
and mine:
 
 
#include <algorithm>
#include <iostream>
#include <random>
#include <charconv>
#include <vector>
#include <cstring>
#include <chrono>
 
using namespace std;
using namespace std::chrono;
 
int main( int argc, char** argv )
{
try
{
if( argc < 4 )
return
cout << argv[0] << " n from to" << endl,
EXIT_FAILURE;
auto parse = []( char const *str, char const *err )
{
size_t value;
if( from_chars_result fcr = from_chars( str, str + strlen( str ),
value ); (bool)fcr.ec || *fcr.ptr )
throw invalid_argument( err );
return value;
};
size_t n = parse( argv[1], "wrong number of values" );
if( !n )
return EXIT_SUCCESS;
size_t
from = parse( argv[2], "wrong from-value" ),
to = parse( argv[3], "wrong to-value" );
if( from > to )
swap(from, to);
if( n - 1 > to - from )
return
cout << "n is too small" << endl,
EXIT_FAILURE;
mt19937_64 mt;
vector<int> values( to - from + 1);
steady_clock::time_point t1 = steady_clock::now();
for (int k=0; k < 100000 ; ++k) {
fill(values.begin(), values.begin() + n, 1);
fill(values.begin() + n, values.end(), 0);
shuffle(values.begin(), values.end(), mt);
}
steady_clock::time_point t2 = steady_clock::now();
for( size_t i=0; i < values.size(); ++i )
if( values[i]) cout << i+from << " ";
cout << endl << duration_cast<duration<double>>(t2 - t1)<<endl;
 
}
catch( exception const &exc )
{
return
cout << exc.what() << endl,
EXIT_FAILURE;
}
}
Ralf Goertz <me@myprovider.invalid>: Jan 16 02:46PM +0100

Resent the reply, since I can't see it on my server.
 
Am Mon, 16 Jan 2023 13:35:57 +0100 schrieb Bonita Montero
> > 7400 7185 5343 4357 2990 2011 1478 1078 859 719
> > 184.93s
 
> Test the algorithm without screen output !
 
I did of course! The timer starts immediately before the loop and stops
after it, before only the last result is output. Your version:
 
 
#include <iostream>
#include <unordered_set>
#include <charconv>
#include <random>
#include <concepts>
#include <chrono>
#include <cstring>
 
using namespace std;
using namespace std::chrono;
 
int main( int argc, char** argv )
{
try
{
if( argc < 4 )
return
cout << argv[0] << " n from to" << endl,
EXIT_FAILURE;
auto parse = []( char const *str, char const *err )
{
size_t value;
if( from_chars_result fcr = from_chars( str, str + strlen( str ),
value ); (bool)fcr.ec || *fcr.ptr )
throw invalid_argument( err );
return value;
};
size_t n = parse( argv[1], "wrong number of values" );
if( !n )
return EXIT_SUCCESS;
size_t
from = parse( argv[2], "wrong from-value" ),
to = parse( argv[3], "wrong to-value" );
if( from > to )
swap(from, to);
if( n - 1 > to - from )
return
cout << "n is too small" << endl,
EXIT_FAILURE;
unordered_set<size_t> values;
mt19937_64 mt;
uniform_int_distribution<size_t> uid( from, to );
steady_clock::time_point t1 = steady_clock::now();
for (int k=0; k < 100000 ; ++k) {
values.erase( values.begin(), values.end());
if( to - from != (size_t)-1 && to - from + 1 < n / 2 )
{
values.reserve( n );
while( values.size() < n )
{
size_t value;
do
value = uid( mt );
while( values.contains( value ) );
values.emplace( value );
}
}
else
{
if( to - from == (size_t)-1 )
throw bad_alloc();
values.reserve( to - from + 1 );
size_t i = from - 1;
do
values.emplace( ++i );
while( i != to );
while( values.size() > n )
for( ; ; )
{
auto itRemove = values.find( uid( mt ) );
if( itRemove == values.end() )
continue;
values.erase( itRemove );
break;
}
}
}
steady_clock::time_point t2 = steady_clock::now();
for( size_t value : values )
cout << value << " ";
cout << endl << duration_cast<duration<double>>(t2 - t1)<<endl;
}
catch( exception const &exc )
{
return
cout << exc.what() << endl,
EXIT_FAILURE;
}
}
 
 
and mine:
 
 
#include <algorithm>
#include <iostream>
#include <random>
#include <charconv>
#include <vector>
#include <cstring>
#include <chrono>
 
using namespace std;
using namespace std::chrono;
 
int main( int argc, char** argv )
{
try
{
if( argc < 4 )
return
cout << argv[0] << " n from to" << endl,
EXIT_FAILURE;
auto parse = []( char const *str, char const *err )
{
size_t value;
if( from_chars_result fcr = from_chars( str, str + strlen( str ),
value ); (bool)fcr.ec || *fcr.ptr )
throw invalid_argument( err );
return value;
};
size_t n = parse( argv[1], "wrong number of values" );
if( !n )
return EXIT_SUCCESS;
size_t
from = parse( argv[2], "wrong from-value" ),
to = parse( argv[3], "wrong to-value" );
if( from > to )
swap(from, to);
if( n - 1 > to - from )
return
cout << "n is too small" << endl,
EXIT_FAILURE;
mt19937_64 mt;
vector<int> values( to - from + 1);
steady_clock::time_point t1 = steady_clock::now();
for (int k=0; k < 100000 ; ++k) {
fill(values.begin(), values.begin() + n, 1);
fill(values.begin() + n, values.end(), 0);
shuffle(values.begin(), values.end(), mt);
}
steady_clock::time_point t2 = steady_clock::now();
for( size_t i=0; i < values.size(); ++i )
if( values[i]) cout << i+from << " ";
cout << endl << duration_cast<duration<double>>(t2 - t1)<<endl;
 
}
catch( exception const &exc )
{
return
cout << exc.what() << endl,
EXIT_FAILURE;
}
}
Muttley@dastardlyhq.com: Jan 16 04:38PM

On Mon, 16 Jan 2023 14:42:50 +0100
 
>> Test the algorithm without screen output !
 
>I did of course! The timer starts immediately before the loop and stops
>after it, before only the last result is output. Your version:
 
But wait, didn't she state that her algorithm was "perfect"? I simply won't
believe Bonita has more hubris and self delusion than an angry mouse.
Bonita Montero <Bonita.Montero@gmail.com>: Jan 16 09:06PM +0100


> But wait, didn't she state that her algorithm was "perfect"? I simply won't
> believe Bonita has more hubris and self delusion than an angry mouse.
 
And you don't check that Ralf's code does sth. completely different.
David Brown <david.brown@hesbynett.no>: Jan 16 11:17AM +0100

On 14/01/2023 08:24, Juha Nieminen wrote:
 
> I write: "Nothing of what I wrote is controversial."
 
> You read: "Nothing of what I wrote is controversial, how could anyone
> disagree with me?"
 
Perhaps you don't know what the word "controversial" actually means?
Your written English is much better than most native English speakers',
but anyone can make a mistake. If something is "controversial", it
means people have different opinions about it - there is a fair amount
of disagreement. If something is /not/ controversial, or
"uncontroversial", it means that there is /no/ disagreement about it of
any relevance. (There's always the odd extremist, such as the c.l.c.
member who thinks "#define R return" is a good start to a program.)
 
No one is reading between the lines here - anyone who writes that their
own opinion, which differs from others, is "uncontroversial" is either
ignorant or arrogant, or has not written what they meant to write. You
are not ignorant - and you don't like been seen as arrogant. Perhaps
this whole branch of the thread is due to your thinking that
"uncontroversial" means "widely held opinion" ?
 
 
> I am not objecting to the disagreements.
 
You clearly have been objecting to them!
 
> I am objecting to the repeated
> confrontational attitude shown by some people who seem to be set on
> trying to "deconvert" me from this heresy.
 
But you expect others to believe /your/ repeated but unsupported claims,
veiled accusations, and unveiled profanities? Don't you see any
hypocrisy in this?
 
Here's a little thought experiment. Imagine, for a moment, that other
people really have found that using "i" as an index variable can make
some code easier to read and clearer to understand, compared to using a
more descriptive name with full words. For someone with the personal
experience to back that up, how do you think your posts appear? You are
telling that person they are insane, and that everyone knows without
doubt that they are wrong. You are telling them that their experience
as a professional developer for decades, is /wrong/. You write with
such a determined, uncompromising conviction in your own ideas that you
leave no room for variation, opinion, or personal opinion. And then you
accuse /others/ of being confrontational. So imagine yourself on the
other side of the table for a moment, re-read your own posts, and
consider how they look.
 
> have taken this as their hill to die on. (You may accuse me of that
> very same thing, and you would have a point, but I am the one being
> on the defensive here.)
 
You have a /very/ distorted view of this thread. /Very/ distorted.
There is only /one/ person in this thread who is fanatical about an
idea, and that is /you/. You have expressed an extremist view on
identifiers. Everyone else here has simply said that while we all agree
on the main principles, opinions and experience in the details will vary
by person, project, and circumstance.
 
> something I disagree with, some people here only take that one part
> and assert that Google fully disagrees with me. And then accuse me
> of just taking one part and ignoring the others.
 
Do you /still/ not understand?
 
We all /agree/ with you about the part of Google's guidelines that you
quoted. Any serious programmer knows to code for readability, and pick
good identifiers that can be understood by other people. Even
programmers who never look at other people's code learn that if you
write cryptic code with poor identifiers, you won't understand your own
code after a few months or years.
 
We all agree on "optimise for readability and understandable code, not
for brevity or identifier size".
 
 
> I am not ignoring the part of Google's coding guideline I disagree
> with. I quoted the part that I agree with, to highlight that it's
> not some kind of unique controversial stance.
 
No one has /ever/ suggested that this part of Google's guidelines are
particularly controversial, or that you are unusual in agreeing with
them - we /all/ agree with them more or less. (People might have
different opinions on how much project-specific knowledge should be
required by people reading code, but that's details, not principle.)
 
The disagreement is on your stance that /all/ identifiers should be full
words and fully descriptive. It is that opinion that is unusual and
extreme - it is contrary to Google's guidelines and others that I have
seen, contrary to common practice and idiomatic code, and several people
here (including me) have said that in their experience, short
identifiers (such as loop index "i") often /increase/ readability and
code understanding in small scopes. But I have no problem in accepting
that /your/ experience might be different and /your/ opinion might be
different from mine here - I don't say you are wrong just because you
disagree with Google and others here.
 
 
I really don't understand how this can still be unclear to you.
 
 
> then defend it against criticism, than it is to present criticism
> of someone's idea. If someone criticizes the thing I suggested,
> it's natural to respond to that criticism in defense of the idea.
 
Feel free to try to defend your opinion. I would like to see your
reasoning, or understand what the circumstances are in which you find
descriptive identifiers critical even in small and obvious scopes. So
far I have seen nothing but repeated assertions, and appeals to code
guidelines that disagree with you.
 
But please stick to the controversial issues - /not/ the things we all
agree upon.
"Öö Tiib" <ootiib@hot.ee>: Jan 15 03:40PM -0800

On Sunday, 15 January 2023 at 21:38:02 UTC+2, quanzhou wrote:
> auto [a, ..., b] = y;
> auto [...,a, b] = z;
 
> helps to get the last member variable of the right side type.
 
I do not understand what it means. Can you describe a problem
and then write short example program that solves the problem
using that feature?
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: