Re: threads?
I would implement threads in the following form $thread_counter = 0; $global = lock; $thread = new thread( \thread_sub ); $thread-start(); thread_sub { lock( $global ) { print i'm thread , ++$thread_counter, \n; } } It's a mixture of ithreads and the C# threading model. The thread works in the same interpreter. You have to do locking by yourself. That would make it light weighted and gives you the power to do everything you want. I don't think that normal threads are very difficult to understand. But it gives the highest flexibility.
Re: threads?
On Thu, Oct 21, 2010 at 6:04 PM, Darren Duncan dar...@darrenduncan.netwrote: Aaron Sherman wrote: Things that typically precipitate threading in an application: - Blocking IO - Event management (often as a crutch to avoid asynchronous code) - Legitimately parallelizable, intense computing Interestingly, the first two tend to be where most of the need comes from and the last one tends to be what drives most discussion of threading. The last one in particular would legitimately get attention when one considers that it is for this that the concern about using multi-core machines efficiently comes into play. That sounds great, but what's the benefit to a common use case? Sorting lists with higher processor overhead and waste heat in applications that traditionally weren't processor-bound in the first place? Over the past 20+ years, I've seen some very large, processor-bound applications that could (and in some cases, did) benefit from threading over multiple cores. However, they were so far in the minority as to be nearly invisible, and in many cases such applications can simply be run multiple times per host in order to VERY efficiently consume every available processor. The vast majority of my computing experience has been in places where I'm actually willing to use Perl, a grossly inefficient language (I say this, coming as I do from C, not in comparison to other HLLs), because my performance concerns are either non-existent or related almost entirely to non-trivial IO (i.e. anything sendfile can do). The first 2 are more about lowering latency and appearing responsive to a user on a single core machine. Write me a Web server, and we'll talk. Worse, write a BitTorrent client that tries to store its results into a high performance, local datastore without reducing theoretical, back-of-the-napkin throughput by a staggering amount. Shockingly enough, neither of these frequently used examples are processor-bound. The vast majority of today's applications are written with network communications in mind to one degree or another. The user, isn't so much interesting as servicing network and disk IO responsively enough that hardware and network protocol stacks wait on you to empty or fill a buffer as infrequently as possible. This is essential in such rare circumstances as: - Database intensive applications - Moving large data files across wide area networks - Parsing and interpreting highly complex languages inline from data received over multiple, simultaneous network connections (sounds like this should be rare, but your browser does it every time you click on a link) Just in working with Rakudo, I have to use git, make and Perl itself, all of which can improve CPU performance all they like, but will ultimately run slow if they don't handle reading dozens of files, possibly from multiple IO devices (disks, network filesystems, remote repositories, etc) as responsively as possible. Now, to back up and think this through, there is one place where multi-core processor usage is going to become critical over the next few years: phones. Android-based phones are going multi-core within the next six months. My money is on a multi-core iPhone within a year. These platforms are going to need to take advantage of multiple cores for primarily single-application performance in a low-power environment. So, I don't want you to think that I'm blind to the need you describe. I just don't want you to be unrealistic about the application balance out there. I think that Perl 6's implicit multi-threading approach such as for hyperops or junctions is a good best first choice to handle many common needs, the last list item above, without users having to think about it. Likewise any pure functional code. -- Darren Duncan It's very common for people working on the design or implementation of a programming language to become myopic with respect to the importance of executing code as quickly as possible, and I'm not faulting anyone for that. It's probably a good thing in most circumstances, but in this case, assuming that the largest need is going to be the execution of code turns out to be a misleading instinct. Computers execute code far, far less than you would expect, and the cost of failing to service events is often orders of magnitude greater than the cost of spending twice the number of cycles doing so. PS: Want an example of how important IO is? Google has their own multi-core friendly network protocol modifications to Linux that have been pushed out in the past 6 months: http://www.h-online.com/open/features/Kernel-Log-Coming-in-2-6-35-Part-3-Network-support-1040736.html They had to do this because single cores can no longer keep up with the network.
Re: threads?
I've done quite a lot of concurrent programming over the past 23ish years, from the implementation of a parallelized version of CLIPS back in the late 80s to many C, Perl, and Python projects involving everything from shared memory to process pooling to every permutation of hard and soft thread management. To say I'm rusty, however, would be an understatement, and I'm sure my information is sorely out of date. What I can contribute to such a conversation, however, is this: - Make the concept of process and thread an implementation detail rather than separate worlds and your users won't learn to fear one or the other. - If the programmer has to think about semaphore management, there's already a problem. - If the programmer's not allowed to think about semaphore management, there's already a problem. - Don't paint yourself into a corner when it comes to playing nice with local interfaces. - If your idea of instantiating a thread involves creating a on OS VM, then you're probably lighter weight than Python's threading model, but I'd suggesting parring it down some more. It's thread, not ringworld (I was going to say not 'space elevator,' but it seemed insufficient to the examples I've seen). I know that's pretty high-level, but it's what I've got. I think I wrote my last threaded application in 2007.
Re: threads?
On Tue, Oct 12, 2010 at 10:22 AM, Damian Conway dam...@conway.org wrote: Perhaps we need to think more Perlishly and reframe the entire question. Not: What threading model do we need?, but: What kinds of non-sequential programming tasks do we want to make easy...and how would we like to be able to specify those tasks? Things that typically precipitate threading in an application: - Blocking IO - Event management (often as a crutch to avoid asynchronous code) - Legitimately parallelizable, intense computing Interestingly, the first two tend to be where most of the need comes from and the last one tends to be what drives most discussion of threading. Perhaps it would make more sense to discuss Perl 6's event model (glib, IMHO, is an excellent role model, here -- http://en.wikipedia.org/wiki/Event_loop#GLib_event_loop ) and async IO model before we deal with how to sort a list on 256 cores...
Re: threads?
Aaron Sherman wrote: On Tue, Oct 12, 2010 at 10:22 AM, Damian Conway dam...@conway.org wrote: Perhaps we need to think more Perlishly and reframe the entire question. Not: What threading model do we need?, but: What kinds of non-sequential programming tasks do we want to make easy...and how would we like to be able to specify those tasks? Things that typically precipitate threading in an application: - Blocking IO - Event management (often as a crutch to avoid asynchronous code) - Legitimately parallelizable, intense computing Interestingly, the first two tend to be where most of the need comes from and the last one tends to be what drives most discussion of threading. Perhaps it would make more sense to discuss Perl 6's event model (glib, IMHO, is an excellent role model, here -- http://en.wikipedia.org/wiki/Event_loop#GLib_event_loop ) and async IO model before we deal with how to sort a list on 256 cores... The last one in particular would legitimately get attention when one considers that it is for this that the concern about using multi-core machines efficiently comes into play. The first 2 are more about lowering latency and appearing responsive to a user on a single core machine. I think that Perl 6's implicit multi-threading approach such as for hyperops or junctions is a good best first choice to handle many common needs, the last list item above, without users having to think about it. Likewise any pure functional code. -- Darren Duncan
Re: threads?
On Sun, Oct 17, 2010 at 01:18:09AM +0200, Carl Mäsak wrote: Damian (), Matt (): Perhaps we need to think more Perlishly and reframe the entire question. Not: What threading model do we need?, but: What kinds of non-sequential programming tasks do we want to make easy...and how would we like to be able to specify those tasks? I watched a presentation by Guy Steele at the Strange Loop conference on Thursday where he talked about non-sequential programming. One of the interesting things that he mentioned was to use the algebraic properties of an operation to know when a large grouping of operations can be done non-sequentially. For example, we know that the meta reduction operator could take very large lists and split them into smaller lists across all available cores when performing certain operations, like addition and multiplication. If we could mark new operators that we create with this knowledge we could do this for custom operators too. This isn't a new idea, but it seems like it would be a helpful tool in simplifying non-sequential programming and I didn't see it mentioned in this thread yet. This idea seems to be in the air somehow. (Even though all copies of the meme might have its roots in that Guy you mention.) http://irclog.perlgeek.de/perl6/2010-10-15#i_2914961 Perl 6 has all the prerequisites for making this happen. It's mostly a question of marking things up with some trait or other. our multi sub infix:+($a, $b) will optimizeassociativity { ... } (User-defined ops can be markes in exactly the same way.) All that's needed after that is a reduce sub that's sensitive to such traits. Oh, and threads. Minimizing the overhead of such a mechanism would be crucial to making it beneficial for use on non-massive data sets. For this kind of thing to work well we'd need to have multiple threads able to work in a single interpreter. Tim.
Re: threads?
Damian (), Matt (): Perhaps we need to think more Perlishly and reframe the entire question. Not: What threading model do we need?, but: What kinds of non-sequential programming tasks do we want to make easy...and how would we like to be able to specify those tasks? I watched a presentation by Guy Steele at the Strange Loop conference on Thursday where he talked about non-sequential programming. One of the interesting things that he mentioned was to use the algebraic properties of an operation to know when a large grouping of operations can be done non-sequentially. For example, we know that the meta reduction operator could take very large lists and split them into smaller lists across all available cores when performing certain operations, like addition and multiplication. If we could mark new operators that we create with this knowledge we could do this for custom operators too. This isn't a new idea, but it seems like it would be a helpful tool in simplifying non-sequential programming and I didn't see it mentioned in this thread yet. This idea seems to be in the air somehow. (Even though all copies of the meme might have its roots in that Guy you mention.) http://irclog.perlgeek.de/perl6/2010-10-15#i_2914961 Perl 6 has all the prerequisites for making this happen. It's mostly a question of marking things up with some trait or other. our multi sub infix:+($a, $b) will optimizeassociativity { ... } (User-defined ops can be markes in exactly the same way.) All that's needed after that is a reduce sub that's sensitive to such traits. Oh, and threads. // Carl
Re: threads?
On Oct 12, 2010, at 9:22 AM, Damian Conway wrote: Perhaps we need to think more Perlishly and reframe the entire question. Not: What threading model do we need?, but: What kinds of non-sequential programming tasks do we want to make easy...and how would we like to be able to specify those tasks? I watched a presentation by Guy Steele at the Strange Loop conference on Thursday where he talked about non-sequential programming. One of the interesting things that he mentioned was to use the algebraic properties of an operation to know when a large grouping of operations can be done non-sequentially. For example, we know that the meta reduction operator could take very large lists and split them into smaller lists across all available cores when performing certain operations, like addition and multiplication. If we could mark new operators that we create with this knowledge we could do this for custom operators too. This isn't a new idea, but it seems like it would be a helpful tool in simplifying non-sequential programming and I didn't see it mentioned in this thread yet. Here are the slides to the talk to which I'm referring: http://strangeloop2010.com/talk/presentation_file/14299/GuySteele-parallel.pdf ~Matt
Re: threads?
I haven't enough smarts to see if this is at all what you're looking for but is used some of the same terms: http://dpj.cs.uiuc.edu/DPJ/Home.html?cid=nl_ddjupdate_2010-10-12_html Welcome to the home page for the Deterministic Parallel Java (DPJ) project at the University of Illinois at Urbana-Champaign. Project Overview The broad goal of our project is to provide deterministic-by-default semantics for an object-oriented, imperative parallel language, using primarily compile-time checking. ?Deterministic? means that the program produces the same visible output for a given input, in all executions. ?By default? means that deterministic behavior is guaranteed unless the programmer explicitly requests nondeterminism. This is in contrast to today?s shared-memory programming models (e.g., threads and locks), which are inherently nondeterministic and can even have undetected data races. Our paper at HotPar 2009 states our research goals in more detail. The other pages of this site provide additional information about the DPJ type system and language. a -- Andy Bach Systems Mangler Internet: andy_b...@wiwb.uscourts.gov Voice: (608) 261-5738; Cell: (608) 658-1890 No, no, you're not thinking, you're just being logical. -Niels Bohr, physicist (1885-1962)
Re: threads?
On Tue, Oct 12, 2010 at 10:43:44PM +0200, Leon Timmermans wrote: On Tue, Oct 12, 2010 at 4:22 PM, Damian Conway dam...@conway.org wrote: The problem is: while most people can agree on what have proved to be unsatisfactory threading models, not many people can seem to agree on what would constititute a satisfactory threading model (or, possibly, models). What we really need is some anecdotal evidence from folks who are actually using threading in real-world situations (in *any* languages). What has worked in practice? What has worked well? What was painful? What was error-prone? And for which kinds of tasks? Most languages either implement concurrency in a way that's not very useful (CPython, CRuby) or implement it in a way that's slightly (Java/C/C++) to totally (perl 5) insane. Erlang is the only language I've worked with whose threads I really like, but sadly it's rather weak at a lot of other things. In general, I don't feel that a shared memory model is a good fit for a high level language. I'm very much a proponent of message passing. Unlike shared memory, it's actually easier to do the right thing than not. Implementing it correctly and efficiently is not easier than doing a shared memory system though in my experience (I'm busy implementing it on top of ithreads; yeah I'm masochist like that). And we also need to stand back a little further and ask: is threading the right approach at all? Do threads work in *any* language? Are there better metaphors? Perhaps we need to think more Perlishly and reframe the entire question. Not: What threading model do we need?, but: What kinds of non-sequential programming tasks do we want to make easy...and how would we like to be able to specify those tasks? I agree. I would prefer implicit over explicit concurrency wherever possible. I know you're speaking about the Perl interface to concurrency, but you seem to contradict yourself because message passing is explicit whereas shared memory is implicit - two different models, both of which could be used together to implement a pretty flexible system. It'd be a shame to not provide a way to both use threads directly or to fallback to some implicitly concurrent constructs. Brett -- B. Estrade estr...@gmail.com
Re: threads?
On Tue, Oct 12, 2010 at 07:22:33AM -0700, Damian Conway wrote: Leon Timmermans wrote: For the love of $DEITY, let's please not repeat ithreads! $AMEN! Backwards compatibility is not the major design criterion for Perl 6, so there's no need to recapitulate our own phylogeny here. The problem is: while most people can agree on what have proved to be unsatisfactory threading models, not many people can seem to agree on what would constititute a satisfactory threading model (or, possibly, models). What we really need is some anecdotal evidence from folks who are actually using threading in real-world situations (in *any* languages). What has worked in practice? What has worked well? What was painful? What was error-prone? And for which kinds of tasks? And we also need to stand back a little further and ask: is threading the right approach at all? Do threads work in *any* language? Are there better metaphors? A more general metaphore would be asynchronous tasking, a thread being a long running implicit task. Other issues include memory consistency models, tasking granularity, scheduling, and flexible synchronization options. I am coming from the OpenMP world, so a lot of this falls on the shoulders of the runtime - a clear strength of Perl IMHO. It may be worth someone taking the time to read what the OpenMP spec has to say about tasking as well as exploring tasking support on Chapel, Fortress, X10, and Cilk. PGAS based languages may also offer some inspirations as a potential alternative to threads or tasks. The only scriping language that I know that supports threading natively is Qore. I've mentioned this before. Perl's functional aspects also make it fairly easy to create concurrency without the worry of side effects, but not everyone is lucky enough to have a loosely coupled problem or not need i/o. Now how to distill what's been learned in practice into a Perlish approach? Perhaps we need to think more Perlishly and reframe the entire question. Not: What threading model do we need?, but: What kinds of non-sequential programming tasks do we want to make easy...and how would we like to be able to specify those tasks? There are something like 12 HPC domains that have been identified, all needing something a little different from the compiler, runtime, and platform - these do not include things for which Perl is often (ab)used. As someone who doesn't (need to) use threading to solve the kinds of problems I work on, I'm well aware that I'm not the right person to help in this design work. We need those poor souls who already suffer under threads to share their tales of constant misery (and their occasional moments of triumph) so we can identify successful patterns of use and steal^Wborg^Wborrow the very best available solutions. Are you sure you couldn't use threading over shared memory? :) Cheers, Brett Damian -- B. Estrade estr...@gmail.com
Re: threads?
On Tue, Oct 12, 2010 at 02:31:26PM +0200, Carl M?sak wrote: Ben (): If perl6 can statically (at compile time) analyse subroutines and methods and determine if they're reentrant, then it could automatically use the lightest weight threads when it knows that the entry sub won't have side effects or alter global data. I'm often at the receiving end of this kind of reply, but... ...to a first approximation, I don't believe such analysis to be possible in Perl 6. Finding out whether something won't have side effects is tricky at best, squeezed in as we are between eval, exuberant dynamism, and the Halting Problem. If one knows what variables are shared, some degree of side effect potential can be determined. But yes, in general, a tough problem. Brett // Carl -- B. Estrade estr...@gmail.com
Re: threads? - better metaphors
On 2010-Oct-12, at 10:22, Damian Conway wrote: What we really need is some anecdotal evidence from folks who are actually using threading in real-world situations (in *any* languages). What has worked in practice? What has worked well? What was painful? What was error-prone? And for which kinds of tasks? And we also need to stand back a little further and ask: is threading the right approach at all? Do threads work in *any* language? Are there better metaphors? 'Channels are a good model of the external world' - Russ Cox Threads without Locks, slide 39 Perhaps the work on the 'channel' model done in Plan9 (and Inferno) will be helpful. It has many years of experience in publicly available code, libraries, and discussion archives, and verification tools. Particularly the work of Russ Cox http://swtch.com/~rsc/ Particularly Threads without Locks Bell Labs, Second International Plan 9 Workshop, December 2007 http://swtch.com/~rsc/talks/threads07/ This talk has a nice crisp overview of the issues in different models and mentions several real world applications concurrent prime sieve (by Mcllroy) file system indexer implementation publish and subscribe re-entrant IO multiplexing window systems http://swtch.com/~rsc/thread/cws.pdf -- amazing stuff! http://video.google.com/videoplay?docid=810232012617965344 the classic 'Squinting at Power Series' - and several others (see slide 31) http://swtch.com/~rsc/thread/squint.pdf (this could be an excellent test suite of any 'threading' implementation) and extended in the work of PlanB http://lsub.org/ls/planb.html http://lsub.org/index.html#demos This model is available on many OSs in the port of Plan9 to user space http://swtch.com/plan9port/ and in C based libthread that builds multiple-reader, multiple-writer finite queues. There is a lot to like and borrow from Plan9, including the 9P2000 protocol as a core organizing meme http://9p.cat-v.org/faq The 'Spin' verification tool and it's history are *very* interesting also http://swtch.com/spin/ Note that many of the people doing 'go' were the ones that did Plan9 Regards, Todd Olson PS I'd really like to have their channel model available in Perl6 Many things I'd like to model would work well with channels I have (unpublished) Perlish syntax to lay over channels PPS Russ has also done some nice work on regular expression engines http://swtch.com/~rsc/regexp/
Re: threads?
On Mon, Oct 11, 2010 at 12:32 AM, Ben Goldberg ben-goldb...@hotmail.com wrote: If thread-unsafe subroutines are called, then something like ithreads might be used. For the love of $DEITY, let's please not repeat ithreads!
Re: threads?
Leon Timmermans wrote: For the love of $DEITY, let's please not repeat ithreads! $AMEN! Backwards compatibility is not the major design criterion for Perl 6, so there's no need to recapitulate our own phylogeny here. The problem is: while most people can agree on what have proved to be unsatisfactory threading models, not many people can seem to agree on what would constititute a satisfactory threading model (or, possibly, models). What we really need is some anecdotal evidence from folks who are actually using threading in real-world situations (in *any* languages). What has worked in practice? What has worked well? What was painful? What was error-prone? And for which kinds of tasks? And we also need to stand back a little further and ask: is threading the right approach at all? Do threads work in *any* language? Are there better metaphors? Perhaps we need to think more Perlishly and reframe the entire question. Not: What threading model do we need?, but: What kinds of non-sequential programming tasks do we want to make easy...and how would we like to be able to specify those tasks? As someone who doesn't (need to) use threading to solve the kinds of problems I work on, I'm well aware that I'm not the right person to help in this design work. We need those poor souls who already suffer under threads to share their tales of constant misery (and their occasional moments of triumph) so we can identify successful patterns of use and steal^Wborg^Wborrow the very best available solutions. Damian
RE: threads?
Although anecdotal, I've heard good things about Go's channel mechanism as a simple lightweight concurrency model and a good alternative to typical threading. Channels are first-class in the language and leverage simple goroutine semantics to invoke concurrency. --- Phil -Original Message- From: thoughtstr...@gmail.com [mailto:thoughtstr...@gmail.com] On Behalf Of Damian Conway Sent: October 12, 2010 10:23 AM To: perl6-language@perl.org Subject: Re: threads? Leon Timmermans wrote: For the love of $DEITY, let's please not repeat ithreads! $AMEN! Backwards compatibility is not the major design criterion for Perl 6, so there's no need to recapitulate our own phylogeny here. The problem is: while most people can agree on what have proved to be unsatisfactory threading models, not many people can seem to agree on what would constititute a satisfactory threading model (or, possibly, models). What we really need is some anecdotal evidence from folks who are actually using threading in real-world situations (in *any* languages). What has worked in practice? What has worked well? What was painful? What was error-prone? And for which kinds of tasks? And we also need to stand back a little further and ask: is threading the right approach at all? Do threads work in *any* language? Are there better metaphors? Perhaps we need to think more Perlishly and reframe the entire question. Not: What threading model do we need?, but: What kinds of non-sequential programming tasks do we want to make easy...and how would we like to be able to specify those tasks? As someone who doesn't (need to) use threading to solve the kinds of problems I work on, I'm well aware that I'm not the right person to help in this design work. We need those poor souls who already suffer under threads to share their tales of constant misery (and their occasional moments of triumph) so we can identify successful patterns of use and steal^Wborg^Wborrow the very best available solutions. Damian
Re: threads?
Damian, I use threads in C++ a lot in my day to day job. We use an in-house library which isn't much more than a thread class which you inherit from and give a Run method to, and a load of locks of various (sometimes ill-defined) kinds. Let me say: it's not good. Threads with semaphores and mutexes and all that are just horrible, horrible things. It's probably not helped at all by how C++ itself has no awareness at all of the threading, so there are no hints in the code that something runs in a particular thread, you can't put lock preconditions on functions or data structures or anything like that... I'm not sure what a better model is, but what I'd like to see is something which: - can enforce that certain bits of data are only accessed if you have certain locks, at compile time - can enforce that certain bits of code can only be run when you have certain locks, at compile time - can know that you shouldn't take lock B before lock A if you want to avoid a deadlock - uses a completely different model that nobody's probably thought of yet where none of this matters because all those three things are utterly foul I always liked Software Transactional Memory, which works very nicely in Haskell - but not for all solutions. Whatever concurrency model Perl 6 might support, it's probably going to need more than one of them. Since the language is so extensible, it may be that the core should only implement the very basic primitives, and then there are libraries which provide the rest - some of which might ship alongside the compiler. I don't know, but I do not want people to end up having to count semaphores and verify locking integrity by eye because it's really, truly horrible. I did read a bit about Go's mechanism, and it did look interesting. Some systems are very well-modelled as completely independent processes (which might be threads) throwing messages at each other... Actually something that's very nice as a mental model for server-type systems is a core routine which responds to a trigger (say, a new connection) by spawning a new thread to handle it, which is the only thing which handles it, and maybe uses something like channels to interact with any global data store that's required. For that though you need cheap thread creation or easy thread pool stuff, and you need to have a global data model which isn't going to completely bottleneck your performance. I'm totally rambling now, but I do get the distinct impression from all my experience that safe concurrency is very difficult to do quickly in the general case. Of course, the safest concurrency boils down to sequencing everything and running it all on one core... On 12 October 2010 16:25, philippe.beauch...@bell.ca wrote: Although anecdotal, I've heard good things about Go's channel mechanism as a simple lightweight concurrency model and a good alternative to typical threading. Channels are first-class in the language and leverage simple goroutine semantics to invoke concurrency. --- Phil -Original Message- From: thoughtstr...@gmail.com [mailto:thoughtstr...@gmail.com] On Behalf Of Damian Conway Sent: October 12, 2010 10:23 AM To: perl6-language@perl.org Subject: Re: threads? Leon Timmermans wrote: For the love of $DEITY, let's please not repeat ithreads! $AMEN! Backwards compatibility is not the major design criterion for Perl 6, so there's no need to recapitulate our own phylogeny here. The problem is: while most people can agree on what have proved to be unsatisfactory threading models, not many people can seem to agree on what would constititute a satisfactory threading model (or, possibly, models). What we really need is some anecdotal evidence from folks who are actually using threading in real-world situations (in *any* languages). What has worked in practice? What has worked well? What was painful? What was error-prone? And for which kinds of tasks? And we also need to stand back a little further and ask: is threading the right approach at all? Do threads work in *any* language? Are there better metaphors? Perhaps we need to think more Perlishly and reframe the entire question. Not: What threading model do we need?, but: What kinds of non-sequential programming tasks do we want to make easy...and how would we like to be able to specify those tasks? As someone who doesn't (need to) use threading to solve the kinds of problems I work on, I'm well aware that I'm not the right person to help in this design work. We need those poor souls who already suffer under threads to share their tales of constant misery (and their occasional moments of triumph) so we can identify successful patterns of use and steal^Wborg^Wborrow the very best available solutions. Damian On 12 October 2010 16:25, philippe.beauch...@bell.ca wrote: Although anecdotal, I've heard good things about Go's channel mechanism as a simple lightweight concurrency model and a good alternative to typical
Re: threads?
When Larry decided that Perl 6 would incorporate concepts from prototype-based objects, he did so at least in part because it's more intuitive for people to work with, e.g., a cow than it is to try to work with the concept of a cow as a thing unto itself. In a similar way, I think that Perl's dominant concurrency system ought to be of a type that people who aren't computer scientists can grok, at least well enough to do something useful without first having to delve into the arcane depths of computing theory. As such, I'm wondering if an Actor-based concurrency model[1] might be a better way to go than the current threads-based mindset. Certainly, it's often easier to think of actors who talk to each other to get things done than it is to think of processes (or threads) as things unto themselves. [1] http://en.wikipedia.org/wiki/Actor_model -- Jonathan Dataweaver Lang
Re: threads?
On Tue, Oct 12, 2010 at 4:22 PM, Damian Conway dam...@conway.org wrote: The problem is: while most people can agree on what have proved to be unsatisfactory threading models, not many people can seem to agree on what would constititute a satisfactory threading model (or, possibly, models). What we really need is some anecdotal evidence from folks who are actually using threading in real-world situations (in *any* languages). What has worked in practice? What has worked well? What was painful? What was error-prone? And for which kinds of tasks? Most languages either implement concurrency in a way that's not very useful (CPython, CRuby) or implement it in a way that's slightly (Java/C/C++) to totally (perl 5) insane. Erlang is the only language I've worked with whose threads I really like, but sadly it's rather weak at a lot of other things. In general, I don't feel that a shared memory model is a good fit for a high level language. I'm very much a proponent of message passing. Unlike shared memory, it's actually easier to do the right thing than not. Implementing it correctly and efficiently is not easier than doing a shared memory system though in my experience (I'm busy implementing it on top of ithreads; yeah I'm masochist like that). And we also need to stand back a little further and ask: is threading the right approach at all? Do threads work in *any* language? Are there better metaphors? Perhaps we need to think more Perlishly and reframe the entire question. Not: What threading model do we need?, but: What kinds of non-sequential programming tasks do we want to make easy...and how would we like to be able to specify those tasks? I agree. I would prefer implicit over explicit concurrency wherever possible.
Re: threads?
On Tue, Oct 12, 2010 at 10:28 PM, B. Estrade estr...@gmail.com wrote: I agree. I would prefer implicit over explicit concurrency wherever possible. I know you're speaking about the Perl interface to concurrency, but you seem to contradict yourself because message passing is explicit whereas shared memory is implicit - two different models, both of which could be used together to implement a pretty flexible system. With implicit I mean stuff like concurrent hyperoperators and junctions. Shared memory systems are explicitly concurrent to me because you have to ether explicitly lock or explicitly do a transaction. It'd be a shame to not provide a way to both use threads directly or to fallback to some implicitly concurrent constructs. I agree
Re: threads?
Damian Conway wrote: Perhaps we need to think more Perlishly and reframe the entire question. Not: What threading model do we need?, but: What kinds of non-sequential programming tasks do we want to make easy...and how would we like to be able to specify those tasks? The mindset that I use goes something like most tasks are potentially concurrent: sequentialization is an optimization that most people perform without even thinking. Generally, I would split concurrency into producer-consumer (i.e. message passing) and stream-processing (for hyper and reduction operators -- possibly also for feeds, with a kernel per step). When dealing with compute-tasks, you're basically just choosing how to map a dependency graph to the available compute resources. When dealing with external resources (e.g. sockets, GUI) then explicit parallelism (via message passing) becomes useful. P6 already specifies a whole bunch of non-sequential tasks (hypers, reductions, feeds, background-lazy lists), so no need to reframe the entire question just yet. Implementing the existing concurrency will flush out plenty of flaws in the specs.
Re: threads?
I agree that threads are generelly a difficult issue to cope. What is worse, there are a lot of Java-developers who tell us, that it is not difficult for them, but in the end the software fails on the productive system, for example because the load is different then on the test system, causing different threads to be slowed down to a different extent etc. So people who are having difficulties with multithreading still use them a lot and don't admit the difficulties and they might not even appear during testing... Even though I did see software that heavily uses multithreading and works well. On the other hand I think that there are certain tasks that need to use some kind of parallelism, either for making use of parallel CPU infrastructure or for implementing patterns that can more easily be expressed using something like multithreading. I think that the approach of running several processes instead of several threads is something that can be considered in some cases, but I think it does come with a performance price tag that might not be justified in all situations. Maybe the actor model from Scala is worth looking at, at least the Scala-guys claim that that solves the issue, but I don't know if that concept can easily be adapted for Perl 6. Best regards, Karl
Re: Threads and Progress Monitors
--- Dave Whipp [EMAIL PROTECTED] wrote: Dulcimer wrote: sub slow_fn { my $tick = Timer.new(60, { print ... }); return slow_fn_imp @_; } Now if I could just get the compiler to not complain about that unused variable... Maybe I'm being dense Why not just sub slow_fn { Timer.new(1, { print . }); return slow_fn_imp @_; } Geez. I read my response this morning, which I wrote just before going to bed, and realized that I must've been dead on my feet. The problem is that I want the timer to last for the duration of the slow_fn_imp. If I don't assign it to a variable, then it may be GCed at any time. I was making several assumptions which don't hold, apparently, such as that the underlying Timer would iterate until stopped. Not an ideal default, lol I thopught the point was to have the function print dots repeatedly, tho? I've just realised, however, that I'm relying on it being destroyed on leaving the scope. I'm not sure that the GC guarentees that. I might need sub slow_fn { my $timer is last { .stop } = Timer.new(60, { print . }); return slow_fn_imp @_; } but that's starting to get cluttered again. I don't really consider that clutter. It's clear and to the point, and Does What You Want. How about sub slow_fn { my $timer is last { .stop } = new Timer secs = 1, reset = 1, code = {print .}; return slow_fn_imp @_; } so that the timer goes off after a second, prints a dot, and resets itself to go off again after another second? And I still like the idea of an expanding temporal window between dots: sub slow_fn { my $pause = 1; my $timer is last { .stop } = new Timer secs = $pause++, reset = {$pause++}, code = {print .}; return slow_fn_imp @_; } As a sidenote, although it would actually reduce readability here, I'm still trying to wrap my brain thoroughly around the new dynamics of $_. Would this work correctly maybe? sub slow_fn { my $timer is last { .stop } = new Timer secs = $_=1, reset = {$_++}, code = {print .}; return slow_fn_imp @_; } Isn't that $_ proprietary to slow_fn such that it *would* work? __ Do you Yahoo!? Yahoo! Calendar - Free online calendar with sync to Outlook(TM). http://calendar.yahoo.com
Re: Threads and Progress Monitors
--- Dave Whipp [EMAIL PROTECTED] wrote: OK, we've beaten the producer/consumer thread/coro model to death. Here's a different use of threads: how simple can we make this in P6: sub slow_func { my $percent_done = 0; my $tid = thread { slow_func_imp( \$percent_done ) }; thread { status_monitor($percent_done) and sleep 60 until $tid.done }; return wait $tid; } I think this would work under Austin's A17; but it feels a bit clunky. The fact that the sleep 60 isn't broken as soon as the function is done is untidy, though I wouldn't want to start killing thread. perhaps: { ... $tid = thread { slow... } status_monitor(\$percent_done) and wait(60 | $tid) until $tid.done; return $tid.result; } The thing is, that wait 60 probably can't work -- replace C60 with C$period, and the semantics change. There are some obvious hacks that could work here: but is there a really nice solution. Ideally, we won't need the low level details such as C$tid sub slow_func_imp { my $pct_done = 0; ... yield $pct_done++; # Per my recent message ... } sub slow_func { my $tid := thread slow_func_imp; status_monitor($tid.resume) while $tid.active; }
Re: Threads and Progress Monitors
On Thursday, May 29, 2003, at 10:47 AM, Dave Whipp wrote: OK, we've beaten the producer/consumer thread/coro model to death. Here's a different use of threads: how simple can we make this in P6: Hey, good example. Hmm... Well, for starters I think it wouldn't be a big deal to associate a progress attribute with each thread object. It should be that thread's responsibility to fill it out, if it wants to -- so you shouldn't ever have to pass \$percent_done as an argument, it should be a basic attribute of every thread instance. That might encourage people to add progress calculations to their threads after-the-fact, without changing the basic interface of what they wrote. I'll also claim that I would still prefer the auto-parallel, auto-lazy-blocking behavior on the thread results we've mused about previously. So coming from the semantics end, I'd love to see it written like this: # Declaring a threaded calculation sub slow_func_impl is threaded { while (...stuff...) { ... do stuff ... _.thread.progress += 10.0; # or however you want to guesstimate[*] this } return $result; } # If you don't care about getting the actual thread object, just the result, # call it this way: { ... my $result = slow_func_impl(...); ... return $result; } # But if you want to get the thread object, so you can monitor it's progress, # call it this way: { ... my $tid = thread slow_func_impl(...); while $tid.active { status_monitor($tid.progress); sleep 60; } return $tid.result; } To my eye, that looks pretty darn slick. MikeL [*] Huh. Imagine my surprise to find out that my spellcheck considers guesstimate to be a real word. And I always thought that was just a spasmostical pseudolexomangloid.
Re: Threads and Progress Monitors
Michael Lazzaro [EMAIL PROTECTED] wrote in # But if you want to get the thread object, so you can monitor it's { ... my $tid = thread slow_func_impl(...); while $tid.active { status_monitor($tid.progress); sleep 60; } return $tid.result; } To my eye, that looks pretty darn slick. You might be a bit frustrated if the slow_func_impl took 61 seconds :-(. How do we interrupt the Csleep? Possibly in the same way as we'd timeout a blocking IO operations. But I wonder if this could work: my $tid = thread slow_func_impl(...); until wait $tid, timeout=60 { status_monitor($tid.progress); } return $tid.result; Here I assume that Cwait returns a true value if its waited condition occurs, but false if it times out. Hmm, A few days ago I tried indroducing a syntax for thread with a sensitivity list in place of an explict loop-forever thread. Perhaps I can reuse that syntax: my $tid = thread slow_func_impl(...); thread $tid | timeout(60) { when $tid = { return $tid.result } default = { status_monitor $tid.progress } } Perhaps a different keyword would be better: Calways as the looping counterpart to Cwait -- then extend Cwait to accept a code block. Dave.
Re: Threads and Progress Monitors
On Thu, May 29, 2003 at 10:47:35AM -0700, Dave Whipp wrote: OK, we've beaten the producer/consumer thread/coro model to death. Here's a different use of threads: how simple can we make this in P6: sub slow_func { my $percent_done = 0; my $tid = thread { slow_func_imp( \$percent_done ) }; thread { status_monitor($percent_done) and sleep 60 until $tid.done }; return wait $tid; } At first glance, this doesn't need a thread - a coroutine is sufficient. Resume the status update coroutine whenever there has been some progress. It doesn't wait and poll a status variable, it just let the slow function work at its own speed without interruption until there is a reason to change the display. In fact, it probably doesn't need to be a coroutine either. A subroutine - display_status( $percent ) - should't require any code state to maintain, just a bit if data so all it needs is a closure or an object. At second glance, there is a reason for a higher powered solution. If updating the display to a new status takes a significant amount of time, especially I/O time, it would both block the slow function unnecessarily and would update for every percent point change. Using a separate process or thread allows the function to proceed without blocking, and allows the next update to jmp ahead to the current actual level, skipping all of the levels that occurred while the previous display was happening. Instead of sleep, though, I'd use a pipeline and read it with a non-blocking read until there is no data. Then, if the status has changed since the last update, do a display update and repeat the non-blocking read. If the status has not changed, do a blocking read to wait for the next status change.
Re: Threads and Progress Monitors
John Macdonald [EMAIL PROTECTED] wrote At first glance, this doesn't need a thread - a Instead of sleep, though, I'd use a pipeline and read it with a non-blocking read until there is no data. ... ++ For the lateral thinking. Definitely a valid solution to the problem, as given. So I'll change the problem prevent it: the slow fn is a 3rd-party blob with no access to source code and no progress indication. sub slow_fn { print starting slow operation: this sometimes takes half an hour!\n; my $tid = thread { slow_fn_imp @_ }; $start = time; loop { wait $tid | timeout(60); return $tid.result if $tid.done; print ... $(time-$start) seconds\n; } } Still a bit too complex for my taste: perhaps we can use Ctimeout to generate exceptions: my lazy::threaded $result := { slow_fn_imp @_ }; loop { timeout(60); return $result; CATCH Timeout { print ...$(time)\n } } At last, no Ctid! (Reminder: the suggested semantics of the threaded variable were that a FETCH to it blocks until the result of the thread is available). Dave.
Re: Threads and Progress Monitors
Dave wrote: Still a bit too complex for my taste: perhaps we can use Ctimeout to generate exceptions: my lazy::threaded $result := { slow_fn_imp @_ }; loop { timeout(60); return $result; CATCH Timeout { print ...$(time)\n } } At last, no Ctid! (Reminder: the suggested semantics of the threaded variable were that a FETCH to it blocks until the result of the thread is available). To nitpick: my $result is lazy::threaded := { slow_fn_imp @_ }; Because lazy::threaded isn't the Ireturn type, it's the Ivariable type. loop { timeout(60); return $result; CATCH { when Timeout { print ...$(time)\n } } Because CCATCH is like Cgiven $!. I like that elegant use of threaded variables, by the way. Now write the Ctimeout function :-P. Luke
Re: Threads and Progress Monitors
On Thursday, May 29, 2003, at 12:45 PM, Dave Whipp wrote: Michael Lazzaro [EMAIL PROTECTED] wrote in # But if you want to get the thread object, so you can monitor it's { ... my $tid = thread slow_func_impl(...); while $tid.active { status_monitor($tid.progress); sleep 60; } return $tid.result; } To my eye, that looks pretty darn slick. You might be a bit frustrated if the slow_func_impl took 61 seconds :-(. How do we interrupt the Csleep? Possibly in the same way as we'd timeout a blocking IO operations. Personally, I'd be happy with just making the Csleep a smaller number, like one second, or a fifth of a second, or whatever. You want the status_monitor to be updated no more often than it needs to be, but often enough that it's not lagging. But if you really wanted wake-immediately-upon-end, I'd add that as a variant of Csleep. For example, you might want a variant that blocked until a given variable changed, just like in debuggers; that would allow: { my $tid = thread slow_func_impl(...); while $tid.active { status_monitor($tid.progress); sleep( 60, watch = \($tid.progress) ); # do you even need the '\'? } return $tid.result; } ... which would sleep 60 seconds, or until the .progress attribute changed, whichever came first. You could make more builtins for that, but I think I'd like them to just be Csleep or Cwait variants. Obvious possibilities: sleep 60; # sleep 60 seconds sleep( block = $tid ); # sleep until given thread is complete sleep( watch = \$var ); # sleep until given var changes value sleep( 60, block = $tid, watch = [\$var1, \$var2, \$var3] ); five tests $tid.sleep(...);# sleep the given thread, instead of this one MikeL
Re: Threads and Progress Monitors
On Thursday, May 29, 2003, at 04:48 PM, Luke Palmer wrote: To nitpick: my $result is lazy::threaded := { slow_fn_imp @_ }; Pursuing this lazy-threaded variables notion, a question. Given: sub slow_func is threaded {# me likey this auto-parallelizing syntax! ... } Would we want to say that _both_ of these have the lazy-blocking behavior? my $result := slow_func(); print $result; my $result = slow_func(); print $result; Or would the first one block at Cprint, but the second block immediately at the C=? The obvious answer is that the := binding passes through the lazyness, but the = assignment doesn't. But I wonder if that isn't a bit too obscure, to put it mildly. MikeL
Re: Threads and Progress Monitors
sub slow_fn { my $tick = Timer.new(60, { print ... }); return slow_fn_imp @_; } Now if I could just get the compiler to not complain about that unused variable... Maybe I'm being dense Why not just sub slow_fn { Timer.new(1, { print . }); return slow_fn_imp @_; } or maybe even sub slow_fn { my $tick = 1; Timer.new({$tick++}, { print . }); return slow_fn_imp @_; } For a slowly slowing timer ? Or to my taste, sub slow_fn { Timer.new(60, { print ... }); return slow_fn_imp @_; } __ Do you Yahoo!? Yahoo! Calendar - Free online calendar with sync to Outlook(TM). http://calendar.yahoo.com
Re: Threads and Progress Monitors
Dulcimer wrote: sub slow_fn { my $tick = Timer.new(60, { print ... }); return slow_fn_imp @_; } Now if I could just get the compiler to not complain about that unused variable... Maybe I'm being dense Why not just sub slow_fn { Timer.new(1, { print . }); return slow_fn_imp @_; } The problem is that I want the timer to last for the duration of the slow_fn_imp. If I don't assign it to a variable, then it may be GCed at any time. I've just realised, however, that I'm relying on it being destroyed on leaving the scope. I'm not sure that the GC guarentees that. I might need sub slow_fn { my $timer is last { .stop } = Timer.new(60, { print . }); return slow_fn_imp @_; } but that's starting to get cluttered again. Dave.
Re: Threads and Progress Monitors
Dave Whipp said: I've just realised, however, that I'm relying on it being destroyed on leaving the scope. I'm not sure that the GC guarentees that. GC doesn't, but I would be surprised if Perl 6 doesn't and in that case Parrot will be accommodating. Take a look at the recent p6i archives for the gory details. -- Paul Johnson - [EMAIL PROTECTED] http://www.pjcj.net
Re: Threads and run time/compile time
I wish I knew why you are discussing in -internals issue on this list. You should be specifying behaviour not how it is implemented. A mention of implementation is reasonable but _don't_ spend too much time. If Larry wants it. -internals will give it to him. Anyway, please recall that because of threading concerns, the final internal form of any compiled piece of code will be as immutable as possible. So that if another thread needs to reslurp a module, the compiled form will be available. Of course, some initializations would have to be rerun, but that is minor compared to the other costs. Remember specify _as if_ it would do X. -internals will make it so. As fast as possible. chaim (Of course some requests will not be doable and some revisitin will have to be performed but the first cut should not be too concerned.) c "SWM" == Steven W McDougall [EMAIL PROTECTED] writes: SWM Based on your examples, I have to assume that you are serious about SWM RFC1v3 item 6: SWM 6. Modules should be loaded into the thread-global space when used SWM[...] SWMSubsequent threads should then reslurp these modules back in on SWMtheir start up. SWM[...] SWMeach thread needs to reuse the original modules upon creation. SWM[...] SWMThis, of course, could lead to massive program bloat SWM This is a non-starter for me. Right now, I am working on apps that may SWM create 10 threads per *second*. I cannot possibly get the performance SWM I need if every thread has to recompile all its own modules. SWM We could either discuss alternate approaches for RFC1, or I could SWM submit a new RFC for a thread architecture that gives me the SWM performance I want. -- Chaim FrenkelNonlinear Knowledge, Inc. [EMAIL PROTECTED] +1-718-236-0183