Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 将子例程引用传递给perl线程_Multithreading_Perl_Reference_Subroutine - Fatal编程技术网

Multithreading 将子例程引用传递给perl线程

Multithreading 将子例程引用传递给perl线程,multithreading,perl,reference,subroutine,Multithreading,Perl,Reference,Subroutine,我试图将子例程引用传递给perl线程,以实现threadMap子例程。我所处的环境是,我必须“滚动我自己的”大部分事情;安装新的perl包不是一个选项 另外,我运行的是perl版本5.10。在我的工作环境中,perl>5.10的版本不可用 我可以毫无困难地传递子程序引用。但是,一旦我尝试将子例程引用传递给线程,该线程似乎无法理解它 下面是我建议的threadMap子例程,我相信它的注释对于感兴趣的问题回答者来说是足够解释的 #input: hash with keys L (listref),

我试图将子例程引用传递给perl线程,以实现threadMap子例程。我所处的环境是,我必须“滚动我自己的”大部分事情;安装新的perl包不是一个选项

另外,我运行的是perl版本5.10。在我的工作环境中,perl>5.10的版本不可用

我可以毫无困难地传递子程序引用。但是,一旦我尝试将子例程引用传递给线程,该线程似乎无法理解它

下面是我建议的threadMap子例程,我相信它的注释对于感兴趣的问题回答者来说是足够解释的

#input: hash with keys L (listref), f (function which can apply to each element of L), and optionally nThreads
#default for nThreads is 50
#divides L into sublists for each thread, then kicks off threads
#each thread applies f to each element of the sublist
#and then returns the result of $f on each item
#output: map{ &$f($_) } @{$L}, but done threadily
sub threadMap{
  my %arg = @_;
  my ($L,$f,$nThr) = ($arg{L},$arg{f},$arg{nThreads});
  my $MAXTHREADS = 50;
  if(not defined $nThr or $nThr > $MAXTHREADS){
   $nThr = $MAXTHREADS;
  }

  &log(1,"threadMap: I have f $f");

  my @threadLists = &makeSublistsForThreads($L,$nThr);
  #in the event that L is less than $nThr, we reduce the number of threads
  $nThr = scalar(@threadLists);
  my @threads; 
  my @ret;
  for(0 .. $nThr-1){
  #invoke the threads in list context
  #    push @threads, threads->create({'context' => 'list'}, sub{ my ($L,$f) = @_; print "I have L <@$L> and f $f\n"; return (map{ &f($_) } @{$L}) }, ($threadLists[$_],$f) );
  push @threads, threads->create({'context' => 'list'}, sub{ my ($L) = @_; print "I have L <@$L> and f $f\n"; return (map{ &f($_) } @{$L}) }, ($threadLists[$_]) );
  }
  for(@threads){
  #each thread returns its items, so we get them back in order
      push @ret, $_->join();
  }
  return @ret;
}
#输入:使用键L(listref)、f(可应用于L的每个元素的函数)和可选的nThreads进行散列
#nThreads的默认值为50
#将L划分为每个线程的子列表,然后启动线程
#每个线程将f应用于子列表的每个元素
#然后返回每个项目的$f结果
#输出:映射{&$f($)}@{$L},但以线程方式完成
子线程映射{
我的%arg=@;
my($L,$f,$nThr)=($arg{L},$arg{f},$arg{nThreads});
我的$MAXTHREADS=50;
if(未定义$nThr或$nThr>$MAXTHREADS){
$nThr=$MAXTHREADS;
}
&日志(1,“线程映射:我有f$f”);
my@threadLists=&makeSublistsForThreads($L,$nThr);
#如果L小于$nThr,我们将减少线程的数量
$nThr=标量(@threadLists);
我的@threads;
我的@ret;
对于(0..$nThr-1){
#在列表上下文中调用线程
#推送@threads,threads->create({'context'=>'list'},sub{my($L,$f)=@;打印“我有L和f$f\n”;返回(map{&f($)}@{$L},($threadLists[$\uz],$f));
推送@threads,threads->create({'context'=>'list'},sub{my($L)=@;打印“我有L和f$f\n”;返回(map{&f($)}@{$L},($threadLists[$));
}
对于(@threads){
#每个线程都返回它的项目,所以我们将它们按顺序返回
按@ret,$\->join();
}
返回@ret;
}
当我运行此脚本时,会出现一个名为“foo”的脚本,该脚本大致包含以下内容:

my @L = (1 .. 5); 
my $f = sub{ my ($i) = @_; return 100*$i; };

print "I have f $f\n";

@out = &threadMap("L"=>\@L,"f"=>$f);
&log(1,"I had input <@L> and output <@out>");

my @realOut = map{ &$f($_) } @L; 
&log(1,"Output should be <@realOut>");
my@L=(1..5);
my$f=sub{my($i)=@;return 100*$i;};
打印“我有f$f\n”;
@out=&threadMap(“L”=>\@L,“f”=>$f);
&日志(1,“我有输入和输出”);
my@realOut=map{&$f($)}@L;
&日志(1,“输出应为”);
我得到这个输出:

我有f代码(0xbf3530)

2013年7月17日星期三10:27:49:线程映射:我有f代码(0xbf3530)

我有L和f代码(0x110f100)

线程1异常终止:调用了未定义的子例程&main::f 在/u/jamie/perl/jdPerlLib.pl第6037行

我有L和f代码(0x16b3df0)

线程2异常终止:调用了未定义的子例程&main::f 在/u/jamie/perl/jdPerlLib.pl第6037行

我有L和f代码(0x1a7d7b0)

线程3异常终止:调用了未定义的子例程&main::f 在/u/jamie/perl/jdPerlLib.pl第6037行

我有L和f代码(0x1fbb600)

线程4异常终止:调用了未定义的子例程&main::f 在/u/jamie/perl/jdPerlLib.pl第6037行

我有L和f代码(0x7fd5240b78c0)

线程5异常终止:调用了未定义的子例程&main::f 在/u/jamie/perl/jdPerlLib.pl第6037行

2013年7月17日星期三10:27:49:我有输入和输出

这告诉我,从foo到threadMap子例程的顶部,函数引用是常量,但一旦它被传递到线程,它就会发生更改并失控。为什么会这样?我可以避免吗

请注意,这两种方法都失败

  #invoke the threads in list context
  #    push @threads, threads->create({'context' => 'list'}, sub{ my ($L,$f) = @_; print "I have L <@$L> and f $f\n"; return (map{ &f($_) } @{$L}) }, ($threadLists[$_],$f) );
  push @threads, threads->create({'context' => 'list'}, sub{ my ($L) = @_; print "I have L <@$L> and f $f\n"; return (map{ &f($_) } @{$L}) }, ($threadLists[$_]) );
#在列表上下文中调用线程
#推送@threads,threads->create({'context'=>'list'},sub{my($L,$f)=@;打印“我有L和f$f\n”;返回(map{&f($)}@{$L},($threadLists[$\uz],$f));
推送@threads,threads->create({'context'=>'list'},sub{my($L)=@;打印“我有L和f$f\n”;返回(map{&f($)}@{$L},($threadLists[$));

#在列表上下文中调用线程
推送@threads,threads->create({'context'=>'list'},sub{my($L,$f)=@;打印“我有L和f$f\n”;返回(map{&f($)}@{$L},($threadLists[$\uz],$f));
#推送@threads,threads->create({'context'=>'list'},sub{my($L)=@;打印“我有L和f$f\n”;返回(map{&f($)}@{$L},($threadLists[$));


另外,由于这是我第一次发布stackoverflow,我的问题是否足够清楚,或者太/不够详细?

您正在调用threadMap中名为“f”的函数:

map{ &f($_) } ...
如错误消息所示,该函数不存在

您的意思是取消引用并调用CODEref:

map { $f->($_) } ...
在您的更新注释中,代码起作用,因为您确实在其中定义了一个名为“f”的子项

另一方面,您通常不应该使用符号和符号调用perl subs。这是Perl4中的保留语法,在Perl5中有非常特定的语义,当您只想调用sub时,几乎不需要这些语义


调用
&f
将禁用原型处理,并可以传递
@
——如果该行为对您来说似乎没有立即的用处,那么不要使用该功能<代码>&也用于表示子系统本身(例如,
my$coderef=\&f
defined&f
)和特殊的
goto&f
调用
&
还取消对code ref的引用,通常是为了调用它,但更明显的是,该操作是通过一个箭头和括号传递的:
$coderef->()

更新——如果我的测试程序'foo'具有以下内容,则它似乎可以工作:sub f{my($i)=@;return 100*$i;}my$f=\&f;这表明了一种可能的解释——perl会在某个地方创建匿名子例程引用的浅拷贝,如果它是对“真实”子例程的引用,它就不会在该地方创建匿名子例程引用?但我仍然不清楚细节…有什么“提示”(哈!)?皮尔克罗:谢谢你的详细回复。好眼力
map { $f->($_) } ...