如何限制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-&gt;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-&gt;list() 返回一个列表,您可以比使用循环更轻松地捕获长度...比如$totalThreads = scalar(threads-&gt;list());,不是吗? 好吧,这是一个错字,我有threads->lists()而不是threads->list(),但现在我运行我的$totalThreads; foreach 我的 $thr (threads->list()) $totalThreads++; 打印“线程活跃:”。 $totalThreads 。 "\n";我得到的是:在我打印的行的连接(。)中使用未初始化的值 @jonathan,如果我使用 scalar() 方式,我会收到相同的消息:当我尝试打印计数时,在连接 (.) 中使用未初始化的值 @Jonathan Leffler,不,要捕获列表的长度,您必须使用我使用的技巧。虽然,thread-&gt;list 应该返回标量上下文中的线程数。 OP 必须有旧版本的 threads.pm。

以上是关于如何限制perl中的最大并行线程数的主要内容,如果未能解决你的问题,请参考以下文章

使用 Task.Run() 时如何限制最大线程数?

多线程之最大并行数

Linux最大线程数限制及当前线程数查询

windows一个进程中的最大线程数与哪些因素有关

linux线程数限制与zabbix监控

IIS 之 连接数并发连接数最大并发工作线程数队列长度最大工作进程数