2009-12-25 76 views
15

我是航空航天工程專業的學生,​​我正在做一個高級頂尖項目。我正在開發的數學模型之一需要XFOIL生成的天文數據量,XFOIL是一種流行的航空航天工具,用於查找翼型上的升力和阻力系數。 (但我正在離題)如何讓我的Perl腳本爲子進程使用多個內核?

切入正題:我有一個Perl腳本,它使用不同的輸入參數反覆調用XFOIL來生成我需要的數據。我需要XFOIL運行5600次,目前它每次運行平均需要大約100秒。做數學,這意味着它將需要大約6.5天才能完成。

現在,我有一個四核機器,但我作爲程序員的經驗是有限的,我真的只知道如何使用基本的Perl。我想一次運行4個XFOIL實例,都是在他們自己的核心上。事情是這樣的:

while (1){ 
    for (i = 1..4){ 
     if (! exists XFOIL_instance(i)){ 
      start_new_XFOIL_instance(i, input_parameter_list); 
     } 
    } 
} 

所以在程序檢查(或最好睡覺,直到XFOIL例如將其喚醒,開始一個新的實例),如果每一個內核的運行XFOIL。如果不是,則退出前一個實例,我們可以使用新的輸入參數列表啓動一個新實例。

如果任何人有任何想法如何實現,請讓我知道。這將大大加快我需要生成數據的時間,並讓我在航天項目本身上工作。

感謝您的幫助!

+1

我怕我不打算提供一個完整的答案,但短版是你可以肯定地分離當前perl腳本的四個實例,然後讓每個實例運行一個XFOIL腳本。但是,爲處理結果設置處理器親和力 - 這將需要知道您正在使用的操作系統。 – 2009-12-25 18:53:16

+2

您確定XFOIL不會線程或以其他方式使用多個處理器,以使其運行時間首次達到大約100秒? – dlamblin 2009-12-25 19:18:05

+0

難以將XFOIL實現到C/Fortran中嗎?如果不是,那麼我建議你去做。 Perl並不完全是編程語言的Speedy Gonzalez ... – Zaid 2009-12-25 19:43:19

回答

17

嘗試Parallel::ForkManager。這是一個模塊,提供了一個簡單的界面來分離這樣的過程。

下面是一些示例代碼:

#!/usr/bin/perl 

use strict; 
use warnings; 
use Parallel::ForkManager; 

my @input_parameter_list = 
    map { join '_', ('param', $_) } 
    (1 .. 15); 

my $n_processes = 4; 
my $pm = Parallel::ForkManager->new($n_processes); 
for my $i (1 .. $n_processes) { 
    $pm->start and next; 

    my $count = 0; 
    foreach my $param_set (@input_parameter_list) {   
     $count++; 
     if (($count % $i) == 0) { 
      if (!output_exists($param_set)) { 
       start_new_XFOIL_instance($param_set); 
      } 
     } 
    } 

    $pm->finish; 
} 
$pm->wait_all_children; 

sub output_exists { 
    my $param_set = shift; 
    return (-f "$param_set.out"); 
} 

sub start_new_XFOIL_instance { 
    my $param_set = shift; 
    print "starting XFOIL instance with parameters $param_set!\n"; 
    sleep(5); 
    touch("$param_set.out"); 
    print "finished run with parameters $param_set!\n"; 
} 

sub touch { 
    my $fn = shift; 
    open FILE, ">$fn" or die $!; 
    close FILE or die $!; 
} 

您需要提供自己的實現爲start_new_XFOIL_instance和output_exists功能,你還需要定義自己的參數集傳遞給XFOIL 。

+1

這看起來是我需要的。我將閱讀Parallel :: ForkManager並讓你知道它是如何發展的。謝謝您的幫助! 當然,任何其他來自其他任何輸入的讚賞。 – 2009-12-25 20:10:55

+0

如果您還不知道,可以在主目錄中安裝Parallel :: ForkManager模塊。看看這裏如何做到這一點: http://stackoverflow.com/questions/540640/how-can-i-install-a-cpan-module-into-a-local-directory – 2009-12-26 06:30:19

+1

詹姆斯,非常感謝你的幫幫我。我通過命令行安裝了Parallel :: ForkManager - 我想我現在已經開始運行了。我仍然試圖弄清楚模塊的複雜性以及我希望它在錯誤條件下的行爲方式,但是在我的雙核筆記本電腦上進行的初步運行讓我認爲我已經認識到了這一點 - 至少基本的想法,無論如何。再次感謝一堆! – 2009-12-26 07:55:57

3

這看起來像你可以使用齒輪工這個項目。

www.gearman.org

Gearman是一個工作隊列。您可以將您的工作流程分成許多小部件。

我會推薦使用amazon.com甚至他們的拍賣能力服務器來完成這個項目。

每個計算小時或更少的時間花費10次,可以顯着加速您的項目。

我會在本地使用gearman,確保你有一個「完美」的5-10你的subjobs運行之前,它交給一個亞馬遜計算農場。

3

Perl threads將利用多個內核和處理器。線程的主要功能是在線程之間共享數據並協調其活動,這非常簡單。分叉進程不能輕易將數據返回給父進程,也不能自行協調。

Perl線程的主要缺點是與fork相比創建起來相對昂貴,它們必須複製整個程序及其所有數據;你必須把它們編譯到你的Perl中;他們可能是越野車,Perl越老,線程越脆弱。如果你的工作很昂貴,創作時間應該不重要。

下面是一個如何與線程一起使用的例子。有很多方法可以做到,這個使用Thread::Queue來創建工作線程可以共享的大量工作列表。當隊列爲空時,線程退出。主要優點是,它更容易控制有多少線程處於活動狀態,並且您不必爲每一項工作創建新的昂貴的線程。

本示例將所有工作一次性推送到隊列中,但沒有理由不能隨時添加到隊列中。如果你這樣做,你會使用dequeue而不是dequeue_nb這將等待更多的輸入。

use strict; 
use warnings; 

use threads; 
use Thread::Queue; 

# Dummy work routine 
sub start_XFOIL_instance { 
    my $arg = shift; 
    print "$arg\n"; 
    sleep 1; 
} 

# Read in dummy data 
my @xfoil_args = <DATA>; 
chomp @xfoil_args; 

# Create a queue to push work onto and the threads to pull work from 
# Populate it with all the data up front so threads can finish when 
# the queue is exhausted. Makes things simpler. 
# See https://rt.cpan.org/Ticket/Display.html?id=79733 
my $queue = Thread::Queue->new(@xfoil_args); 

# Create a bunch of threads to do the work 
my @threads; 
for(1..4) { 
    push @threads, threads->create(sub { 
     # Pull work from the queue, don't wait if its empty 
     while(my $xfoil_args = $queue->dequeue_nb) { 
      # Do the work 
      start_XFOIL_instance($xfoil_args); 
     } 

     # Yell when the thread is done 
     print "Queue empty\n"; 
    }); 
} 

# Wait for threads to finish 
$_->join for @threads; 

__DATA__ 
blah 
foo 
bar 
baz 
biff 
whatever 
up 
down 
left 
right 
+0

我看到我以前的評論(或您之前的回答)已被刪除,無論如何感謝您更新您的答案。 我很好奇,如果你確定線程可以利用多個內核和處理器,如果是的話,你是如何驗證它的? 謝謝 =) – user454322 2012-09-19 02:31:10

+0

@ user454322看到您的評論後,我寫了一個腳本來在一堆線程中執行無限循環,並在OS X上使用Activity Monitor查看所有四個內核正在被使用。你說的線程模型是每個真實線程的新的Perl解釋器。以前,我在我的腦海中認爲這一切都是在一個過程中模擬的。 – Schwern 2012-09-20 02:13:54

+0

我已經發布http://stackoverflow.com/questions/12536064/how-does-perls-threading-system-work,如果你有機會請看看。 – user454322 2012-09-21 18:23:10

0

您是否考慮牛羚並行parallel。 它可以讓你用不同的輸入運行你的程序的幾個安裝實例,並且當你的CPU核心開始可用時,它們就會填滿你的CPU核心。它通常是實現簡單任務並行化的一種非常簡單有效的方法。

相關問題