如何限制perl中的最大并行线程数
Posted
技术标签:
【中文标题】如何限制perl中的最大并行线程数【英文标题】:How to limit the max number of parallel threads in perl 【发布时间】:2012-07-21 23:00:41 【问题描述】:我有一个程序 (Perl),它启动大量线程(每个线程负责基于数据处理创建图形)。 我开始使用的每个线程:
my @threads //list to store threads that have been launched
push @threads,threads->create(\mySubName,params...);
线程正确触发,但过了一段时间,在我打开其中几个之后,Perl 解释器崩溃(我认为它与内存有关?)。所以我的解决方案是限制我一次打开的线程数,我选择了 15 个。我想在每个创建行之前添加一个子程序,以检查是否可以在我等待时触发下一个线程或执行睡眠一个完成。我就是这样做的。
sub checkThreads
my $addThread = 0;
until($addThread)
my $totalThreads = 0;
foreach my $task (@threads)
if($task->is_running())$totalThreads++;
if($totalThreads <= 15 )
print "Ok to add new thread, carry on!\n";
$addthread = 1;
else
print "Waiting for $totalThreads threads to fire next one...\n";
sleep 2;
所以每次我想创建一个新线程时,我都会调用
&checkThreads;
当我等待一些线程清理时,这会造成延迟。 问题是当我调用那个子时,我点击了我检查的那一行:
$task->is_running()
程序退出并停止运行,没有任何错误或警告。我只想要一个计算正在运行的线程来限制它们的子。
我怎样才能成功地执行这个计数?
我尝试过的其他事情正在评估以下行:
scalar(threads->list());
但这给了我一个奇怪的价值,就像我认为它是一个无福的参考:
threads=SCALAR(0x80fea8c)
【问题讨论】:
顺便说一句,那是(a的字符串化)blessed ref 非常非常 BTW - 请记住 perl 中的线程与其他编程语言中的线程不同 - 它们非常消耗资源,因为每个线程都有所有变量的副本。它们在某些情况下仍然有用,但在我必须进行并行化的每种情况下,分叉的效果要好得多。它与您的问题没有直接关系,我只是想告诉您。 :) 什么版本的 Perl?什么版本的线程?您的线程是否已分离(可能在 mySubName 中自行分离)? 【参考方案1】:Thread::Semaphore 提供了一个counting semaphore 来限制并发:
my $sem = Thread::Semaphore->new(15); # max 15 threads
my @threads = map
# request a thread slot, waiting if none are available:
$sem->down;
threads->create(\&mySubName, @params)
0..100;
$_->join for @threads;
在你的函数中:
sub mySubName
do_stuff();
# release slot:
$sem->up;
【讨论】:
Richard 我认为这是可行的,我在脚本中实现了它,看起来它确实在控制我的最大线程数,有没有办法可以查看信号量的当前值?因为我运行了它,但是在运行了一段时间之后,我的脚本就挂在了$sem->down;
我将线程数降低到 5 并且它工作正常,仍然有 7 看起来程序在某些时候停止,不知道为什么。感谢您的提示!
您可以通过取消引用对象本身来获取信号量的货币值,这只是对最大值(默认为 1)减去其计数的祝福引用。因此,要获取当前未完成线程的数量,请评估 $max - $$sem
。
我们可以使用共享标量变量来计算正在运行的线程数吗?我的意思是在 mySubName() 的第一行,我们将计数器增加 1 并在返回时将其减少 1。【参考方案2】:
查看文档,
my $count = threads->list();
应该有效,与您所说的相反。 you 正在使用的线程版本的文档是怎么说的?好吧,您可以使用以下解决方法。
my $count = () = threads->list();
【讨论】:
我使用了 Richard 提出的信号量方法,但我尝试了一下,它确实给出了列表中实际线程的数量,谢谢!【参考方案3】:man perlthrtut
What Threads Are Running?
"threads->list()" returns a list of thread objects, one for each thread
that's currently running and not detached. Handy for a number of
换句话说,找出threads->list()返回的列表中有多少项目,然后你就知道了。
您可能想调查 Thread::Pool 或其他 cpan 软件包,看看是否其他人已经为您完成了繁重的工作。
【讨论】:
当我尝试使用threads->list()时,我得到以下结果:Can't locate auto/threads/lists.al in @INC (@INC contains: C:\Program Files (x86)\ActiveState Komodo 3.5\lib\support\dbgp\perllib C:\Program Files (x86)\ActiveState Komodo 3.5\lib\support\dbgp\perllib C:/Perl/lib C:/Perl/site/lib 。 ) 在 C:\path\main3.pl 第 508 行 如果threads->list()
返回一个列表,您可以比使用循环更轻松地捕获长度...比如$totalThreads = scalar(threads->list());
,不是吗?
好吧,这是一个错字,我有threads->lists()而不是threads->list(),但现在我运行我的$totalThreads; foreach 我的 $thr (threads->list()) $totalThreads++; 打印“线程活跃:”。 $totalThreads 。 "\n";我得到的是:在我打印的行的连接(。)中使用未初始化的值
@jonathan,如果我使用 scalar() 方式,我会收到相同的消息:当我尝试打印计数时,在连接 (.) 中使用未初始化的值
@Jonathan Leffler,不,要捕获列表的长度,您必须使用我使用的技巧。虽然,thread->list
应该返回标量上下文中的线程数。 OP 必须有旧版本的 threads.pm。以上是关于如何限制perl中的最大并行线程数的主要内容,如果未能解决你的问题,请参考以下文章