- why use static_cast ? - 6 Updates
- Michael Sipser of MIT validates the notion of a simulating halt decider (Ben's support) - 2 Updates
- I was wrong about gcc's inlining behavior - 5 Updates
- bool is<T>(V v) attempts - 2 Updates
| Manfred <noname@add.invalid>: Oct 21 05:52AM +0200 On 10/20/2022 8:21 PM, Lynn McGuire wrote: > was 13 or 14. > His actual comment was that static_cast's are easier to grep which I > find hard to believe. If by grep you mean grep(1), then yes, static_cast is definitely easier to grep than a C-style cast. However, the advantage of reinterpret_cast (static_cast wouldn't work) is not that it is more readable. It is that it hurts the eye. Depending on which compiler you use, I'd verify that what you intend to do actually works. As far as the standard is concerned, at least one necessary condition is that fem::str<8> is effectively an unsigned char[8]. Otherwise it's UB unless your compiler says otherwise (although it probably Just Works on any of them, in practice.) |
| Bonita Montero <Bonita.Montero@gmail.com>: Oct 21 05:21PM +0200 Am 20.10.2022 um 17:32 schrieb JiiPee: > sure, although about 99.9% in cases the speed is not an issue in these > object oriented programs. But sure, if speed is in essence, one should > consider not using it. That's nonsense. OOP doesn't cost more than procedural programming since with the latter you have context like this also. Virtual functions have some slight overhead but it is very small. |
| Bonita Montero <Bonita.Montero@gmail.com>: Oct 21 05:24PM +0200 Am 20.10.2022 um 16:55 schrieb JiiPee: >> that static_cast<fem::str<8>*> is more "readable". Heh. > its surely not more readable. > but dynamic_cast is surely useful checking class hierarkies. A virtual function that gives some type-capabiliy information is usually much faster. |
| Lynn McGuire <lynnmcguire5@gmail.com>: Oct 21 01:59PM -0500 On 10/20/2022 10:52 PM, Manfred wrote: > probably Just Works on any of them, in practice.) >> Thanks, >> Lynn I am using Visual Studio 2015 on Windows 10 Pro x64. fem::str<8> is an array of unsigned char [8] that I pass around the place to hold a Fortran string of given length that is blank filled rather than null terminated. https://cci.lbl.gov/fable/sources/fable/fem/str.hpp And yes, I will be able to tell rather quickly if the cast is working properly or not. I am minimizing usage though as I prefer char * and std::string. Thanks, Lynn |
| Lynn McGuire <lynnmcguire5@gmail.com>: Oct 21 02:05PM -0500 On 10/20/2022 12:14 PM, JiiPee wrote: > of cases against not using it. Talking about the slowness of static cast > here. But of course I would not put a static cast in a tight loop > looping millions of things a second. I am always concerned about speed. My calculation engine needs to have responses in seconds if needful for large online rotating equipment up to 55,000 hp in size. My other case is the endless recycle calculations of refinery or large natural gas plants that can go 20 or 30 minute on a modern 4 Ghz cpu. When we finish our C++ port then we will be looking at selected speedups using limited parallelization and memset. Lynn |
| JiiPee <kerrttuPoistaTama11@gmail.com>: Oct 22 12:09AM +0300 On 21/10/2022 22:05, Lynn McGuire wrote: >> static cast here. But of course I would not put a static cast in a >> tight loop looping millions of things a second. > I am always concerned about speed. IN my coding, also professional, very rarely this kind of thing would slow down essentially. I have very rarely time critical situations. |
| olcott <none-ya@beez-waxes.com>: Oct 20 10:17PM -0500 On 10/17/2022 10:23 AM, Ben Bacarisse wrote: > because..." was one way he used to put it before finding a more tricky > wording. For years, the project has simply been to find words he can > dupe people with. I will keep posting this every day reminding people that Ben has agreed that Sipser_H does correctly compute the halt status of Sipser_D according to this criteria: *Professor Sipser has agreed to these verbatim words* (and no more) If simulating halt decider *H correctly simulates its input D until H* *correctly determines that its simulated D would never stop running* *unless aborted* then H can abort its simulation of D and correctly report that D specifies a non-halting sequence of configurations. until someone like Andre gives me an accurate review of this paper. *Simulating Halt Decider Applied to the Halting Theorem* https://www.researchgate.net/publication/364302709_Simulating_Halt_Decider_Applied_to_the_Halting_Theorem -- Copyright 2022 Pete Olcott "Talent hits a target no one else can hit; Genius hits a target no one else can see." Arthur Schopenhauer |
| olcott <polcott2@gmail.com>: Oct 21 03:03PM -0500 On 10/17/2022 10:23 AM, Ben Bacarisse wrote: > one no one cares about. D(D) halts (so H is not halt decider), but D(D) > would not halt unless H stops the simulation. H /can/ correctly > determine this silly criterion (in this one case) so H is a POOH decider Ben has agreed that Sipser_H does correctly compute the halt status of Sipser_D according to this criteria: *Professor Sipser has agreed to these verbatim words* (and no more) If simulating halt decider *H correctly simulates its input D until H* *correctly determines that its simulated D would never stop running* *unless aborted* then H can abort its simulation of D and correctly report that D specifies a non-halting sequence of configurations. *Simulating Halt Decider Applied to the Halting Theorem* https://www.researchgate.net/publication/364302709_Simulating_Halt_Decider_Applied_to_the_Halting_Theorem >> The correct simulation is the correct simulation who ever does it, and >> since D will halt when run, the correct simulation of D will halt. > Right, but that's not the criterion that PO is using, is it? I don't Ben agrees that Richard is evaluating my work using the wrong criteria. *This is the criteria that I am using* *Professor Sipser has agreed to these verbatim words* (and no more) If simulating halt decider *H correctly simulates its input D until H* *correctly determines that its simulated D would never stop running* *unless aborted* then H can abort its simulation of D and correctly report that D specifies a non-halting sequence of configurations. > because..." was one way he used to put it before finding a more tricky > wording. For years, the project has simply been to find words he can > dupe people with. Professor Sipser knows these things much deeper than my learned-by-rote from a textbook reviewers. -- Copyright 2022 Pete Olcott "Talent hits a target no one else can hit; Genius hits a target no one else can see." Arthur Schopenhauer |
| Juha Nieminen <nospam@thanks.invalid>: Oct 21 11:44AM (I don't know if this applies to other compilers like clang. Could be.) For the longest time I thought that if gcc sees a function implementation at the place where the function is being called, then it doesn't matter if the keyword 'inline' appears before that function implementation or not. I thought that gcc just ignores that keyword when making inlining decisions. (After all, why wouldn't it?) Just now, however, I got a concrete counter-example to this. I had a number-crunching class declared and implemented locally in a a source file (ie. inside a nameless namespace). While I separated the class definition from the function implementations, I didn't use any 'inline' keywords. After a while, when the class grew a bit too large, I decided to move its function implementations to another source file and, thus, make the class global (well, inside a namespace, but still global). I figured that this wouldn't affect its speed because all the number-cruching happened inside the class, with its function calling other functions of the same class. To my puzzlement, the class became almost twice as slow. To my logic it shouldn't have, because all the function implementations were visible where they needed to be as fast as possible. After wondering about it for a while I decided to try to add the 'inline' keyword in front of all the function implementations (except the couple that were called from the outside). And what do you know, the class became as fast as before. So it appears that I have been wrong: When it comes to functions visible at the global scope, the 'inline' keyword can make a huge difference, even when the implementations are seen by the compiler at the call places. It appears that gcc uses a different inlining strategy when dealing with local and global functions (that have no 'inline' keyword). |
| Michael S <already5chosen@yahoo.com>: Oct 21 07:01AM -0700 On Friday, October 21, 2022 at 2:44:59 PM UTC+3, Juha Nieminen wrote: > places. > It appears that gcc uses a different inlining strategy when dealing > with local and global functions (that have no 'inline' keyword). Did you compare which functions were inlined before and after the change? Is it possible that the function(s) that made the difference for performance are called once? Assuming -O2, the 'static' function (static in C sense rather in C++ sense) will be inlined even when it does not pass other heuristics, most importantly the size heuristics. I recommend to read this section of the manual: https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Optimize-Options.html#Optimize-Options It would not make things clear, because the matter is *not* simple, but hopefully it will give you better look. In particular, read about -finline-functions-called-once and -finline-limit. If your program is not big or release builds are not frequent, you can try -flto. It reduces difference between local and global things. |
| Bo Persson <bo@bo-persson.se>: Oct 21 04:41PM +0200 On 2022-10-21 at 13:44, Juha Nieminen wrote: > at the global scope, the 'inline' keyword can make a huge difference, > even when the implementations are seen by the compiler at the call > places. It probably doesn't make a huge difference in general, but if your function is 'close' to getting inlined, an actual 'inline' keyword might add a few points to the heuristics, and tip it over the decision point. |
| Andrey Tarasevich <andreytarasevich@hotmail.com>: Oct 21 08:47AM -0700 On 10/21/2022 4:44 AM, Juha Nieminen wrote: > if the keyword 'inline' appears before that function implementation or > not. I thought that gcc just ignores that keyword when making inlining > decisions. (After all, why wouldn't it?) GCC's behavior in this regard is difficult to predict and it seems to be rather fluid. I can easily provide an example for you in which GCC will honor `inline` keyword when making decisions about inlining a call #include <iostream> void hello() { std::cout << "Hello World" << std::endl; } int main() { hello(); } GCC refuses to inline the `hello()` call even in -O3 mode. But if you add the `inline` keyword to the declaration of `hello()`, the call will be inlined starting from -O1. However, make two calls to `hello()` from `main()` int main() { hello(); hello(); } and the calls will not be inlined even if you slap `static inline` onto `hello()`. -- Best regards, Andrey. |
| scott@slp53.sl.home (Scott Lurndal): Oct 21 04:04PM > } >and the calls will not be inlined even if you slap `static inline` onto >`hello()`. That's because of the awful iostream crap. This version inlines both calls: $ cat /tmp/c.cpp #include <stdio.h> inline void hello() { printf("Hello World\n"); } int main() { hello(); hello(); } 0000000000400500 <main>: 400500: 48 83 ec 08 sub $0x8,%rsp 400504: bf a0 06 40 00 mov $0x4006a0,%edi 400509: e8 d2 ff ff ff callq 4004e0 <puts@plt> 40050e: bf a0 06 40 00 mov $0x4006a0,%edi 400513: e8 c8 ff ff ff callq 4004e0 <puts@plt> 400518: 31 c0 xor %eax,%eax 40051a: 48 83 c4 08 add $0x8,%rsp 40051e: c3 retq 40051f: 90 nop As opposed to the iostream version, which it doesn't make sense to inline. 0000000000400990 <hello()>: 400990: 53 push %rbx 400991: ba 0b 00 00 00 mov $0xb,%edx 400996: be 90 0a 40 00 mov $0x400a90,%esi 40099b: bf 80 10 60 00 mov $0x601080,%edi 4009a0: e8 7b fe ff ff callq 400820 <std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)@plt> 4009a5: 48 8b 05 d4 06 20 00 mov 0x2006d4(%rip),%rax # 601080 <std::cout@@GLIBCXX_3.4> 4009ac: 48 8b 40 e8 mov -0x18(%rax),%rax 4009b0: 48 8b 98 70 11 60 00 mov 0x601170(%rax),%rbx 4009b7: 48 85 db test %rbx,%rbx 4009ba: 74 3c je 4009f8 <hello()+0x68> 4009bc: 80 7b 38 00 cmpb $0x0,0x38(%rbx) 4009c0: 74 1e je 4009e0 <hello()+0x50> 4009c2: 0f b6 43 43 movzbl 0x43(%rbx),%eax 4009c6: bf 80 10 60 00 mov $0x601080,%edi 4009cb: 0f be f0 movsbl %al,%esi 4009ce: e8 6d fe ff ff callq 400840 <std::ostream::put(char)@plt> 4009d3: 5b pop %rbx 4009d4: 48 89 c7 mov %rax,%rdi 4009d7: e9 54 fe ff ff jmpq 400830 <std::ostream::flush()@plt> 4009dc: 0f 1f 40 00 nopl 0x0(%rax) 4009e0: 48 89 df mov %rbx,%rdi 4009e3: e8 e8 fd ff ff callq 4007d0 <std::ctype<char>::_M_widen_init() const@plt> 4009e8: 48 8b 03 mov (%rbx),%rax 4009eb: be 0a 00 00 00 mov $0xa,%esi 4009f0: 48 89 df mov %rbx,%rdi 4009f3: ff 50 30 callq *0x30(%rax) 4009f6: eb ce jmp 4009c6 <hello()+0x36> 4009f8: e8 b3 fd ff ff callq 4007b0 <std::__throw_bad_cast()@plt> 4009fd: 0f 1f 00 nopl (%rax) |
| Aaron Gray <aaronngray@gmail.com>: Oct 20 11:35PM -0700 I have been trying to get an is() and as() functions working and as theres no dynamic is_subclass in C++ I have resulted in going back to relying on dynamic_cast !!! I cannot seem to get inbuilt ints to work though. #include <iostream> #include <type_traits> template <typename T> std::string typeof() { in return typeid(T).name(); } template <typename T> std::string typeof(T t) { return typeid(t).name(); } template <typename T, typename V> bool is(V* t) { try { return dynamic_cast<T*>(t) != nullptr; } catch (std::bad_cast) { return false; } } template <typename T, typename V> bool is(V& t) { try { dynamic_cast<T&>(t); return true; } catch (std::bad_cast) { return false; } } template <> // FAILING ! bool is<int&>(int t) { return true; } template <typename T, typename V> T& as(V t) { return *dynamic_cast<T*>(&t); } template <typename T, typename V> T* as(V* t) { return dynamic_cast<T*>(t); } class Z { public: virtual void f() {}; }; class X : public Z { public: virtual void f() {}; }; class Y : public X { public: virtual void f() {}; }; class U { public: virtual void f() {}; }; class V : public U { virtual void f() {}; }; int main() { int i = 4; int& i2 = i; X x; Y y; V v; X* x2 = &y; X& x3 = y; std::cout << typeof<X>() << std::endl; std::cout << typeof<X>() << std::endl; std::cout << typeof(x) << std::endl; std::cout << typeof(y) << std::endl; // std::cout << typeof<int&>() << std::endl; // needs intergral type template specialization case // std::cout << typeof(i2) << std::endl; std::cout << is<X>(x) << std::endl; std::cout << is<X>(y) << std::endl; std::cout << is<int&>(i) << std::endl; //fail std::cout << is<int&>(i2) << std::endl; // fail std::cout << is<Y>(x) << std::endl; std::cout << is<X>(v) << std::endl; std::cout << is<Y>(x2) << std::endl; std::cout << is<Y>(x3) << std::endl; // reference upcasts pass ! //std::cout << typeid(X). << std::endl; } |
| Andrey Tarasevich <andreytarasevich@hotmail.com>: Oct 21 01:45AM -0700 On 10/20/2022 11:35 PM, Aaron Gray wrote: > bool is<int&>(int t) { > return true; > } You are using a template specialization syntax, but your specialization does not match any of the previously declared "main" templates. So far you declared two "main" templates: one that takes a pointer and one that takes a reference. The specialization takes an `int`, which does not match any of the "main" templates. This will work template <typename T> bool is(int t){ return false; } template <> bool is<int&>(int t) { return true; } Whether it is the best way to go about implementing your intent is a different question... -- Best regards, Andrey. |
| 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