大家好~我使用多线程在 Perl 中编写了一个非常简单的代码。代码如下。
#!/bin/perl
use strict;
use threads;
use Benchmark qw(:hireswallclock);
my $starttime;
my $finishtime;
my $timespent;
my $num_of_threads = 1;
my $total_size = 10000000;
my $chunk_size = int($total_size / $num_of_threads);
if($total_size % $num_of_threads){
$chunk_size++;
}
my @threads = ();
$starttime = Benchmark->new;
for(my $i = 0; $i < $num_of_threads; $i++) {
my $thread = threads->new(\&search);
push (@threads, $thread);
}
foreach my $thread (@threads) {
$thread->join();
}
my $finishtime = Benchmark->new;
$timespent = timediff($finishtime, $starttime);
print "$num_of_threads threads used in ".timestr($timespent)."\nDone!\n";
sub search{
my $i = 0;
while($i < $chunk_size){
$i++;
}
return 1;
}
这段代码工作正常,因为当增加线程数时,它会运行得更快。
但是,当在中间添加额外的行时,将创建一个大数组,添加更多线程时代码将运行得更慢。带有附加行的代码如下所示。
#!/bin/perl
use strict;
use threads;
use Benchmark qw(:hireswallclock);
my $starttime;
my $finishtime;
my $timespent;
my $num_of_threads = 1;
my $total_size = 10000000;
my $chunk_size = int($total_size / $num_of_threads);
if($total_size % $num_of_threads){
$chunk_size++;
}
##########Additional codes##########
print "Preparing data...\n";
$starttime = Benchmark->new;
my @array = ();
for(my $i = 0; $i < $total_size; $i++){
my $rn = rand();
push(@array, $rn);
}
$finishtime = Benchmark->new;
$timespent = timediff($finishtime, $starttime);
print "Used ".timestr($timespent)."\n";
######################################
my @threads = ();
$starttime = Benchmark->new;
for(my $i = 0; $i < $num_of_threads; $i++) {
my $thread = threads->new(\&search);
push (@threads, $thread);
}
foreach my $thread (@threads) {
$thread->join();
}
my $finishtime = Benchmark->new;
$timespent = timediff($finishtime, $starttime);
print "$num_of_threads threads used in ".timestr($timespent)."\nDone!\n";
sub search{
my $i = 0;
while($i < $chunk_size){
$i++;
}
return 1;
}
我对 Perl 多线程中的这种行为感到很困惑。有谁知道这里可能出了什么问题吗?
谢谢!
最佳答案
您必须记住,当使用 ithreads(解释器线程)时,整个 Perl 解释器,包括代码和内存,都被克隆到新线程中。因此,要克隆的数据越多,所需的时间就越长。有一些方法可以控制克隆的内容;查看 threads
perldoc。
您应该尽可能少地执行操作,甚至在生成线程之前不要加载很多模块。
如果您确实有大量数据将被所有线程使用,请将其与threads::shared
共享。然后共享一个数据结构使用shared_clone()
。你不能简单地 share()
任何东西,除了一个简单的变量。该共享变量只能包含普通标量或其他共享引用。
如果您要使用或抽取该数据,请使用 Thread::Queue
模块将其设为队列。它会自动共享值并负责锁定。生成工作线程池后,使用 Thread::Semaphore
控制它们。这样他们就不会在你给他们任何事情之前终止。您还可以防止竞争条件。
https://metacpan.org/pod/threads::shared
HTH
关于multithreading - 当内存使用率变高时 Perl 多线程变慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66459184/