2014-08-27 90 views
-1

我想目前你這個小(在這種還原形式無謂)的紅寶石代碼,運行非常緩慢片段:紅寶石緩存數組訪問?

MAX = 28123 
M = 7000 

abundant = Array.new(M) {|k| k} 
checked = Array.new(MAX) {|k| false} 

for a in 0..M-1 do 
    for b in a..M-1 do 
     checked[abundant[a] + abundant[b]] = true if abundant[a] + abundant[b] < MAX 
    end 
end 

這需要大約10秒來執行,而等效C++代碼在約運行0.2秒:

int main() 
{ 
    int abundant[M]; 
    bool checked[MAX];    

    for (int n = 0; n < M; n++) 
     abundant[n] = n; 
    for (int n = 0; n < MAX; n++) 
     checked[n] = false; 

    for (int a = 0; a < M; a++) 
     for (int b = a; b < M; b++) 
      if (abundant[a] + abundant[b] < MAX) 
       checked[abundant[a] + abundant[b]] = true; 
} 

我在做錯誤的紅寶石實現?我是新來的紅寶石 - 我使用任何已知是慢的聲明?

+0

對我來說運行<3s,包括Ruby旋轉起來。在任何情況下,(a)解釋,(b)有對象創建,(c)你正在運行一個塊來初始化這些對象,等等。蘋果,桔子。 – 2014-08-27 10:58:37

+0

但是對於這樣一個簡單的任務,0.2s vs. 3s仍然不是真的可以接受的。數組的創建不是關鍵點(添加'puts'init done「'消息時很容易看到),它是嵌套的循環,它會產生變化。 「有對象創造」是什麼意思?循環中是否有這樣的內容? – JulianS 2014-08-27 11:09:13

+0

是的,但是C會允許你這麼做:'abundant = Array.new(2 * M-1,true)+ Array.new(MAX-2 * M-1,false)'?通常,在Ruby中,通過使用已經在C中實現並優化的內置方法(或由gems提供的方法),您可以快速且簡潔地執行操作。 – 2014-08-27 16:08:38

回答

3

Ruby肯定比C++慢很多,所以沒有太多的工作可以讓你的代碼更快。

相信下面的代碼具有相同的行爲,並且是快一點(±25%):

MAX = 28123 
M = 7000 

checked = Array.new(MAX) {|k| false} 

(0..M - 1).each do |a| 
    (a..M - 1).each do |b| 
    checked[a + b] = true if a + b < MAX 
    end 
end 

使用#each沒有差別,但製作更少數組訪問一樣。我相信C++速度更快的原因之一是因爲它不會對數組訪問進行邊界檢查,而Ruby必須這樣做。

您可以更改C++版本以使用std::vector.at()來訪問數組,然後與Ruby版本進行比較嗎?

+0

你的建議改善速度顯然更快,但不能用於未簡化的問題。但是:與此同時,我比較了另一個不同問題的執行速度,並且必須觀察同樣的差距。顯然,這真的是ruby的解釋器,速度很慢。 – JulianS 2014-08-27 11:37:50

+4

@JulianS當然是 - 它是一名口譯員。你也使用較慢的版本。目前還不清楚你想要做什麼 - 這不僅僅是新聞快訊,Ruby比編譯C慢得多。 – 2014-08-27 11:48:19