- Some kind of unwanted optimization going on here ??? And if so, how do I prevent it ??? - 15 Updates
- Start constexpr N threads at runtime - 3 Updates
- Technical paper in 6 languages (including code comments) - 1 Update
- Refraining from embracing - 5 Updates
- Structured binding considered harmful - 1 Update
"Öö Tiib" <ootiib@hot.ee>: Mar 25 04:27PM -0700 On Thursday, 26 March 2020 01:20:49 UTC+2, Mike Terry wrote: > volatile unsigned long long int result1 = fibonacci( 47 ); > volatile time_t endTime1 = time(nullptr); > which seems to work on my system. Yes but OP's problem sounded like reordering I/O and time() call: unsigned long long int result1 = fibonacci( 47 ); cout << "fibonacci( 47 ) = " << result1 << endl; // <- I/O (1) time_t endTime1 = time(nullptr); // <- time() call (2) |
Mike Terry <news.dead.person.stones@darjeeling.plus.com>: Mar 25 11:33PM On 25/03/2020 23:13, Öö Tiib wrote: > something volatile or doing input from somewhere so perhaps MS > optimizer has screwed up tracking of what of its API has side > effects. I'm just a regular C++ user, and don't understand the relevent standards as well as others here! It would seem to me that calling time() probably IS deemed as having side effects by the VC compiler, but this in itself would only prevent the re-ordering of the calls to time(). I guess the compiler sees that fibonacci() has no side effects, and so it's free to re-order it with respect to the time() calls. (?) As a test for OP, deliberately introducing a side effect into fibonacci() might solve the problem. Mike. |
"Öö Tiib" <ootiib@hot.ee>: Mar 25 04:49PM -0700 On Thursday, 26 March 2020 01:34:05 UTC+2, Mike Terry wrote: > fibonacci() has no side effects, and so it's free to re-order it with > respect to the time() calls. (?) As a test for OP, deliberately > introducing a side effect into fibonacci() might solve the problem. Yes but in OP's code result of fibonzzi() was used in output before calling time() and that must be as good as assigning to volatile. unsigned long long int result1 = fibonacci( 47 ); cout << "fibonacci( 47 ) = " << result1 << endl; time_t endTime1 = time(nullptr); |
Mike Terry <news.dead.person.stones@darjeeling.plus.com>: Mar 26 12:00AM On 25/03/2020 23:27, Öö Tiib wrote: > unsigned long long int result1 = fibonacci( 47 ); > cout << "fibonacci( 47 ) = " << result1 << endl; // <- I/O (1) > time_t endTime1 = time(nullptr); // <- time() call (2) Hmm, this would be consistent with the compiler recognising the time() calls and cout<< calls as both having side effects (or involving I/O), but not the fibonacci() call, thus allowing it (supposedly) to move the fibonacci() call to after the time() call. Here is the OP's code which gives the unexpected result: (I've prefixed lines with side effects or I/O with # ) ///// Actual code (unexpected result) # cout << "Calculating fibonacci( 47 )" << endl; # time_t startTime1 = time( nullptr ); unsigned long long int result1 = fibonacci( 47 ); # time_t endTime1 = time(nullptr); # cout << "fibonacci( 47 ) = " << result1 << endl; ..and here is the "optimised" result: (obvious why zero seconds are recorded) ///// Compiler reordere code # cout << "Calculating fibonacci( 47 )" << endl; # time_t startTime1 = time( nullptr ); # time_t endTime1 = time(nullptr); unsigned long long int result1 = fibonacci( 47 ); # cout << "fibonacci( 47 ) = " << result1 << endl; The OP's code which worked as expected is as like this: ///// Actual code (giving expected result) # cout << "Calculating fibonacci( 47 )" << endl; # time_t startTime1 = time( nullptr ); unsigned long long int result1 = fibonacci( 47 ); # cout << "fibonacci( 47 ) = " << result1 << endl; # time_t endTime1 = time(nullptr); Here, the second time() call can't be reordered before the fibonacci() call because: 1) it must occur after the second cout<< call 2) the second cout<< call must occur after the fibonacci() call, as it uses the result1 variable. Well, we could say that still the compiler could have moved the fibonacci() call to before the first time() call, rather than after the second time() call. True - but who knows why it chooses which way to optimise? (I mean, it's not deliberately trying to thwart the programmer!) Mike. |
Mike Terry <news.dead.person.stones@darjeeling.plus.com>: Mar 26 12:09AM On 25/03/2020 23:49, Öö Tiib wrote: > unsigned long long int result1 = fibonacci( 47 ); > cout << "fibonacci( 47 ) = " << result1 << endl; > time_t endTime1 = time(nullptr); ..and this code worked as expected. I doubt that simply using a variable for output /at a later point of execution/ is considered equivalent to marking the variable as volatile /from its creation/. (But now I'm guessing...) Mike. |
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Mar 26 12:17AM On Wed, 25 Mar 2020 16:49:24 -0700 (PDT) Öö Tiib <ootiib@hot.ee> wrote: [snip] > unsigned long long int result1 = fibonacci( 47 ); > cout << "fibonacci( 47 ) = " << result1 << endl; > time_t endTime1 = time(nullptr); §4.6/7 of C++17 says The least requirements on a conforming implementation are: * Accesses through volatile glvalues are evaluated strictly according to the rules of the abstract machine. * At program termination, all data written into files shall be identical to one of the possible results that execution of the program according to the abstract semantics would have produced. * The input and output dynamics of interactive devices shall take place in such a fashion that prompting output is actually delivered before a program waits for input. What constitutes an interactive device is implementation-defined. These collectively are referred to as the observable behavior of the program. I cannot say I fully understand the consequences, but it seems reasonably clear that printing the correct value of the 47th (and 46th) fibonacci to stdout has a computational consequence and must be correct (within available resource limits), but printing the time at and during which the program happens to be executed does not, in the sense that no particular value of time is predicated by the program as written. So maybe the optimization is permitted. Dunno. |
"Öö Tiib" <ootiib@hot.ee>: Mar 25 05:29PM -0700 On Thursday, 26 March 2020 02:00:37 UTC+2, Mike Terry wrote: > unsigned long long int result1 = fibonacci( 47 ); > # time_t endTime1 = time(nullptr); > # cout << "fibonacci( 47 ) = " << result1 << endl; Nope, for third time OP's code was verbatim: cout << "fibonacci( 47 ) = " << result1 << endl; time_t endTime1 = time(nullptr); // SEE THIS STATEMENT You have yourself reordered. |
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Mar 26 12:43AM On Thu, 26 Mar 2020 00:17:22 +0000 > sense that no particular value of time is predicated by the program as > written. > So maybe the optimization is permitted. Dunno. And if so, as another poster has observed, making the time values volatile should deal with the OP's issue. |
Mike Terry <news.dead.person.stones@darjeeling.plus.com>: Mar 26 01:24AM On 26/03/2020 00:29, Öö Tiib wrote: > cout << "fibonacci( 47 ) = " << result1 << endl; > time_t endTime1 = time(nullptr); // SEE THIS STATEMENT > You have yourself reordered. You're not reading the OP correctly. Yes, I know what he wrote in the "verbatim" program code. OK, OP starts with the following paragraph explaining what the following code is, and what the unexpected result is: The code below as is works as expected. But if I move the statement ending with the comment "SEE THIS STATEMENT" to before the previous statement, it calculates time as 0.000000000 minutes. Note the phrase "works as expected". This indicates that the "verbatim" code is the code where things run IN THE EXPECTED ORDER. Here is the verbatum code (GIVING EXPECTED RESULT): cout << "Calculating fibonacci( 47 )" << endl; time_t startTime1 = time( nullptr ); unsigned long long int result1 = fibonacci( 47 ); cout << "fibonacci( 47 ) = " << result1 << endl; time_t endTime1 = time(nullptr); // SEE THIS STATEMENT cout << "Calculation time = " << (endTime1 - startTime1 ) / 60.0 << " minutes\n" << endl; Now note the phrase "But if I move the statement.....[unexpected result]" So, the code with the unexpected result has the time() call moved up AS I SHOWED IT. SUMMARY: Yes, I've re-ordered the verbatim code AS INSTRUCTED BY OP TO REPRODUCE THE UNEXPECTED BEHAVIOUR. When explaining the unexpected compiler behaviour there are two code listings to consider: a) the "actual" code given to the compiler b) the "reordered" code as adjusted internally by the compiler The code I quote above is the "actual" compiler input GIVING THE UNEXPECTED RESULT. I follow this (below) by the "compiler reordered" code. The "verbatim" code (which works as expected) I then listed (even further below), along with an explanation for why it doesn't give unexpected results. No need to spend any more time on this, as I've already wasted more than it warrents, and won't respond any further. |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Mar 26 04:36AM +0100 On 25.03.2020 22:01, Bob Langelaan wrote: > return fibonacci( n - 1 ) + fibonacci( n - 2 ); > } // end else > } // end function fibonacci I've reproduced the issue with Visual C++ 2019, using optimization option `/O2`. With the `time` call before the output it reports 0 time even though the code clearly runs for several seconds. I believe that a compiler is permitted to move the call to `time` to before the call to `fibonacci`, since it can prove that the latter doesn't change any state that the `time` function could depend on. The flow of time is not regarded as part of the abstract machine state. Adding `std::atomic_thread_fence(std::memory_order_acq_rel);` around each `fibonacci` call did not prevent this. I don't know if it should. But I felt it was worth trying. Adding `volatile` to the result variables fixed it. However, most uses of `volatile` will be deprecated in C++20; <url: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1152r4.html>. And apparently that includes `volatile` return types. So one cannot, apparently, quick-fix it by making `time` (and `clock`, etc.) produce `volatile` values, if that would work, which I don't know. This reminds me of the C++11 (or was it C++14) /carte blanche/ to completely optimize away a provably infinite loop. A very impractical effect for real programming, stemming from the standard specifying things in terms of a too limited academic ivory tower abstraction. - Alf |
"Öö Tiib" <ootiib@hot.ee>: Mar 25 11:58PM -0700 On Thursday, 26 March 2020 03:24:29 UTC+2, Mike Terry wrote: > I SHOWED IT. > SUMMARY: Yes, I've re-ordered the verbatim code AS INSTRUCTED BY OP TO > REPRODUCE THE UNEXPECTED BEHAVIOUR. OK. Seems that I misunderstood that part. On that case your solution of using volatile is fine. Unless they have done something bad (as they seem to plan) to volatile. |
"Öö Tiib" <ootiib@hot.ee>: Mar 26 01:30AM -0700 On Thursday, 26 March 2020 05:36:57 UTC+2, Alf P. Steinbach wrote: > A very impractical effect for real programming, stemming from the > standard specifying things in terms of a too limited academic ivory > tower abstraction. Precisely! Idea of breaking volatile seems to come from same school as that infinite loop mess. Making low level hardware drivers impossible to write in C++ would result with developers being forced to use low level hardware drivers of hardware vendors and making it impossible for smaller hardware vendors to write their drivers in anything but assembler (that is rare and expensive skill these days). |
David Brown <david.brown@hesbynett.no>: Mar 26 11:32AM +0100 On 26/03/2020 00:13, Öö Tiib wrote: > something volatile or doing input from somewhere so perhaps MS > optimizer has screwed up tracking of what of its API has side > effects. The compiler can't re-order things with side-effects. But calculating fibonacci() does not have any side-effects, and the compiler can re-arrange that with respect to any side-effect code. There is a common misunderstanding that code observable behaviour (or potentially having observable behaviour) also forces an order on other code - it does not. |
David Brown <david.brown@hesbynett.no>: Mar 26 11:40AM +0100 On 26/03/2020 01:17, Chris Vine wrote: > sense that no particular value of time is predicated by the program as > written. > So maybe the optimization is permitted. Dunno. When the code is: unsigned long long int result1 = fibonacci( 47 ); cout << "fibonacci( 47 ) = " << result1 << endl; time_t endTime1 = time(nullptr); the compiler needs to write the output before measuring the time. And in order to write the output, it must calculate the result of the fibonacci. When the code is: unsigned long long int result1 = fibonacci( 47 ); time_t endTime1 = time(nullptr); cout << "fibonacci( 47 ) = " << result1 << endl; the compiler must measure the time before writing out the result. And in order to write the output, it must calculate the result of the fibonacci. But it does /not/ need the result of the fibonacci in order to measure the time. The compiler can see that calling fibonacci(47) cannot possibly have side-effects that are relevant to the call to time(). Therefore it is fine to delay the calculation until the results are needed. Thus this optimisation is perfectly valid. The simple solution here is to use volatile: volatile unsigned long long int result1 = fibonacci( 47 ); time_t endTime1 = time(nullptr); cout << "fibonacci( 47 ) = " << result1 << endl; This forces the compiler to calculate the results and write result1 before getting the time. I'd also recommend the "47" be replaced by a volatile: volatile const unsigned int N = 47; volatile unsigned long long int result1 = fibonacci(N); time_t endTime1 = time(nullptr); cout << "fibonacci( 47 ) = " << result1 << endl; A smart enough compiler could see that fibonacci(47) can be pre-calculated at compile time, and eliminate the run-time calculation entirely. A less smart one might eliminate some of it, but not all. |
David Brown <david.brown@hesbynett.no>: Mar 26 11:58AM +0100 On 26/03/2020 09:30, Öö Tiib wrote: > level hardware drivers of hardware vendors and making it impossible > for smaller hardware vendors to write their drivers in anything but > assembler (that is rare and expensive skill these days). No, you are both misunderstanding this quite significantly. The re-ordering of the calculation in this code is allowed because the calculation of fibonacci(47) has no observable behaviour. Adding a memory fence around it will not force any order, because "result1" is not required to be in memory - though a compiler is certainly free to interpret the fence more generally and use it for ordering result1. Making result1 volatile /will/ force the desired order. Making the return type of functions like "time" volatile is just a silly idea. It makes no sense at all. Think about what volatile means, and it should be obvious. No version of C or C++ has a /carte blanche/ to remove infinite loops. Quoting from C11 (because I have it open at the moment): """ An iteration statement whose controlling expression is not a constant expression, 156) that performs no input/output operations, does not access volatile objects, and performs no synchronization or atomic operations in its body, controlling expression, or (in the case of a for statement) its expression-3, may be assumed by the implementation to terminate. 157) """ In C++, this is part of the "forward progress guarantee", and amounts to the same thing. An infinite loop that does nothing is undefined behaviour - an infinite loop that does something observable is fine. And as for the suggested changes to "volatile", the recommendation is to disallow complicated cases and only allow simple ones. That is /fine/ - the complicated cases should never be used in the first place. So if you have: volatile int a, b, c; then a = 1; b = c; and the like are still allowed. You can have pointers-to-volatile, you can read and write volatile data, you can use pointer casts to make a "use a volatile access here" expressions (which every compiler has allowed, but was not defined behaviour until C18). What you can't do are things like: a = b++ + c++; That's fine. There is no standard for saying how these things should work, and compilers interpret then in very different ways. If your low-level drivers are affected by the new restrictions in volatile, then they /should/ be re-written - even if you are using older C++ standards. |
Melzzzzz <Melzzzzz@zzzzz.com>: Mar 26 08:21AM > I only ever call "join" without checking that it's 'joinable' beforehand (even if I know that the thread entry point function might have returned). > Even if you do check that it's joinable first, it might not be joinable a few microseconds later when you try to join it. > Can't we just simply call "join"? No. joining on detached thread is UB. -- press any key to continue or any other to quit... U ničemu ja ne uživam kao u svom statusu INVALIDA -- Zli Zec Svi smo svedoci - oko 3 godine intenzivne propagande je dovoljno da jedan narod poludi -- Zli Zec Na divljem zapadu i nije bilo tako puno nasilja, upravo zato jer su svi bili naoruzani. -- Mladen Gogala |
"Öö Tiib" <ootiib@hot.ee>: Mar 26 01:37AM -0700 On Thursday, 26 March 2020 10:21:45 UTC+2, Melzzzzz wrote: > > Even if you do check that it's joinable first, it might not be joinable a few microseconds later when you try to join it. > > Can't we just simply call "join"? > No. joining on detached thread is UB. AFAIK it throws on non-joinable thread (not UB) and uncaught exception (is also not UB but) just has often undesirable result. |
Melzzzzz <Melzzzzz@zzzzz.com>: Mar 26 08:39AM >> No. joining on detached thread is UB. > AFAIK it throws on non-joinable thread (not UB) and uncaught exception > (is also not UB but) just has often undesirable result. Well, I use pthreads, I concluded from there ;) -- press any key to continue or any other to quit... U ničemu ja ne uživam kao u svom statusu INVALIDA -- Zli Zec Svi smo svedoci - oko 3 godine intenzivne propagande je dovoljno da jedan narod poludi -- Zli Zec Na divljem zapadu i nije bilo tako puno nasilja, upravo zato jer su svi bili naoruzani. -- Mladen Gogala |
Frederick Gotham <cauldwell.thomas@gmail.com>: Mar 26 12:53AM -0700 Jorgen Grahn wrote: > native language? For the combination C++ / Sweden, I have never seen > it: code is IME always in English, at work and at university. > (But I admit we are fairly extreme in that area.) Christian Gollwitzer wrote: > You probably overthink this. Technical papers are usually published > exclusively in English, especially if they ar ein the field of computer > science (and most other fields, too). Even if 99% of people don't bother having their paper translated into other languages, I shall. Vir Campestris wrote: > I've never known a software engineer who can't read > English with a reasonable level of proficiency. I want beginner programmers and cryptographers to be able to read my paper in a language they understand (instead of running it through Google Translate). And also there might be a proficient programmer, cryptographer or mathematician who isn't good with languages -- I have a friend who's a high school math teacher and he's not good with languages. |
woodbrian77@gmail.com: Mar 25 10:08PM -0700 Shalom Are people rethinking on-line code generation now that the cat is out of the bag with the Wuhan virus? https://github.com/Ebenezer-group/onwards "There is a time for everything, and a season for every activity under the heavens: a time to be born and a time to die, a time to plant and a time to uproot, a time to kill and a time to heal, a time to tear down and a time to build, a time to weep and a time to laugh, a time to mourn and a time to dance, a time to scatter stones and a time to gather them, a time to embrace and a time to refrain from embracing, a time to search and a time to give up, a time to keep and a time to throw away, a time to tear and a time to mend, a time to be silent and a time to speak, a time to love and a time to hate, a time for war and a time for peace." Ecclesiastes 3 And if anyone has suggestions on how to improve my software, please let me know. Thanks in advance. Brian Ebenezer Enterprises - Enjoying programming again. http://webEbenezer.net |
Christian Gollwitzer <auriocus@gmx.de>: Mar 26 07:33AM +0100 > Are people rethinking on-line code generation now > that the cat is out of the bag with the Wuhan virus? No. This incident has no influence on the other thing. It's magical thinking that unconnected events can influence each other. This lead former people to believe in werid things like witchcraft or other supernatural powers. Christian |
Jorgen Grahn <grahn+nntp@snipabacken.se>: Mar 26 06:44AM On Thu, 2020-03-26, Christian Gollwitzer wrote: >> Are people rethinking on-line code generation now >> that the cat is out of the bag with the Wuhan virus? > No. This incident has no influence on the other thing. It would have been different in the 1970s I suppose, when we would have gone to the data central with our stack of punched cards ... /Jorgen -- // Jorgen Grahn <grahn@ Oo o. . . \X/ snipabacken.se> O o . |
"Öö Tiib" <ootiib@hot.ee>: Mar 25 11:46PM -0700 > Shalom > Are people rethinking on-line code generation now > that the cat is out of the bag with the Wuhan virus? No, the off-line code generators of Protocol Buffers, Thrift, Apache Avro, FlatBuffers and others do not help to spread the virus in any way so those won't be banned. |
Ian Collins <ian-news@hotmail.com>: Mar 26 08:33PM +1300 > Shalom > Are people rethinking on-line code generation now > that the cat is out of the bag with the Wuhan virus? It's Covid-19 and no. Twat. -- Ian. |
Sam <sam@email-scan.com>: Mar 25 08:01PM -0400 Chris Vine writes: > "But nobody can offend me without my permission, first. And I do not > give anyone permission to offend me" is nothing more than a > projection. Bullies don't like it when people hit back. If you'd like to complete your compilation of my favorite sayings, just let me know and I'll put together a list. > time ago, in a galaxy far, far away. But not everyone is as smart as > me... I think we're looking at a future Microsoft Windows developer, > here". Well, you got me there, because I can't return the favor: I have absolutely no idea what you said, or wrote, last year. Even last month, come to think of it. Whatever it was, it could not have been memorable enough to have such a profound effect on me that I would still remember it, years later, unlike my proclamations which make such a lasting impact on you, from the looks of it. > When told he was a dickhead he didn't like it at all. His reaction > to having the facts pointed out to him was quite satisfying. Can you refresh my memory as to how exactly you reached your conclusion that I "didn't like it at all"? You are shirley mistaken about it; and for the same exact reasons that I just explained, of course, in painful detail. It is logically impossible for me to have any reaction to being called a dickhead, since this presumes that I would care. A comp.lang.c++ search for "Chris Vine dickhead" finds two posts, the one that you just made, and one from 2017. A search for "Sam dickhead" finds only your, sole, post, from three hours ago. Your other post, from 2017, reads: # And we now also seem to have acquired this Jeff guy who cross-posts # random garbage to this newsgroup in classic troll mode. And we have a # different poster (strangely silent for the last 4 or so weeks) who will # join any argument which he doesn't understand and take it to the point # of absurdity, cannot bear not to have the last word and doesn't mind # projecting himself as a complete dickhead. Was that in referring to me? The fact that I may post occasionally, or in bursts, is nowhere close to being notable. Examining your own posting frequency also finds a fairly similar, in-the-ballpark, posting pattern. Maybe that's because somsone called /you/ a dickhead, perhaps? But, in any case, I'm genuinely curious to find out who called me a dickhead, years ago, an event that must've left a bigger impression on you, than on me, since I can't even remember it. But you do, apparently, so I'm waiting to hear the details. |
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