2014-08-27 69 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