develooper Front page | perl.perl5.porters | Postings from April 2021

Thread Next
From:
B. Estrade
Date:
April 9, 2021 05:53
Subject:

Message ID:
6f86c41e-966f-0260-3842-a955c554122d@cpanel.net


On 4/8/21 11:50 PM, Yuki Kimoto wrote:
> B. Estrade
> 
> I don't yet understand what you want.

You and me both. What I *want* and what I think we have to do to get 
there are two vastly different things.

For now, I want all of us to think "thread safety" and "SMP" in 
everything we do. Not in a design sense, in the unconsiousness sense; so 
it imbues itself in every aspect of any work and thinking done in the 
name of perl/Perl.

If you ask me right now; in 2024, I'd like to be able to do something as 
simple as this as a single OS process, but utilizing "light weight" OS 
threads (e.g., pthreads):

   #!/usr/bin/env perl
   use strict;
   use warnings;
   use v12;

   # 'traditional perl code'
   #...
   #

   my_r $mailbox_rref = [];
   map_r(8) {
     local $thread_id = tid();
     $mailbox_rref->[$thread_id] = qq{Hello from thread #$thread_id};
   }
   foreach my $msg (@$mailbox_ref) {
     say $msg;
   }

Output:

Hello from thread # 0
Hello from thread # 1
Hello from thread # 2
Hello from thread # 3
Hello from thread # 4
Hello from thread # 5
Hello from thread # 6
Hello from thread # 7

Another example,

   #!/usr/bin/env perl
   use strict;
   use warnings;
   use v12;

   # 'traditional perl code'
   #...
   #

   sub state_var_update {
     state $ret = 0;
     return ++$ret;
   }

   sub atomic_var_update {
     atomic $ret = 0;   # like 'state' but actions upon it are atomic
     return ++$ret;     # atomic nature forces unordered serialization
   }

   sub now_serving {
     state $now_serving = 0;
     my $ticket = shift;
     return undef if $ticket != $now_serving;
     return q{You've been served a nice warm rye loaf!};
   }

   my $num_threads = 8;
   map_r($num_threads) {
     local $thread_id = tid();
     local $bakery_ticket = atomic_var_update; # threads race
     # threads do stuff
     # .. and more stuff
     # ... and maybe more stuff

     # busy wait
     do {
       local $ihazbeenserved = now_serving($bakery_ticket);
     } while(not $ihazbeenserved);

     # "safely" print to STDOUT without clobbering (could use regular
     # printf and risk messages overlapping)
     printf_r("Yay! I, thread %d, now has my %s", $tid, $ihazbeenserved);
   }

   # had to google for the following
   format STUDENT =
   ===================================
   @<<<<<<<<<<<<<<<<<<<< @<<
   $name $age
   @#####.##
   $fee
   ===================================
   .

   select(STDOUT);
   $~ = STUDENT;

   @n = ("Deepak", "Rajat", "Vikrant");
   @a  = (18, 16, 14);
   @s = (2000.00, 2500.00, 4000.000);

   $i = 0;
   foreach (@n)
   {
      $name = $_;
      $age = $a[$i];
      $fee = $s[$i++];
      write;
   }

> 
> If you want to call OpenMP easily, I'm also trying in my SPVM module.
> 
> https://github.com/yuki-kimoto/SPVM/tree/master/examples/native/openmp
> 

I saw your module come through on metacpan under "recent" and it looked 
very interesting. I'll look deeper into it.

> Perl already has Inline::C/XS/FFIs modules. SPVM is another way to bind 
> C libraries.
> 
> More example
> 
> -cuda
> -Eigen
> -GSL
> -OpenCV
> -zlib
> 
> https://github.com/yuki-kimoto/SPVM/tree/master/examples/native

Yes, very nice. I will look at it. Whereas what I want and what I am 
playing with are vastly different, I am also very interested in FFI type 
support for leveraging SMP, GPUs (not really myself but it's important), 
etc.

My two examples above point to a few things:

0. '_r' indicates "thread safe" - this is an old tradition from IBM; 
google it, it's a thing; I promise.

1. atomic data types (thread safe) that in addition to providing for 
"safe" updates (one thread at a time), can serve as barriers 
(serialization points)

2. a map_r (or similar) construct that provides a threaded environment; 
yes, I know 'map_r' also implies a lot of things related to the existing 
'map'; that'd be cool to, but it seemed like a more apt name that what I 
had originally, 'fork_r'.

3. ability for threads to call all subs "unsafely" (race condition); but 
with the judicious use of atomics can provide barriers to keep things

4. thread safe analogs to things like printf (see inline comment in code 
above)

5. the use of 'format' was just because I've never used it before and 
had just googled it to see what it's all about :)

I quite enjoyed coming up these examples, and I might even as an 
exercise try to come up with many more so that when asked - "what do you 
mean" or "show me an example" of what you are thinking, I can point to that.

Even after this thought exercise, I am beginning to see how a mix of the 
following might point us in the right direction (and through the 
minefield that is the perl runtime):

* a threaded block (above it's map_r, could be fork_r, or just spawner, etc)
* thread safe forms of:
   - scalar reference; declared with 'my_r', array ref or hash ref on 
the other end is assumed to be a 'thread safe' anonymous array or hash
   - arrays - slots can be updated in a threaded environment (threads 
can be unsafe and simultaneously update an element; but that's the risk 
with SMP)
   - hash - same concept as 'thread safe' array, but hash
   - atomic - an actual scalar value that can be safely updated; it's 
primary use is as a synchronization point; default access is "unordered" 
meaning first thread there wins, then all others line up 
non-deterministically; there should probably be an way to 'order' 
threads based on tid() in some efficient way

Other thoughts,

* sub_r: thread safe form of 'sub' that has a serialization effect as 
well, except it is run by only one thread at a time (user is allowed to 
do unsafe things using perl's traditional scoping rules) - akin to an 
OpenMP 'critical' section.

Anyway, thanks for asking. I'll think more about it and see if I can 
flesh it out more.

Note, I am not going for any particular concurrency model. I am going 
for "what does SMP look like in perl5". I think I have a good idea, and 
the '_r' stuff and atomic(s) are merely language additions to get around 
affecting "serial" perl. (no I don't want a perl_r; just for the record).

Brett

> 
> 2021年4月9日(金) 0:05 B. Estrade <brett@cpanel.net 
> <mailto:brett@cpanel.net>>:
> 
>     Thank you, appreciate the reply. To avoid collision with the other
>     thread, I update the subject.
> 
>     So I suppose this cuts to the heart of the matter. It's fair, I
>     believe,
>     that "top level 'threading'" is not something that can be reasonable
>     supported in the perl runtime (and to be fair, other scripting
>     languages
>     also struggle greatly with this).
> 
>     The question, then goes to: how do we facilitate access to the native
>     platform's SMP? Perhaps the answer is, as always, "it depends."
> 
>     I will continue to pound my head on this, something will shake
>     loose. In
>     the meantime, as proof that I am vested in seeing some interesting
>     options shake loose, I have offered a module on CPAN called
>     OpenMP::Environment.
> 
>     It only provides programmatic manipulation of the environmental
>     variables that OpenMP programs care about; but it is a necessary step
>     for me to investigate and gain some intuition about what is possible
>     and
>     what looks "right".
> 
>     Currently I am thinking a SIMD (single instruction, multiple data)
>     approach is the most accessible. This doesn't really get at what is
>     ideal (in my mind), but at least provides a path forward by creating
>     threaded libraries made available via Inline::C/XS/FFIs - and even
>     leveraging these via a tie interface. And if the direction of providing
>     SIMD "data types" is truly the best direction, PDL seems like a really
>     good target for that.
> 
>     Thanks for all the feedback, will monitor the list/thread. I do ask
>     that
>     we keep the whole idea of threading "where and when feasible" (even in
>     language design considerations) is extremely important to Perl's long
>     term viability and as a driver of important capabilities. The idea of
>     using Perl to efficiently max out a large SMP machine for useful
>     work is
>     very exciting to me, and I think I am not the only one.
> 
>     Cheers,
>     Brett
> 
> 
>     On 4/8/21 3:42 AM, Konovalov, Vadim wrote:
>      >> Nicholas Clark <nick@ccl4.org <mailto:nick@ccl4.org>> wrote:
>      >>> On Wed, Apr 07, 2021 at 10:49:05AM -0500, B. Estrade wrote:
>      >>>
>      >>>> Here's some food for thought. When was was the last time
>     anyone had a
>      >>>> serious discussion of introducing smp thread safety into the
>     language? Or
>      >>>> easy access to atomics? These are, IMO, 2 very important and
>     serious things
>      >>>
>      >>> Retrofitting proper multicore concurrency to perl would imply
>     that it's
>      >>> possible at all.
>      >>>
>      >>> None of the comparable C-based dynamic languages have done it
>     (eg Python,
>      >>> Ruby)
>      >
>      > Both Python and Ruby are not a good place to learn on how
>     multiprocessing happens.
>      > There is much better place to learn from - Julia.
>      >
>      > Julia made interesting approach: syntax highly inspired by
>     Python, but correctly
>      > deals with multithreading. In a sense - this is much developed
>     Python with all missing
>      > features added into completely different language.
>      >
>      > Very interesting approach, and I suppose this is about what perl
>     community intended
>      > to implement when perl6 discussion have begun in 2000.
>      >
>      >
>      >
>      >>> Ruby's new experimental new threading is an actor model (I
>     believe) CPython
>      >>> is dogged by the GIL (all the threads you like, but if you're
>     CPU bound then
>      >>> you're making one core very toasty) The seem to be thinking
>     about going
>      >>> multicore by doing something like ithreads (using pickle to
>     pass data
>      >>> structures between MULITPLICITY-like interpreters) but that's
>     likely going
>      >>> to be as good as ithreads.
>      >
>      > It appears that reference counting + threading results in
>     considerable slow down
>      > and the solution to the problem is good GC.
>      > This was "proved" by GILectomy project, see any google video on
>     this or this
>      > nice summary https://news.ycombinator.com/item?id=11842779
>      >
>      > Perl history on threading (PERL5005THREADS and then ITHREADS
>     where 1st was
>      > deprecated and removed while 2nd was recently deprecated) gives
>     me think
>      > that no real multithreading/multicoring is actually possible on
>     language level.
>      > Developing into that direction now is just wasting of time.
>      >
>      > "async" is another story, which is Javascript way, where basic JS
>     engine V8 is single-threaded.
>      >
>      >
> 

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About