Path: news.cs.hut.fi!news.funet.fi!news.eunet.fi!EU.net!howland.erols.net!feed1.news.erols.com!uunet!in1.uu.net!crusty.teleport.com!nntp0.teleport.com!usenet
From: [email protected] (Edward Walker)
Newsgroups: comp.lang.perl.announce,comp.lang.perl.misc
Subject: Perl-PVM version 1.1
Followup-To: comp.lang.perl.misc
Date: 15 Oct 1996 17:43:38 GMT
Organization: National University of Singapore
Lines: 526
Approved: [email protected] (comp.lang.perl.announce)
Message-ID: <[email protected]>
NNTP-Posting-Host: gadget.cscaper.com
X-Disclaimer: The "Approved" header verifies header information for article transmission and does not imply approval of content.
Xref: news.cs.hut.fi comp.lang.perl.announce:451 comp.lang.perl.misc:49687

Hi,

       Version 1.1 of Perl-PVM is now available.
This is a perl extension for PVM using dynamic loading.
PVM allows you to write parallel applications over
a heterogenous network of computers.

The differences with 1.0 are as follows:

1, Parallel::Pvm::spawn now accepts argv argument

2, Parallel::Pvm::notify accepts "cnt" argument
  for PvmHostAdd

3, Parallel::Pvm::recv_notify correctly receives
  list of host tids for PvmHostAdd notification

4, Some internal buffering optimization.

(1--3 was contributed by Rob Torop. Many thanks
to him!)

You may obtain a copy from my web page

       http://www.nsrc.nus.sg/STAFF/edward/Pvm.html

If you have problems obtaining a copy, get in touch with
me.

I've included a patch file below if you wish to apply
the patch yourself.

Enjoy! And may the force be with you.

- ed
---------------------------------------------------------
Dr Edward Walker
National Supercomputing Research Centre
81, Science Park Drive
#04-03, The Chadwick
Singapore 0511

Email: [email protected]
Web: http://www.nsrc.nus.sg/STAFF/edward

----------------Cut here: 1.0_2_1.1_patch----------------------
*** Pvm.xs
--- Pvm.xs
***************
*** 17,28 ****

 #define MAXPROCS      100
 #define MAXHOSTS      100
! #define MAXSTR                200000

 #define STRING          1
 #define INTEGER         2
 #define DOUBLE          3

 static SV *recvf_callback = (SV *)NULL;
 static int (*olmatch)();

--- 17,29 ----

 #define MAXPROCS      100
 #define MAXHOSTS      100
! #define MAXSTR                100000

 #define STRING          1
 #define INTEGER         2
 #define DOUBLE          3

+ static char g_buffer[MAXSTR];
 static SV *recvf_callback = (SV *)NULL;
 static int (*olmatch)();

***************
*** 79,85 ****
 {
 int cnt=0;

!    cnt = strlen(str);
    /* add 1 for the byte holding the '\0' */
    return cnt+1;
 }
--- 80,88 ----
 {
 int cnt=0;

!    while( str[cnt] != '\0' ){
!       cnt++;
!    }
    /* add 1 for the byte holding the '\0' */
    return cnt+1;
 }
***************
*** 100,105 ****
--- 103,115 ----
                 return STRING;
              }
         }
+         /* else{
+              if ( could_be_double ){
+                 if ( str[i] != '0' ){
+                    must_be_double = 1;
+                 }
+              }
+         } */
         i++;
     }
     if ( could_be_double ) return DOUBLE;
***************
*** 109,131 ****
 static char *
 buffer_string( char *str, int new_flag )
 {
! static int bufsize;
! static char *buf ;

    if ( new_flag ){
!       bufsize = 1;
!       free(buf);
!       buf = (char *)malloc((strlen(str)+1)*sizeof(char));
!       buf[0] = '\0';
!       bufsize = (strlen(str)+1)*sizeof(char);
!       sprintf(buf,"%s", str );
    }else{
-       bufsize += (strlen(str)+1)*sizeof(char);
-       buf = (char *)realloc(buf,bufsize);
       /* use vertical tab as token separator */
!       sprintf(buf,"%s\v%s",buf, str );
    }
!    return buf ;
 }

 /*****/
--- 119,140 ----
 static char *
 buffer_string( char *str, int new_flag )
 {
! static int cnt;
! int i;

    if ( new_flag ){
!       cnt=0;
!       for (i=0;str[i] && cnt<MAXSTR-1;i++) g_buffer[cnt++] = str[i];
!       if (cnt == MAXSTR-1) croak("Warning: message truncated. Try increasing MAXSTR");
!       g_buffer[cnt] = '\0';
    }else{
       /* use vertical tab as token separator */
!       g_buffer[cnt++] = '\v';
!       for (i=0;str[i] && cnt<MAXSTR-1;i++) g_buffer[cnt++] = str[i];
!       if (cnt == MAXSTR-1) croak("Warning: message truncated. Try increasing MAXSTR");
!       g_buffer[cnt] = '\0';
    }
!    return g_buffer;
 }

 /*****/
***************
*** 684,705 ****
       int             arg

 void
! spawn(task,ntask,flag=PvmTaskDefault,where="")
!       char *  task
!       int     ntask
!       int     flag
!       char *  where
!       PROTOTYPE: $$;$$
       PREINIT:
!         int tids[MAXPROCS];
       int info;
!         int i;
       PPCODE:
!       info = pvm_spawn(task,0,flag,where,ntask,tids);
       XPUSHs(sv_2mortal(newSViv(info)));
       for (i=0;i<info;i++){
          XPUSHs(sv_2mortal(newSViv(tids[i])));
       }

 int
 initsend(flag=PvmDataDefault)
--- 693,741 ----
       int             arg

 void
! spawn(task,ntask,flag=PvmTaskDefault,where="",argvRef=0)
!       char *  task
!       int     ntask
!       int     flag
!       char *  where
!       SV *    argvRef
!       PROTOTYPE: $$;$$$
       PREINIT:
!       int tids[MAXPROCS];
       int info;
!       int i;
!       char ** argv = (char **)0;
       PPCODE:
!
!       if (argvRef)
!       {
!           int   argc;
!           AV *  av;
!           SV ** a;
!
!           if (!SvROK(argvRef))
!               croak("Parallel::Pvm::spawn - non-reference passed for argv");
!
!           av = (AV *) SvRV( argvRef );
!           argc = av_len( av ) + 1;        /* number of elts in vector */
!           Newz( 0, argv, argc+1, char *); /* last one will be NULL */
!
!           for (i = 0; i < argc; i++)
!           {
!              if ( a = av_fetch( av, i, 0) )
!                 argv[i] = (char *) SvPV( *a, na );
!           }
!       }
!
!       info = pvm_spawn(task,argv,flag,where,ntask,tids);
!
!       Safefree( argv ); /* no harm done if argv is NULL */
!
       XPUSHs(sv_2mortal(newSViv(info)));
       for (i=0;i<info;i++){
          XPUSHs(sv_2mortal(newSViv(tids[i])));
       }
+

 int
 initsend(flag=PvmDataDefault)
***************
*** 729,746 ****
       int i;
       char *str, *po;
       CODE:
       for(i=2;i<items;i++){
!          po = (char *)SvPV(ST(i),na);
!            if ( i == 2 ) {
!               str = buffer_string(po,1);
!            } else{
!               str = buffer_string(po,0);
!            }
       }
-       if ( items == 2 ){
-          str = (char *)malloc(sizeof(char));
-          str[0] = '\0';
-       }
       RETVAL = pvm_psend(tid,tag,str,string_byte_cnt(str),PVM_BYTE);
       OUTPUT:
       RETVAL
--- 765,780 ----
       int i;
       char *str, *po;
       CODE:
+       if ( items == 2 )
+          croak("Usage: Parallel::Pvm::pack(@argv)");
       for(i=2;i<items;i++){
!           po = (char *)SvPV(ST(i),na);
!             if ( i == 2 ) {
!                str = buffer_string(po,1);
!             } else{
!                str = buffer_string(po,0);
!             }
       }
       RETVAL = pvm_psend(tid,tag,str,string_byte_cnt(str),PVM_BYTE);
       OUTPUT:
       RETVAL
***************
*** 878,895 ****
       int i;
       char *str, *po;
       CODE:
         for (i=0;i<items;i++){
!          po = (char *)SvPV(ST(i),na);
!            if ( i == 0 ) {
               str = buffer_string(po,1);
!            } else{
               str = buffer_string(po,0);
!            }
       }
-       if ( items <= 0 ){
-          str = (char *)malloc(sizeof(char));
-          str[0] ='\0';
-       }
         RETVAL = pvm_pkstr(str);
         OUTPUT:
       RETVAL
--- 912,927 ----
       int i;
       char *str, *po;
       CODE:
+       if ( items <= 0 )
+          croak("Usage: Parallel::Pvm::pack(@argv)");
         for (i=0;i<items;i++){
!           po = (char *)SvPV(ST(i),na);
!             if ( i == 0 ) {
               str = buffer_string(po,1);
!             } else{
               str = buffer_string(po,0);
!             }
       }
         RETVAL = pvm_pkstr(str);
         OUTPUT:
       RETVAL
***************
*** 1046,1051 ****
--- 1078,1088 ----
         for (i=0;i<items;i++){
           XPUSHs(sv_2mortal(newSViv(infos[i])));
       }
+       /*
+         for (i=0;i<items;i++){
+           free(hosts[i]);
+       }
+       */

 void
 bufinfo(bufid)
***************
*** 1205,1244 ****

 int
 notify(what,tag,...)
!       int     what
!       int     tag
       PROTOTYPE: $$;@
       PREINIT:
!       int i, tids[MAXPROCS];
       CODE:
       switch(what){
          case PvmTaskExit:
          case PvmHostDelete:
!               if ( items < 3 )
!                  croak("Usage: Parallel::Pvm::pvm_notify(what,tag,tid_list");
!               for (i=2;i<items;i++){
!                  tids[i-2] = SvIV(ST(i));
!               }
!               RETVAL = pvm_notify(what,tag,items-2,tids);
!               break;
          case PvmHostAdd:
!               RETVAL = pvm_notify(what,tag,0,tids);
!               break;
       }
       OUTPUT:
       RETVAL

 int
! recv_notify()
!       PROTOTYPE:
       PREINIT:
!       int id;
!       CODE:
       pvm_recv(-1,-1);
!       pvm_upkint(&id,1,1);
!       RETVAL = id;
!       OUTPUT:
!       RETVAL

 void
 hostsync(hst)
--- 1242,1298 ----

 int
 notify(what,tag,...)
!       int     what
!       int     tag
       PROTOTYPE: $$;@
       PREINIT:
!       int i, cnt, tids[MAXPROCS];
       CODE:
       switch(what){
          case PvmTaskExit:
          case PvmHostDelete:
!               if ( items < 3 )
!                  croak("Usage: Parallel::Pvm::pvm_notify(what,tag,tid_list");
!               for (i=2;i<items;i++){
!                  tids[i-2] = SvIV(ST(i));
!               }
!               RETVAL = pvm_notify(what,tag,items-2,tids);
!               break;
          case PvmHostAdd:
!               if ( items < 2 )
!                 croak("Usage:  Parallel::Pvm::pvm_notify(PvmHostAdd,tag [,cnt]");
!               if (2 == items )
!               cnt = -1;
!               else
!                  cnt = SvIV(ST(2));
!               RETVAL = pvm_notify(what,tag, cnt, (int *)0 );
!               break;
       }
       OUTPUT:
       RETVAL

 int
! recv_notify(what)
!       int what
!       PROTOTYPE: $
       PREINIT:
!       int id,i,cnt;
!       int tids[MAXPROCS];
!       PPCODE:
       pvm_recv(-1,-1);
!       switch (what )
!       {
!          case PvmTaskExit:
!          case PvmHostDelete:
!               pvm_upkint(&id,1,1);
!               XPUSHs( sv_2mortal(newSViv(id)) );
!               break;
!          case PvmHostAdd:
!               pvm_upkint( &cnt, 1, 1 );
!               pvm_upkint( tids, cnt, 1 );
!          for ( i=0; i < cnt; i++)
!              XPUSHs(sv_2mortal(newSViv(tids[i])));
!       }

 void
 hostsync(hst)
*** Pvm.pm
--- Pvm.pm
***************
*** 93,99 ****
       PvmTraceTid
 );

! $VERSION = '1.0';

 sub AUTOLOAD {
     # This AUTOLOAD is used to 'autoload' constants from the constant()
--- 93,99 ----
       PvmTraceTid
 );

! $VERSION = '1.1';

 sub AUTOLOAD {
     # This AUTOLOAD is used to 'autoload' constants from the constant()
***************
*** 348,354 ****
 For more sophisticated users, B<Parallel::Pvm::spawn> may be given additional
 argument parameters to control how/where you want a task to be spawned.
 For example, you can specifically spawn B<client> in the internet
! host <onyx.nsrc.nus.sg> by calling

       Parallel::Pvm::spawn("client",1,PvmTaskHost,"onyx.nsrc.nus.sg");

--- 348,354 ----
 For more sophisticated users, B<Parallel::Pvm::spawn> may be given additional
 argument parameters to control how/where you want a task to be spawned.
 For example, you can specifically spawn B<client> in the internet
! host B<onyx.nsrc.nus.sg> by calling

       Parallel::Pvm::spawn("client",1,PvmTaskHost,"onyx.nsrc.nus.sg");

***************
*** 357,362 ****
--- 357,367 ----

       Parallel::Pvm::spawn("client",4,PvmTaskArch,"RS6K");

+ Also, if the spawned remote executable requires an argument B<argv>,
+ you can supply this by calling
+
+       Parallel::Pvm::spawn("client",4,PvmTaskArch,"RS6K",argv);
+
 Note that tasks which have been spawned by using B<Parallel::Pvm::spawn>
 do not need to be explicitly enrolled into the pvm system.

***************
*** 662,667 ****
--- 667,678 ----

       $info = Parallel::Pvm::notify(PvmHostDelete,999,$host_list);

+       # turns on notification for new host
+       $info = Parallel::Pvm::notify(PvmHostAdd);
+
+         # turns off notification for new host
+       $info = Parallel::Pvm::notify(PvmHostAdd,0);
+
 =item B<Parallel::Pvm::nrecv>

 Nonblocking receive.  Eg.
***************
*** 753,762 ****
 Receives the notification message initiated by B<Parallel::Pvm::notify>.  This
 should be preceded by a B<Parallel::Pvm::probe>.  Eg.

       if ( Parallel::Pvm::probe(-1,$notify_tag) ){
!               $message = Parallel::Pvm::recv_notify ;
       }

 =item B<Parallel::Pvm::recvf_old>

 Resets the comparison function for accepting messages to the
--- 764,777 ----
 Receives the notification message initiated by B<Parallel::Pvm::notify>.  This
 should be preceded by a B<Parallel::Pvm::probe>.  Eg.

+       # for PvmTaskExit and PvmHostDelete notification
       if ( Parallel::Pvm::probe(-1,$notify_tag) ){
!               $message = Parallel::Pvm::recv_notify(PvmTaskExit) ;
       }

+       # for PvmHostAdd notification
+       @htid_list = Parallel::Pvm::recv_notify(PvmHostAdd);
+
 =item B<Parallel::Pvm::recvf_old>

 Resets the comparison function for accepting messages to the
***************
*** 829,834 ****
--- 844,851 ----
       ($ntask,@tid_list) = Parallel::Pvm::spawn("compute.pl",4);

       ($ntask,@tid_list) = Parallel::Pvm::spawn("compute.pl",4,PvmTaskHost,"onyx");
+
+       ($ntask,@tid_list) = Parallel::Pvm::spawn("compute.pl",4,PvmTaskHost,"onyx",argv);

 =item B<Parallel::Pvm::tasks>