2015-11-30 35 views
2

我已經寫了一個perl腳本多次啓動程序,在for循環中使用不同的參數。該程序進行數值計算,如果可以得到一個,則使用整個CPU。我有幾個CPU可用,所以理想情況下,我想一次啓動儘可能多的程序實例,因爲有可用的CPU,但不是更多。由於可能有其他進程在運行,可用CPU的數量並不總是相同的。使用Perl腳本來優化使用可用的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一千一百零六分之七十○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

啓動進程的數量取決於所涉及的任務類型(內存密集型?cpu-bound?I/O密集型?)。看一看'/ proc/cpuinfo'來看看你已經安裝了什麼。 – xxfelixxx

+0

http://search.cpan.org/~jstowe/Linux-Cpuinfo-1.10/lib/Linux/Cpuinfo.pm – xxfelixxx

+0

@xxfelixxx如果你願意,程序的一次運行使用100%的一個CPU。 – fifaltra

回答

2

我會建議採取略有不同的粘性 - 怎麼樣,而不是「節流」你的電話號碼基於負載的活動進程 - 爲什麼不使用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的數量還要多,你就有爭議。

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