Thursday, May 18, 2017

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

bitrex <bitrex@de.lete.earthlink.net>: May 18 09:49AM -0400

On 05/18/2017 04:00 AM, Fred.Zwarts wrote:
> for (size_t i = 0; i < ARRAY_SIZE && !found; ++i) {
> found = (myArray[i] == search_value);
> }
 
Years of Python has corrupted me I think. ;-)
 
I don't like having multiple conditionals in for loops, I think it can
be kinda confusing
David Brown <david.brown@hesbynett.no>: May 18 05:03PM +0200

On 18/05/17 16:20, Alf P. Steinbach wrote:
 
> It would not be a good idea to use it as an authority on anything C++.
 
> Don't know about MISRA but I suspect the same story: a special purpose
> thing.
 
My point is that you can't claim something "is considered bad style"
unless you can point to a reference. It is up the OP to find what he
feels is an appropriate reference for his claim.
David Brown <david.brown@hesbynett.no>: May 18 05:06PM +0200

On 18/05/17 15:07, Cholo Lennon wrote:
>> { int miles {};
>> ::std::cout << "Enter the miles used (-1 to quit): "s;
 
> Why the use of the literal s? It's really unnecessary :-O
 
It is there for the same reason as the annoying extra ::, the ugly,
weird and unnecessary initialisation of variables like "int miles {};",
and the strange bracketing style.
 
I suspect the point is that he can tell if his students wrote their
homework code themselves rather than copying and pasting it from the
internet - by encouraging this unique style that is different from
everyone else, students will be forced to re-write anything they copy.
Jorgen Grahn <grahn+nntp@snipabacken.se>: May 18 03:26PM

On Thu, 2017-05-18, Bob Langelaan wrote:
 
> I created the post below for my students on this topic some time
> ago. I would be interested in getting feedback on my post and the
> topic in general.
 
To add my five cents to the big pile: I think I'm guided by this:
 
- I want to be able to read my loops and convince myself they are
correct.
- My efforts may be better needed elsewhere.
 
Break, continue, return and throw sometimes helps with both those
things, so I use them.
 
What I'd do if I was you would be to teach the students to /read/ a
loop, so they can tell if it's correct or not. Things like
invariants. When is it safe to enter this loop? What's the state
when we exit? What's always true inside of it?
 
If you can reason about those things even with break and continue,
they are applied correctly, and not a problem.
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
Daniel <danielaparker@gmail.com>: May 18 08:30AM -0700

On Thursday, May 18, 2017 at 3:37:02 AM UTC-4, David Brown wrote:
> if (C) break; // Exit when C is reached
> ...
> }
 
For a moment I thought you were introducing a goto label.
 
Daniel
bitrex <bitrex@de.lete.earthlink.net>: May 18 12:01PM -0400

On 05/18/2017 10:34 AM, Stefan Ram wrote:
> which must be something the OP also should dislike. (For a
> top-down reading, one should start at »main«, which is at
> the bottom of the program.)
 
Ya, rather short methods. I'm working on a little graphics engine at the
moment using Allegro 5 and probably 80% of my methods are fewer than 5
lines. I've been a little more lax; sometimes there's no choice but to
have a bunch of lines cuz you have to declare a bunch of verticies and
the straight-C API syntax is a little unwieldy, but anything more than
20 lines or so, that can't be fit on approximately half a display in the
IDE, feels too big.
bitrex <bitrex@de.lete.earthlink.net>: May 18 12:20PM -0400

On 05/18/2017 12:06 AM, Bob Langelaan wrote:
 
> I created the post below for my students on this topic some time ago. I would be interested in getting feedback on my post and the topic in general.
 
> Thanks in advance,
 
> Bob
 
<snip>
 
The question I would have is: are you actually teaching C++, or are you
teaching "intro programming concepts"? From the examples given it
doesn't seem like you're actually teaching C++ as many of them don't
even seem like very good modern C, much less modern C++.
 
IMO C++ isn't a very good "intro to programming concepts/computer
science" language. My first "real" programming languages (other than
Basic on the Apple II) were Pascal and C, simply because in 1991 or
whenever that was kind of what was available. If I'd had other options
though I don't think I would've picked those.
 
I've heard some say things like "but if you don't learn a systems
language first you'll never understand things like strong typing,
pointers, dynamic memory allocation, etc." and I don't know. I don't
really buy it.
 
If it is indeed a C++ course for people who already have programming
experience, where exactly are they coming from? They have "friends at
Microsoft" and yet need to be taught how to use "while" loops and when
break and continue is appropriate and when it isn't? I would think that
a "intro to C++" course for students who already have programming
experience would spend like 2 days on the various reserved words/control
structures in the language and then jump right into real C++ concepts
like classes, inheritance, virtual methods, RAII, smart pointers/memory
management, etc.
 
Many other languages have "continue" and "break" and loops and similar
structures. What gives?
 
Frankly these days if I absolutely had to use a general purpose systems
language for an "programming concepts" language it would probably be
something like Rust or Go and not C++.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: May 18 07:27AM +0200

On 18-May-17 6:06 AM, Bob Langelaan wrote:
> I teach a beginner C++ course and have taught my students that they
> should minimize the use of the break; and continue; statements.
 
Good advice. :)
 
 
 
> I created the post below for my students on this topic some time ago.
> I would be interested in getting feedback on my post and the topic in
> general.
 
Well, the concrete advice on rewriting a loop-and-a-half,
 
for( ;; )
{
int value;
cout << "Value (0 to quit? ";
cin >> value;
if( value == 0 )
{
break;
}
// Do computations, present result.
}
 
as
 
int value;
cout << "Value (0 to quit? ";
cin >> value;
while( value != 0 )
{
// Do computations, present result.
cout << "Value (0 to quit? ";
cin >> value;
}
 
is ungood, downright evil, because
 
1. it introduces undesirable redundancy, repeated code. Not doing that
is known as the DRY principle: Don't Repeat Yourself. Stick to DRY.
 
2. It needlessly expands the scope of the support variables.
And if that scope is contained via an outer curly braces block,
then it needlessly adds extra indentation.
 
You say about it:
 
> duplication is preferred over having an unnecessary break statement or
> continue statement in the loop. In other words, in this case it is
> considered the lessor of two evils :)
 
No, it's not the lesser of two evils. It's an evil introduced to avoid
perfectly good ordinary code because you have OVER-GENERALIZED a rule
about avoiding `break`. You have made it an absolute rule, which is easy
to follow mechanically but produces rather sub-optimal results, instead
of a guideline that requires intelligence in its application.
 
Instead IMO you should teach your students about loop-and-a-half: how to
recognize that it's logically there (code duplication) and how to
express it properly (with a break or return or throw in the middle).
 
• • •
 
That said, your students' argument about `break` being used at Microsoft
is not a valid argument.
 
Very seldom do you find as dirty and invalid code as at Microsoft. To
wit, their documentation has a host of instances of invalid `void main`.
Not to mention the Microsoft monstrosities such as `tmain`. These are
beginner mistakes. And they're all over the place at MS.
 
 
Cheers & hth.,
 
- Alf
woodbrian77@gmail.com: May 18 11:10AM -0700

On Thursday, May 18, 2017 at 10:26:32 AM UTC-5, Jorgen Grahn wrote:
> when we exit? What's always true inside of it?
 
> If you can reason about those things even with break and continue,
> they are applied correctly, and not a problem.
 
+1. I generally don't have a problem with these things either.
 
 
Brian
Ebenezer Enterprises - In G-d we trust.
http://webEbenezer.net
Ian Collins <ian-news@hotmail.com>: May 18 06:34PM +1200

On 05/18/17 04:06 PM, Bob Langelaan wrote:
> I teach a beginner C++ course and have taught my students that they
> should minimize the use of the break; and continue; statements.
 
Good advice with an emphasis on "minimise", they sometimes have their place.
 
Most places where beak is used in a loop can be replaced with a return
if the loop is extracted into a function :)
 
--
Ian
David Brown <david.brown@hesbynett.no>: May 18 09:36AM +0200

(/Please/ get a proper newsreader. It is nearly impossible to deal with
google-groups line split crap without making a mess.)
 
On 18/05/17 06:06, Bob Langelaan wrote:
> I have been getting push back from some of my students with statements
> like "my friends at Microsoft tell me they use break; statements all the
> time" and similar types of objections.
 
/Minimizing/ the use of "break" is good - obsessing about it or banning
it is not. I find "continue" to be very rarely useful - I could happily
live without it in the language. But sometimes "break" really is the
best way to structure a loop.
 
 
> I will go further and say that, generally speaking, a programmer
> should try to limit the use of break statements to exiting from a switch
> statement. And that the continue statement should almost never be used.
 
That paragraph does not read well. I first thought you had said that
"break" should not be used to exit switch statements either.
 
> .
> .
> } // end of while loop
 
It is rare that you want to have the same test twice - but not /always/
bad. It is likely that in a case like this, you could remove the
condition at the start, making it a "while (true)" loop. In a "while
(true)" loop, it is perfectly clear that the loop exit will be done
somewhere in the middle of the loop (except for intentionally
never-ending loops).
 
> .
> .
> } // end of while loop
 
"Continue" here is daft - it should be "break".
 
 
> In the 2 examples above, the exit_criteria is tested twice for each
> iteration of the while loop. This is considered both inefficient and
> poor programming style.
 
Don't claim that something "is considered" unless you can back it up
with clear justifications. Provide references from the Google C++ style
guide, or MISRA, or quotations from one of the C++ "greats". If you
cannot, then be honest and write "I consider it...".
 
And I don't think you can really claim it is inefficient, if the test
condition does not require external calls - the compiler will probably
be able to optimise that "continue" into a single jump to outside the
loop, just like a "break".
 
 
> The following example is also considered poor programming style
> because you should be exiting a loop at the beginning of the loop or at
> the end of the loop, and not in the middle of the loop:
 
Who says? /Why/ do you think that is a good idea?
 
This all comes across as very dogmatic to me. It looks like you want to
avoid exits in the middle of a loop simply because that is a rule that
/you/ were taught.
 
It is fine to say that exits in the middle of a loop are often hard to
follow, and make the flow of the code unclear. That is a /reason/ for
minimising the use of "break" and "continue". Saying they should be
avoided because it is "considered poor programming style" is not a
reason - any more than saying that "friends at Microsoft use break" is a
good reason to use them.
 
> // Another example of poor use of the break statement
 
> while (true) // The same as "while (1)" , but I prefer the former
 
(Side issue - I agree that "while (true)" is the nicest way to write
such loops. I dislike the use of "1" for a boolean, and I think the
alternative "for (;;)" is ugly. But beauty is in the eye of the beholder.)
 
> .
> .
> } // end of while loop
 
Often that is a perfectly good way to structure a loop. When you see
"while (true)" at the start of a loop, you are in no doubt that the exit
condition comes in the middle of the loop somewhere. If you don't know
that it is time to exit until the middle of the loop, then putting a
"break" (or perhaps "return") there seems perfectly reasonable.
 
Another situation where the use of "while (true)" and breaks can make
sense is if the exit criteria is complex. It may be natural to put
these at the beginning or the end of the loop, but it can be clearer to
have multiple statements, with space for comments, rather than jamming
everything into one exit expression. (There are, of course, alternative
restructurings - such as re-factoring the conditions into a function.)
 
So rather than:
 
while (A && B && !C) {
...
}
 
consider:
 
while (true) {
if (!A) break; // Exit if A does not hold
if (!B) break; // Exit if B does not hold
if (C) break; // Exit when C is reached
...
}
 
 
> duplication is preferred over having an unnecessary break statement or
> continue statement in the loop. In other words, in this case it is
> considered the lessor of two evils :)
 
Sometimes code duplication is unavoidable. In such cases, choose to
duplicate the simplest, shortest, clearest code - not the major lines.
Testing "(miles == -1)" is far simpler and "smaller" than "cin >>
miles". Thus it is the test that should be duplicated, /not/ the action
of reading cin.
 
So while I agree that you may need to choose the lesser of two evils, I
think you have got the answer completely wrong in this case.
 
The best structuring here is very simple:
 
while (true) {
cout << "Enter the miles used (-1 to quit): ";
cin >> miles;
if (miles == -1) break;
...
}
 
Then there is /no/ duplication of either the important statements, or
the test.
 
 
 
> }
 
> // When we reach this point, "found" will be true if search_value was
> // found in the array and false otherwise.
 
Baring typos in the code (which are a /really/ bad idea in a post to
students!), that is a perfectly good use of "break".
 
> switch statement. So how would you rewrite the previous example without
> using a break statement, but still be equally efficient? Quite simply
> actually:
 
The world is a big place, and this is an international newsgroup - no
one can guess where "the lower mainland" is.
 
I am always wary of hard and fast rules such as /never/ using break
statements. I need justification - the stronger the rule, the more
justification I need.
 
And efficiency should not be your major concern here - code clarity and
correctness trump efficiency every time. If you are going to have a
rule about code style, ask yourself:
 
Does it make it easier to write correct code?
Does it make it harder to write incorrect code?
Does it make it easier to see that correct code is correct?
Does it make it easier to see that incorrect code is incorrect?
 
For the most part, pick efficient algorithms and let the compiler worry
about the efficiency of the detail in the code. The compiler is not
going to follow your structure of loops and breaks anyway.
 
 
> found = true;
 
> }
 
> }
 
In my book, the complex condition in the for loop makes it poor code -
it is unclear. It is not as bad as using "i = ARRAY_SIZE" to jump to
the end of the loop, but it is still bad. This kind of exercise is a
very artificial problem, and there are no nice answers. They can be
useful while learning, but that does not make them good style in practice.
 
woodbrian77@gmail.com: May 18 11:21AM -0700

On Thursday, May 18, 2017 at 11:20:49 AM UTC-5, bitrex wrote:
 
> Frankly these days if I absolutely had to use a general purpose systems
> language for an "programming concepts" language it would probably be
> something like Rust or Go and not C++.
 
It seems like C++ keeps getting better with time, though.
 
 
Brian
Ebenezer Enterprises
http://webEbenezer.net
bitrex <bitrex@de.lete.earthlink.net>: May 18 05:03PM -0400


> Brian
> Ebenezer Enterprises
> http://webEbenezer.net
 
It's taken me longer to get up to speed with C++1x than say Python for
sure. But compared to what I remember of my brief messing with it years
ago it does feel like an entirely new beast. The time I've spent on it
recently has been a pleasant combination of frustration and amazement. ;-)
Bonita Montero <Bonita.Montero@gmail.com>: May 18 05:24PM +0200

> Fwiw, even if ReadFile returns TRUE, you will get a IO completion.
 
Where is this specified?
"Chris M. Thomasson" <invalid@invalid.invalid>: May 18 10:40AM -0700

On 5/18/2017 8:24 AM, Bonita Montero wrote:
>> Fwiw, even if ReadFile returns TRUE, you will get a IO completion.
 
> Where is this specified?
 
Its hard to find, but read here:
 
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365683(v=vs.85).aspx
 
Right here:
________________________
However, if I/O completion ports are being used with this asynchronous
handle, a completion packet will also be sent even though the I/O
operation completed immediately. In other words, if the application
frees resources after WriteFile returns TRUE with ERROR_SUCCESS in
addition to in the I/O completion port routine, it will have a
double-free error condition. In this example, the recommendation would
be to allow the completion port routine to be solely responsible for all
freeing operations for such resources.
________________________
 
See? If a HANDLE is hooked up to IOCP, a completion _will_ be queued
even if TRUE is returned with ERROR_SUCCESS. This goes for ReadFile as well.
 
Not sure why MSDN makes this so hard to find!
"Chris M. Thomasson" <invalid@invalid.invalid>: May 18 12:51PM -0700

On 5/18/2017 10:40 AM, Chris M. Thomasson wrote:
> even if TRUE is returned with ERROR_SUCCESS. This goes for ReadFile as
> well.
 
> Not sure why MSDN makes this so hard to find!
 
This thread is bringing back many old memories of my time creating
servers on WinNT 4.0. Ah, the good ol' days. Actually, I am working on a
new special HTTP server that uses my experimental fractal encryption as
a "proof of concept". :^)
 
Also, try to use proper attributions on usenet. Thanks.
"Chris M. Thomasson" <invalid@invalid.invalid>: May 18 01:00PM -0700

On 5/4/2017 12:00 PM, Bonita Montero wrote:
> http://bit.ly/2qwJA7w
> So deciding to handle two different cases upon the return-value
> of ReadFile is correct.
 
No, you are wrong. What you wrote is _not_ correct when the HANDLE is
hooked up to IOCP. ReadFile that returns TRUE, wrt GetLastError
returning ERROR_SUCCESS means that GQCS will dequeue a completion.
 
You need to study up on how to use properly use IOCP.
 
I have a lot of experience in the area and can help you out.
alexo <alessandro.volturno@libero.it>: May 18 07:21PM +0200

Il 18/05/2017 15:19, Paavo Helde ha scritto:
>> function in a separate file, it gives those strange linker error
>> messages.
 
> Seems like https://isocpp.org/wiki/faq/templates#templates-defn-vs-decl
 
Ok now I can relax my brain...it's not a thing that happens to me only.
And it is not a conceptual error projecting the class.
 
In the FAQ there is written that this behaviour is "intended" right so
in the standard. I think this way they made things more complex, rather
than simplifying them.
After all if I write a big project with dozens or more source files
expose the code to the user of the class is the oppostite to the concept
of implementation hiding.
 
Anyway the GURUs made their decisions.
 
Thank you for having the patience to read my shizophrenic posts.
 
bye
Paavo Helde <myfirstname@osa.pri.ee>: May 18 09:25PM +0300

On 18.05.2017 20:21, alexo wrote:
> expose the code to the user of the class is the oppostite to the concept
> of implementation hiding.
 
> Anyway the GURUs made their decisions.
 
They were not happy about that; that's why they added the untested
"export templates" feature into the 1998 standard which was supposed to
solve such issues. Alas, this proved too hard to implement and even if
implemented it did not provide better compilation speeds (as was hoped),
so template export was scraped out from the 2011 standard.
 
Implementation hiding is actually pretty simple with templates: just put
the template method definitions in a separate file MyClass.tpp or
something, write in the beginning of file
 
// Implementation details, (c) alexo 2017
 
and #include it in the end of your MyClass.h file. The ultimate goal of
most users of your class is to know as little about it as possible, so
they will happily skip everything marked "implementation details".
ram@zedat.fu-berlin.de (Stefan Ram): May 18 02:34PM

>>that should be done on every entry to or exit of a block.
>If one's methods are so bloated that one can't pretty much immediately
>see where the exit points are then they need to go on a diet...
 
I agree that methods should be small. This I also tell my
participants.
 
As an example, here's the latest version of my eight-queens
program. It also features loops containing return statements,
which must be something the OP also should dislike. (For a
top-down reading, one should start at »main«, which is at
the bottom of the program.)
 
main.cpp
 
#include <algorithm>
#include <array>
#include <cassert>
#include <iostream>
#include <ostream>
#include <string>
#include <vector>
 
using position_type = int;
 
using direction_type = int;
 
static ::std::array< direction_type, 8 >directions{ 0, 1, 2, 3, 4, 5, 6, 7 };
static ::std::array< int, 8 >offset_y{ +1, +1, 0, -1, -1, -1, 0, +1 };
static ::std::array< int, 8 >offset_x{ 0, +1, +1, +1, 0, -1, -1, -1 };
 
struct board_type : public ::std::vector< position_type >
{
using ::std::vector< position_type >::vector;
 
board_type(): board_type( 64 ){}
 
int is_occupied( int const y, int const x ) const
{ return this->at( y * 8 + x ); }
 
void set_queen_at( position_type const position )
{ assert( !this->at( position ));
this->at( position )= 1; }
 
void remove_queen_at( position_type const position )
{ assert( this->at( position ));
this->at( position )= 0; }
 
bool is_in_board( int const position ) const
{ return( unsigned )position < 64u; }
 
bool is_in_board( int const y, int const x ) const
{ return( unsigned )y < 8u &&( unsigned )x < 8u; }
 
bool out_of_board( int const y, int const x ) const
{ return !is_in_board( y, x ); }
 
bool there_is_a_conflict_at_in_direction
( int pos_y, int pos_x, int const dy, int const dx ) const
{ for( int distance = 0;; ++distance )
{ pos_y += dy; pos_x += dx;
if( out_of_board( pos_y, pos_x ))return false;
if( is_occupied( pos_y, pos_x ))return true; }}
 
bool there_is_a_conflict_at_in_direction
( int const position_y, int const position_x,
direction_type const direction ) const
{ return there_is_a_conflict_at_in_direction
( position_y, position_x,
offset_y.at( direction ), offset_x.at( direction )); }
 
bool there_is_a_conflict_with_other_position_at
( int const position_y, int const position_x ) const
{ for( direction_type const direction : directions )
if( there_is_a_conflict_at_in_direction( position_y, position_x, direction ))return true;
return false; }
 
bool there_is_a_conflict_with_other_position_at( position_type const position ) const
{ return there_is_a_conflict_with_other_position_at( position / 8, position % 8 ); }
 
bool there_is_a_conflict_with_this_position_at( position_type const position ) const
{ return this->at( position ); }
 
bool there_is_a_conflict_at( position_type const position ) const
{ assert( is_in_board( position ));
if( there_is_a_conflict_with_this_position_at( position ))return true;
return there_is_a_conflict_with_other_position_at( position ); }
 
bool there_is_no_conflict_at( position_type const position ) const
{ return !there_is_a_conflict_at( position ); }
 
void print_cell_at( int const row, int const col ) const
{ ::std::cout <<( is_occupied( row, col )? 'W' : ':' ); }
 
void print_end_of_line() const
{ ::std::cout << '\n'; }
 
void print_all_cells_of( int const row ) const
{ for( int col = 0; col < 8; ++col )print_cell_at( row, col );
print_end_of_line(); }
 
void print_all_rows() const
{ for( int row = 8; row > 0; ){ --row; print_all_cells_of( row ); }}
 
void print() const
{ print_all_rows(); }};
 
static void print_board_number()
{ static int n = 0; ::std::cout << n++ << '\n'; }
 
static void print_end_of_line()
{ ::std::cout << '\n'; }
 
static void print( board_type const & board )
{ print_board_number(); board.print(); print_end_of_line(); }
 
struct place_eight_queens
{
 
int number_of_current_queen {};
board_type board;
 
void print_solution_or_set_next_queen_at( position_type const position )
{ if( 7 == number_of_current_queen )print( board ); else
{ position_type const first_position_of_next_row =
( static_cast< int >( position )/ 8 + 1 )* 8;
place_next_queen_starting_at( first_position_of_next_row ); }}
 
void place_queen_at( position_type const position )
{ board.set_queen_at( position );
print_solution_or_set_next_queen_at( position );
board.remove_queen_at( position ); }
 
void place_queen_if_no_conflict_at( position_type const position )
{ if( board.there_is_no_conflict_at( position ))
place_queen_at( position ); }
 
void try_all_positions_starting_at( int const starting_position )
{ for( position_type position = starting_position; position < board.size(); ++position )
place_queen_if_no_conflict_at( position ); }
 
void place_next_queen_starting_at( int const starting_position )
{ ++number_of_current_queen;
try_all_positions_starting_at( starting_position );
number_of_current_queen--; }
 
void place_queens()
{ number_of_current_queen = -1;
int const starting_position = 0;
place_next_queen_starting_at( starting_position ); }
 
void run()
{ place_queens(); }};
 
int main() { ::place_eight_queens{}.run(); }
 
transcript
 
0
 
:::W::::
:W::::::
::::::W:
::W:::::
:::::W::
:::::::W
::::W:::
W:::::::
 
...
ram@zedat.fu-berlin.de (Stefan Ram): May 18 11:36AM

>my students that they should minimize the use of the break
 
In your whole post I have searched for a /rationale/
(reason) for the above. I only found this so far:
 
>In the 2 examples above, the exit_criteria is tested twice
>for each iteration of the while loop. This is considered
>both inefficient and poor programming style.
 
This rationale is founded on DRY (don't repeat yourself,
"tested twice"). Ok, we all agree on DRY.
 
>style because you should be exiting a loop at the beginning
>of the loop or at the end of the loop, and not in the middle
>of the loop:
 
I do not deem this a rationale because it is only founded on
»because you should ...«, but then another rule is given
which itself does not have a rationale.
 
>duplication, in this case, this code duplication is preferred
>over having an unnecessary break statement or continue
>statement in the loop.
 
Either code duplication is a major evil, than it can be used
as a rationale for the avoidance of »break«, but then it
also will dictate to avoid the »break«-less code given later.
 
Or code duplication is acceptable, in which case your
»break«-less code duplication is ok, but it now also is
no rationale for the avoiding of break.
 
And it still is to be disputed whether it is true at
all that break will necessarily lead to code duplication or
whether this is only the property of a constructed example.
 
So far you have not given me a convincing rationale for the
avoidance of »break«. Students find it hard to follow
guidelines for which no convincing reasons are given.
Jerry Stuckle <jstucklex@attglobal.net>: May 17 10:35PM -0400

On 5/17/2017 1:53 PM, Gareth Owen wrote:
 
>> Christian
 
> From the NOAA, not NASA or github. Not in assembly, either.
> http://www.nco.ncep.noaa.gov/pmb/codes/nwprod/
 
Ok, so now let's see you compile and run the code successfully. You
will find this is not the complete code for the models.
 
--
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================
Jerry Stuckle <jstucklex@attglobal.net>: May 17 10:33PM -0400

On 5/17/2017 12:42 PM, Gareth Owen wrote:
 
> Yup. The cost of speeding up the code with assembler (time, money, like
> of portability) are far greater than just throwing a bunch more
> processors at them
 
Except that doubling the number of processors does NOT halve the time it
takes to compute. Some computations cannot be started until previous
computers have been completed. That is the case in most weather
prediction algorithms.
 
 
--
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: May 18 07:30AM -0700

On Thursday, May 18, 2017 at 10:18:22 AM UTC-4, qak wrote:
> if(AMD) do REP RET
> else do RET
> then after the first run all the first lines disappear from every PROC
 
Compilers do not do this today because SMC is generally regarded as
one of the biggest performance killers due to pipeline refills, but
if it is done properly as a first-pass operation, or as another form
of dynamic linking applied by compiler as a run-time application of
the various options it found for maximal optimization, to be included
in the app's startup code, then it is merely the compiler itself
directing the maximum operation based on run-time observations,
rather than static compile-time observations.
 
The compiler could determine there are 50 different models which could
exist, and based on which machine they're running on, which OS version,
how much memory is installed, how much memory is available, etc., give
options and choices for maximum performance.
 
By encoding those in the startup code, and then dynamically linking it
all together at runtime based on a runtime test of the operating
environment, the compiler could finish its work of producing the most
optimized version possible for the runtime machine. It would not
merely enable flags which traverse the code differently, but literally
re-arrange the code so that the footprint of the dynamically linked
version in memory only includes those things which are needed for this
instance.
 
And by adding dynamic runtime analysis of what functions are called
most often, they could be rearranged to have a minimal impact on the
cache by moving the most frequently called functions into a common
area that would persist in the L1 cache longer because of its frequent
use.
 
A lot of options become possible when you look at a compiler as more
than just an intermediate translator between source code and object
code. When you recognize that the job isn't done until the code is
running in a real runtime environment, then you just need to produce
mechanical features which go along with the code at various stages,
able to act upon it and produce the best option for the environment
at hand.
 
Note also that I am considering these features mostly for larger
machines, including modern mobile devices and traditional PCs and
laptops / notebooks. I cannot see it being a usable feature in
the embedded environments, except for where the embedded CPUs are
now getting into more and more capable machines, with extra memory
where such factors would make a difference.
 
I can see this type of optimization being most desirable in server
farms, and on widely distributed applications in something like a
supercomputer center, where the goal is maximum app performance,
minimal machine use, and maximum throughput of jobs.
 
Thank you,
Rick C. Hodgin
David Brown <david.brown@hesbynett.no>: May 18 04:59PM +0200

On 18/05/17 16:18, qak wrote:
>> even be loaded off the disk when you run a program.
 
> Can individual instruction be 'hot', or only the whole block of code can
> be cached ?
 
Caches work on a line at a time - typically something like 16 to 64
bytes long. Details will vary from processor to processor, and can be
different for different cache levels.
 
> if(AMD) do REP RET
> else do RET
> then after the first run all the first lines disappear from every PROC
 
What difference do you think this would make? "rep ret" is executed
exactly like "ret" on all processors, while avoiding a performance bug
in early AMD x86-64 processors. Since the instruction is typically at
the end of a function, and typically followed by padding to the next 16
byte boundary, it has only a one in sixteen chance of wasting a byte of
code space. i.e., the cost is negligible, and far smaller than keeping
a list of addresses for function returns that need patched.
 
A compiler such as gcc may use "rep ret" if compiling for a target that
includes these old devices. If you use switches such as "-mtune" or
"-march" to give a newer minimum required processor (AMD or Intel), it
will generate "ret".
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: