我编写了一个perl脚本,它多次启动一个程序,在for循环中使用不同的参数。该程序进行数值计算,并使用整个CPU,如果它可以得到一个。我有几个CPU可用,所以理想情况下,我想一次启动尽可能多的程序实例,因为有可用的CPU,但不是更多。由于可能正在运行其他进程,因此可用CPU的数量并不总是相同。
到目前为止,我所做的是:
#!/usr/bin/perl
use strict;
use warnings;
use IPC::Open2;
use Parallel::ForkManager;
my $program = "./program";
my($out, $in);
my $pid;
my $pm = new Parallel::ForkManager(44);
for my $x (0..100){
my $childpid = $pm->start and next;
$pid= open2($out, $in, $program);
print $in <<EOF;
#input involving $x
EOF
my $printstring = "";
while(<$out>){
if (/^\s*1\.000\s+(-\S+)D(\S+)\s*$/){
$printstring .= "$1e$2";
}
}
print $printstring, "\n";
waitpid( $pid, 0 );
$pm->finish;
}
$pm->wait_all_children;
print "\n\n END\n";
这显然包含一定数量的进程启动,从而可以使用固定数量的CPU,我不知道如何更改它以灵活地确定可用的CPU并相应地更改子进程数。任何想法如何做到这一点?
更新
为了清楚起见,这里的限制因素肯定是CPU时间而不是I / O的东西。
我调查了loadavg
,但我对它的输出感到困惑。
68.71 66.40 63.72 70/1106 19247
与此同时,top
显示
Tasks: 978 total, 23 running, 955 sleeping, 0 stopped, 0 zombie
Cpu(s): 2.1%us, 1.5%sy, 93.3%ni, 3.1%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
CPU的数量是48,所以我认为如果第四个数字(在这种情况下为70)大于48,我不应该再启动子进程,但根据顶部似乎有一些空闲CPU那里,虽然第四个数字是70。
答案 0 :(得分:2)
我打算建议采取稍微不同的方法 - 如何,而不是“扼杀”&#39;基于加载的活动进程数 - 为什么不使用SIGSTOP
和SIGCONT
。
Parallel::ForkManager
为您提供running_procs
方法,该方法返回PID列表。
当负载平均值过高时,您可以signal
到STOP
的那些人。{#1}}
你可以找到&#34;太高&#34;使用Sys::Info::CPU
(这也告诉你load
)或者 - 或许看看Number of processors/cores in command line
但从理论上讲 - 当负载过高时,发出&#39; SIGSTOP&#39;对你的一些子进程。他们应退出运行队列,并且可见但已暂停。
就平均负载而言 - 您会得到3个数字。 1m,5m和15m CPU负载。看看第一个,如果那个大于CPU的数量,你就会有争用。
答案 1 :(得分:1)
可能总会有进程弹跳,有些将使用比其他进程更多的CPU。我认为另一种方法是查看每个CPU使用其空闲百分比的繁忙程度。类似下面的代码片段就可以实现这个目标。然后,您可以设置一个阈值,以确定它是否超过某个空闲量。然后,您可以使用返回的数字来确定要启动的进程数量。这样的事情会让我相信:
#!/usr/bin/env perl
use strict;
use warnings;
use FileHandle;
#Get number of cores over 95% idle
# this can be adjusted
my $idle_percent=90;
my $free_cores=GetCores($idle_percent);
printf( "Cores over %s free: %s\n",$idle_percent,$free_cores);
sub GetCores {
my $threshold=shift;
my $cpu_idle_count=0;
my $delta_time_sleep=2; #Amount of sleep between the 2 samples
my @cpu_idle_totals;
my @cpu_total_totals;
for(0..1) {
my $output_fh=FileHandle->new('/proc/stat','r') or die "No stat";
# Get output of /proc/stat
while ( my $line=$output_fh->getline() ) {
chomp($line);
my ($tag,$user,$nice,$system,$idle,$iowait,$irq,$softirq)
=split( /\s+/, $line);
if ( $tag=~ m/cpu(.+)/ ) {
my $cpu_number=$1;
my $total=(
$user + $nice + $system + $idle
+ $iowait + $irq + $softirq
);
if ( defined( $cpu_idle_totals[$cpu_number] ) ) {
my $idle_delta=$idle-$cpu_idle_totals[$cpu_number];
my $total_delta=$total-$cpu_total_totals[$cpu_number];
my $usage=100 * (($idle_delta)/$total_delta);
printf("%s is %0.2f%% idle\n",$tag,$usage);
if ( $usage >= $threshold ) {
$cpu_idle_count++;
}
}
$cpu_idle_totals[$cpu_number]=$idle;
$cpu_total_totals[$cpu_number]=$total;
}
}
$output_fh->close();
sleep $delta_time_sleep;
}
return $cpu_idle_count;
}
输出:
cpu0 is 89.90% idle cpu1 is 94.97% idle cpu2 is 95.02% idle cpu3 is 97.00% idle cpu4 is 96.98% idle cpu5 is 98.48% idle cpu6 is 97.99% idle cpu7 is 95.98% idle Cores over 90% free:7