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>