- Why can't I understand what coroutines are? - 14 Updates
- Why can't I understand what coroutines are? - 1 Update
- 2020 C++ - 2 Updates
- In the end, rason will come - 2 Updates
- [off-topic] Re: Periodic message transfers using asio - 2 Updates
| Sam <sam@email-scan.com>: Aug 05 08:14PM -0400 Scott Lurndal writes: > >> Gee whiz, how can that possibly happen? > >epoll(...), dear. > How does epoll help with high volume disk I/O? Now look what you've done. You confused him with facts. Shame on you. |
| "Chris M. Thomasson" <invalid_chris_thomasson_invalid@invalid.com>: Aug 05 11:43PM -0700 On 8/5/2019 1:42 AM, Juha Nieminen wrote: > Is there a simple example of a situation where this is significantly > beneficial compared to a lambda or an explicitly written functor > (ie. a class with member variables and an operator())? Damn. I thought they were trying to get something like a standard getcontext/setcontext, or fibers. |
| leigh.v.johnston@googlemail.com: Aug 06 04:13AM -0700 On Monday, August 5, 2019 at 6:48:18 PM UTC+1, Scott Lurndal wrote: > >> Gee whiz, how can that possibly happen? > >epoll(...), dear. > How does epoll help with high volume disk I/O? How do threads help with high volume disk I/O, dear? |
| leigh.v.johnston@googlemail.com: Aug 06 04:23AM -0700 > > >epoll(...), dear. > > How does epoll help with high volume disk I/O? > How do threads help with high volume disk I/O, dear? Of course by that I actually meant how does *lots* of threads help with high volume disk I /O, dear? |
| Bonita Montero <Bonita.Montero@gmail.com>: Aug 06 01:58PM +0200 > One way to think about coroutines is like threads, but > cooperatively multitasking instead of preemptive multitasking. It's not really multitasking since the corutine-context can only live as long as the calling function. With cooperative multitasking like with fibers in Windows, a fiber can end without stopping other contexts. |
| David Brown <david.brown@hesbynett.no>: Aug 06 03:06PM +0200 On 05/08/2019 14:20, Juha Nieminen wrote: > In other words, it sounds to me like coroutines are, essentially, > lambda functions, or stateful functor objects, with a jump at the > beginning of the function to the position in the code that last yielded. The explanation here calls them "stackless": <https://en.cppreference.com/w/cpp/language/coroutines> But really, they are only "stackless" in the sense that C++ does not actually need a stack. They have a local state - you can have normal local variables, and a normal call chain of normal functions. This will typically end up on a heap somewhere, but is effectively a local stack for the coroutine execution state. It is entirely possible, given simple enough coroutines and smart enough compilers, for this all to be boiled down to a single allocatable block. |
| David Brown <david.brown@hesbynett.no>: Aug 06 03:18PM +0200 On 06/08/2019 15:06, David Brown wrote: > for the coroutine execution state. It is entirely possible, given > simple enough coroutines and smart enough compilers, for this all to be > boiled down to a single allocatable block. After reading some of Alf's posts in this thread, it looks like I was wrong here and C++ coroutines will be more restricted than general coroutines. If they can only yield from within the coroutine function itself, not arbitrary external functions, then the compiler can figure out the size of the local stack frame needed and generate it as a single block, thus avoiding any variable sized stack. A simple and lightweight version of this has been in use in embedded systems in C for long time. For those that think Duff's device is cool, macros are a joy, and the non-structured nature of "switch" is a great idea, have a look at this: <https://en.wikipedia.org/wiki/Protothread> <http://dunkels.com/adam/pt/> |
| scott@slp53.sl.home (Scott Lurndal): Aug 05 05:48PM >> networking tying hundreds of thousands threads together. Yes, threads. >> Gee whiz, how can that possibly happen? >epoll(...), dear. How does epoll help with high volume disk I/O? |
| Manfred <noname@add.invalid>: Aug 06 04:24PM +0200 Excellent explanation, thanks! On 8/5/2019 1:11 AM, Alf P. Steinbach wrote: |
| "Chris M. Thomasson" <invalid_chris_thomasson_invalid@invalid.com>: Aug 05 02:44PM -0700 On 8/5/2019 2:51 AM, Martijn van Buul wrote: > a threaded solution would offer no parallelisation, so using threads here > only serves to simplify the implementation of the consumer or producer - > performancewise it's detrimental. [...] Actually, single producer, single consumer queues are pretty nice. The consumer thread can work on things without bothering the procuder thread, and vise versa. The sync can be implemented without using any atomic RMW. |
| Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Aug 06 10:19PM +0100 On Tue, 6 Aug 2019 04:23:44 -0700 (PDT) > > How do threads help with high volume disk I/O, dear? > Of course by that I actually meant how does *lots* of threads help with > high volume disk I /O, dear? No, you have fallen victim to a classic misdirection play by Scott. The claim made in response to a posting of mine, originally by someone by the name of "Sam", was that native OS threads on linux (but not windows) can deal equally well with the kind of i/o things that coroutines are good at, and are easier to use. Both these propositions are in my opinion wrong, but it stands as the argument. High volume disk i/o is irrelevant to this issue, because coroutines aren't well suited to high volume disk i/o, nor are poll/select/epoll. Native threads on the other hand are reasonably well suited to this work load because operations on high volume disks tend to be cpu-bound and not i/o-bound. And apart from anything else, block devices representing hard disks are always signalled as ready (at any rate, they are with select and poll, I do not know about epoll, so poll and select are useless with them). The real answer to Scott is "how do coroutines help with high volume disk i/o"? I agree with what seems to be his suggestion - that they don't - so they are irrelevant to your posting about epoll. |
| "Chris M. Thomasson" <invalid_chris_thomasson_invalid@invalid.com>: Aug 06 03:19PM -0700 On 8/6/2019 2:19 PM, Chris Vine wrote: > The real answer to Scott is "how do coroutines help with high volume > disk i/o"? I agree with what seems to be his suggestion - that they > don't - so they are irrelevant to your posting about epoll. AIO should be fine, its POSIX but oh well: http://man7.org/linux/man-pages/man7/aio.7.html https://pubs.opengroup.org/onlinepubs/009695399/basedefs/aio.h.html IOCP can be used with files, even memory mapped ones. |
| "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Aug 07 12:52AM +0200 On 07.08.2019 00:38, Stefan Ram wrote: > A coroutine is a function that contains > either a coroutine-return-statement or > an await-expression or a yield-expression. You mean, "A C++20 coroutine is...". General implementations of coroutines do not have that or corresponding restriction. Even if the restriction is a special case of coroutines, I think it can be argued that "coroutine" is a misnomer for the C++20 thing. :-) Because it implies much that isn't there. --- By the way, I learned a bit more, by looking around at tutorials, and I'm appalled at all the machinery it seems one must define for the return type of even the simplest C++20 coroutine. It's akin to the infamous 600+ line Microsoft OLE technology "Hello, world!"... Hopefully they'll get around to provide some default machinery, before it's accepted in the standard. Cheers!, - Alf |
| Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Aug 07 12:01AM +0100 On Tue, 6 Aug 2019 15:19:48 -0700 "Chris M. Thomasson" <invalid_chris_thomasson_invalid@invalid.com> wrote: [snip] > AIO should be fine, its POSIX but oh well: > http://man7.org/linux/man-pages/man7/aio.7.html > https://pubs.opengroup.org/onlinepubs/009695399/basedefs/aio.h.html Yes as I understand it AIO works for asynchronous i/o with block devices representing hard disks, even though you can't use select/poll and I think epoll for them. But AIO is not my area and I have to say that I can't really understand the point of it with disks: the issue with such block devices is that in polling terms they are always available to read or write in the absence of an error. For reading in particular, you don't do it for the fun of it: you do it to process the data you obtain, which is likely to require use of the CPU. So why not just use threads without AIO? You are not dealing with network latency. I notice incidentally that the documentation for glibc's implementation of AIO says: "This has a number of limitations, most notably that maintaining multiple threads to perform I/O operations is expensive and scales poorly". All the more reason to do that particular work synchronously I would have thought. The alternative seems to be to use signals. Do you have any experience of AIO? (As I say, I don't.) |
| ram@zedat.fu-berlin.de (Stefan Ram): Aug 06 10:38PM >I'll address the conceptual only. Not wanting to contradict anything, just as an extension: A coroutine is a function that contains either a coroutine-return-statement or an await-expression or a yield-expression. |
| Tim Rentsch <tr.17687@z991.linuxsc.com>: Aug 06 09:31AM -0700 Manfred writes: > [C++20 to have "concepts"] > To this point I think that, even if the feature itself is really good, > the name "concept" is just a bad choice. Me too. "Concept" is a terrible choice of name for this construct. > feature). Personally I would have preferred a name more directly > coupled to "requirement" as in fact they are (we already have typedef, > typereq might have been something clearer). The name "constraint" isn't quite right because a C++ "concept" doesn't yet constrain anything; it is more like what might be called a "constraint-in-waiting". The name "requirement" isn't quite right for much the same kinds of reasons: by itself a C++ "concept" doesn't require anything. We might call it a "statement of requirements", if that phrase weren't so cumbersome. Also there are parts of C++ "concepts" that use the keyword 'requires' and might themselves be called "requirements", which is confusing. A name I am starting to warm up to is "property". It fits with lots of the examples on the cppreference page: the "Hashable" property, the "Incrementable" property, the "Addable" property, etc. When attaching a 'requires' constraint to a type T, we can say "T must have the Hashable property", which to my ears sounds better than "T must satisfy the Hashable requirements". Just my thoughts, for what that might be worth. |
| Fran <flitterio@gmail.com>: Aug 06 04:05PM -0400 On Tue, 06 Aug 2019 09:31:00 -0700, Tim Rentsch >lots of the examples on the cppreference page: the "Hashable" >property, the "Incrementable" property, the "Addable" property, >etc. Those words sound like "capabilities" to me, which seems appropriate to the suffix "...able" on those names. -- Fran |
| David Brown <david.brown@hesbynett.no>: Aug 06 02:32PM +0200 On 05/08/2019 11:56, Öö Tiib wrote: > #pragma GCC optimize "-fno-wrapv" > The proposal does leave those optimizations beyond scope to keep > itself simple. There is a /huge/ difference between a flag that /adds/ semantics to the C++ standard language, and one that /removes/ semantics. Currently, gcc with an appropriate -std flag is quite close to standards compliant for a variety of C++ (and C) standards. It is not perfect, but AFAIK its as close as any other mainstream compiler. This is the case regardless of -fwrapv or -fno-wrapv (the default). A user can choose to add extra semantics to the language with -fwrapv if they find it useful and are willing to pay the price in lost optimisations and poorer safety and bug-catching tools. But if C++20 /requires/ wrapping semantics, then there is no longer a choice. If the compiler allows "-fno-wrapv", then (in that mode) it will no longer be a compliant C++20 compiler. Code written correctly to C++20 could fail to work correctly - and it could easily be silent failures. (If you are using special modes, like "-no-exceptions", code that relies on exceptions will have loud compile-time failures.) Such silent non-compliance would not be acceptable. > basically turning bad behavior that does who knows what into reliable > bad behavior that raises signals, throws exceptions, breaks or > terminates. You misunderstand me. For debugging purposes, consistent bad behaviour is useful. If the program crashes or does something weird in the same place each test run, it is a lot easier to find and fix the problem. But when you are testing your 16-bit MS-DOS apple cart program, and you add your 32,768th apple, it doesn't matter if the program prints out the balance as -32,768 apples or if it fails to print out anything - you can find the problem. With undefined behaviour on overflow, rather than wrapping behaviour, there is a solid chance you will get consistent effects from any particular compilation - but the details may change with other changes to the code or other compilation options. What you don't get is /predictable/ effects - but that doesn't matter for debugging. If you had been predicting effects properly, you wouldn't have the bug in the first place! And with overflow being undefined behaviour, and therefore always an error, you can use tools like gcc's sanitizer to give you a clear, consistent and helpful debug message when the problem occurs. Any tool or feature that makes it easier to find mistakes as early as possible, is a good tool in my book. Having integer overflow as undefined behaviour makes this easier - that is the most important reason I have for wanting it. Wrapping overflow makes bugs /harder/ to find. It increases the chance that the errors will go unnoticed, by quietly continuing with invalid results. >> settings to disable the warning? Isn't that a little inconsistent? > Yes, wrapping feature makes logical defects to behave more predictably > and Yes, I consider it good. That makes no sense. You prefer the behaviour of your defects to be predictable? To be useful, that would mean you would have to know your code has a defect - and in that case, surely you would fix the code rather than wanting to run it with predictable errors? The nearest use would be for debugging, where you want to work backwards from the bad effect you get to figure out what caused it. Predictability is sometimes useful then, but two's complement wrapping is not nearly as helpful as trap on overflow behaviour - which would be impossible when you have wrapping as part of the language definition. > Yes, wrapping feature is sometimes useful > also on its own. Occasionally, yes. It happens often enough that it is important the language has this capability. It happens rarely enough that it is not a problem to have somewhat ugly code to do it. For all platforms where you have two's complement representation of signed integers, you can handle this with conversions to and from unsigned types. It's not hard to wrap it all in a simple class if you want neater code. > Yes, there are compiler intrinsic functions so I can > live without the feature. Unsigned arithmetic is not a compiler intrinsic. You don't need to detect overflow to get wrapping behaviour. (Having said that, I would like to see some standard library classes that cover the features of many common intrinsics, such as gcc and clang's overflow builtins.) > Yes, I would still like warnings. Yes, I can > live without warnings. Yes, way to disable warnings can be good. Yes, > way to enable non-wrapping optimizations can be good. If wrapping behaviour is required for the language standard, you won't get these. > in rest. I am not sure how it all is inconsistent. There just are > priorities what I favor more and these priorities are likely bit > different for all people. What is inconsistent is to want a feature that is almost always an indication of incorrect code. > That would be even better indeed, but what the proposal suggested > was simpler to implement and to add to standard leaving that possible > but beyond scope of it. The proposal suggests something that I am convinced is a huge step backwards (making wrapping behaviour required), while failing to provide a simple, standardised way to let programmers make choices. (I note the proposal suggests, as you do, that compilers could still have flags like "-fno-wrapv". To me, this shows that the proposal authors are making the same mistake you are about the consequences of changing the semantics of the language.) >> Again, what do you think does not work with -fwrapv? > I have used it rarely and experimentally. It did sometimes optimize > int i loops when it should not. That tells me nothing, I am afraid. > to 10% performance difference on extreme case but that is again about > requiring some "-fno-wrapv" to allow compiler to do that optimization > not other way around. When currently "-fwrapv" is defective and Without further references than a vague memory of something that wasn't quite what you expected, I will continue to assume that "-fwrapv" is /not/ defective and works exactly as it says it will. Show me examples, bug reports, or something more definite and I will change that assumption. As I have said before, no one claims gcc is bug-free. > std::numeric_limits<int>::is_modulo is false then it is valid > to weasel out of each such case by saying that it is not a bug. In gcc, is_modulo is false because ints are not guaranteed to be wrapping. They /might/ have wrapping behaviour, depending on the flags and the code in question, but won't necessarily have it. Should the value of is_modulo be dependent on whether -fwrapv is in force or not? I don't think so - I think making these features dependent on compiler settings would open a large can of worms. Remember, you are free to change the -fwrapv setting in the middle of a file using pragmas, or with function attributes - I would not like to see is_modulo changing to fit. It is better to keep it at the pessimistic "false" setting. (That is, at least, my opinion on this particular matter - but I can see why some people could think differently.) > It reduces effort of finding and fixing when these defects behave more > uniformly. Usage of various debugging tools is good idea that helps > to reduce that effort too but is orthogonal to it and not in conflict. I accept what you are saying, but I think you are wrong. I disagree that wrapping overflow is useful for debugging, as I explained earlier. However, compilers like gcc give you the choice. Add "-fwrapv" when you find it helps with debugging - just as you might add sanitizer options and warning options. It does not have to be part of the language, which would reduce choice and options and limit your debugging tools. > Thanks, you have point there. If people will start to use that wrapping > behavior a lot for to achieve various effects then diagnosing it will > become more and more of false positive for those people. Indeed. A key problem with relying on wrapping behaviour is that it is very subtle - it is typically invisible in the code, without studying it in depth. > I suspect that people will use it only on limited but important cases > (like for self-diagnosing or for cryptography). Cryptography would typically use unsigned types. Having library features for detecting overflow would be clearer, safer, and more portable than relying on wrapping behaviour for those that want to check for problems after they have done their arithmetic that might overflow. I really dislike the concept of running into the traffic and then checking if you have been run over, instead of looking first and crossing when it is safe. It would be better to have types similar to std::optional which track the validity of operations - letting you happily perform arithmetic and at the end check for any failures. A big issue I have with the whole concept is that currently we have /types/ for which overflow is defined (unsigned types) and types for which it is not defined. But overflow behaviour should be part of the operations, not the types. > Other possible option > would to standardize compiler intrinsic functions for those cases. I would say making a standard library section that has the required behaviour - compilers can implement this using intrinsics or builtins if they like. > to mark or to rewrite questionable places to suppress false positive > diagnostics about well-defined code. I likely miss some depth of it > or am too naive about something else and it is hard to predict future. Predictions are hard, especially about the future! |
| David Brown <david.brown@hesbynett.no>: Aug 06 02:54PM +0200 On 31/07/2019 10:14, Bonita Montero wrote: > http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0907r0.html I've done a little digging, and there are several revisions to that paper. The latest (AFAICS) is: <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0907r4.html> One change in later revisions that is relevant to some parts of this thread is: """ *Status-quo* If a signed operation would naturally produce a value that is not within the range of the result type, the behavior is undefined. The author had hoped to make this well-defined as wrapping (the operations produce the same value bits as for the corresponding unsigned type), but WG21 had strong resistance against this. """ It seems I am not the only one who thinks this way. I think this revision will be a lot less controversial - it mostly documents the way current compilers work on current hardware, and simplifies the wording in the standard to match. I found another related paper: <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1236r1.html> I think the two papers cover the same ideas, but with different wording. I don't know what will actually end up in C++20. |
| M Powell <forumsmp@gmail.com>: Aug 05 05:22PM -0700 On Sunday, August 4, 2019 at 12:02:06 AM UTC-4, Alf P. Steinbach wrote: > Anyway... > If the network has sufficient bandwidth then I don't see what the > problem is. Got it. Thanks Alf |
| M Powell <forumsmp@gmail.com>: Aug 05 05:24PM -0700 On Sunday, August 4, 2019 at 8:57:40 AM UTC-4, Paavo Helde wrote: > especially the variations in its performance. And the 10 kHz number is > not something special, similar problems are there always when you > require something to happen during some fixed time. Got it. Thanks Paavo |
| 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