- Use of the break; and continue; statments - 13 Updates
- peformance of wait notify concept of condition variable - 4 Updates
- linker error - 2 Updates
- Use of the break; and continue; statments - 2 Updates
- "Need for Speed - C++ versus Assembly Language" - 2 Updates
- compiler generate jmp to another jmp - 2 Updates
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:
Post a Comment