【问题标题】:use perl script to optimally use available cpus使用 perl 脚本来优化使用可用的 CPU
【发布时间】:2015-11-30 06:36:39
【问题描述】:

我编写了一个小 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,我不应该再启动任何子进程,但根据top似乎有一些空闲CPU 在那里,虽然第四个数字是 70。

【问题讨论】:

  • 启动的正确进程数取决于所涉及的任务类型(内存密集型?cpu 密集型?i/o 密集型?)。看看/proc/cpuinfo 看看你安装了什么。
  • @xxfelixxx 如果允许的话,程序的一次运行会占用一个 CPU 的 100%。
  • @xxfelixxx 我知道我有什么 CPU,我不需要脚本来确定硬件信息。我有 48 个 CPU 可用,这就是为什么我将 44 作为最大子代数,因为这将为可能想要计算某些东西的其他人留下一些 CPU。我宁愿找出他们现在有多少是免费的,并相应地调整孩子的数量。
  • @fifaltra,检查loadavg。用最简单的术语来说,它可以告诉您现在使用了多少 CPU/内核。如果数量大于 CPU 数量,则系统过载。

标签: perl parallel-processing cpu-usage


【解决方案1】:

我将建议采取稍微不同的策略——与其根据负载“限制”活动进程的数量,不如使用SIGSTOPSIGCONT

Parallel::ForkManager 为您提供 running_procs 方法,该方法返回一个 PID 列表。

然后,当平均负载“太高”时,您可以将 signal 发送到 STOP

您可以使用Sys::Info::CPU 找到“太高”(这也告诉您load)或者-也许看看Number of processors/cores in command line

但理论上 - 当负载过高时,向您的某些子进程发出“SIGSTOP”。他们应该退出运行队列,并且可见但暂停。

就平均负载而言 - 你得到 3 个数字。 1m、5m 和 15m CPU 负载。看第一个,如果这大于 CPU 的数量,则存在争用。

【讨论】:

    【解决方案2】:

    可能总是有进程在跳来跳去,有些进程会比其他进程使用更多的 CPU。我认为另一种方法是查看每个 CPU 使用其空闲百分比的繁忙程度。像下面的 sn-p 这样的东西可以实现这个目标。然后,您可以设置一个阈值,以确定它是否超过某个空闲量。然后,您可以使用返回的数字来根据要启动的进程数来建立逻辑。我相信这样的事情会有所帮助:

    #!/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
    

    【讨论】:

      猜你喜欢
      • 2019-02-18
      • 2020-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-12
      • 2015-08-31
      • 1970-01-01
      相关资源
      最近更新 更多