R中更快的模数或等式检查(或矢量化的好方法)

Chr*_*den 3 r

我一直在运行Project Euler,试图编写计算效率高的程序.考虑问题1:http://projecteuler.net/problem=1.我将范围从1000增加到10,000,000,以突出低效率.

这是我的解决方案:

system.time({
    x <- 1:1E7
    a <- sum(as.numeric(x[x%%3 ==0 | x%%5==0]))
})
 user  system elapsed 
0.980   0.041   1.011
Run Code Online (Sandbox Code Playgroud)

这是朋友写的一些C++代码,用来做同样的事情.

#include <iostream>
using namespace std;

int main(int argc, char** argv)
{
 long x = 0;
 for (int i = 1; i < 10000000; i++)
 {
   if (i % 3 == 0)
     x += i;
   else if (i % 5 == 0)
     x += i;
 }
 cout << x;
 return 0;
}
cbaden$ time ./a.out
23333331666668
real    0m0.044s
user    0m0.042s
sys     0m0.001s
Run Code Online (Sandbox Code Playgroud)

我知道C++应该除了R是快,但这个更快?Rprof表示我花了近60%的时间用模数运算符,13%的时间用"=="运算.有没有任何矢量化的方法更快地做到这一点?

第二个问题是我将耗尽内存 - 随着范围变大,这种方法的可扩展性不高.是否有一种很好的方法可以保留可矢量化,但不会尝试将子集保留在内存中?

flo*_*del 7

Modulo在integers上运行时更快,而不是numerics:

f1 <- function() {
   x <- 1:1E7
   a <- sum(as.numeric(x[x%%3 ==0 | x%%5==0]))
}

f2 <- function() {
   x <- 1:1E7
   a <- sum(as.numeric(x[x %% 3L == 0L | x %% 5L == 0L]))
}

library(rbenchmark)
benchmark(f1(), f2(), replications = 5)
#   test replications elapsed relative user.self sys.self user.child sys.child
# 1 f1()            5   14.78 4.976431     13.95     0.67         NA        NA
# 2 f2()            5    2.97 1.000000      2.37     0.50         NA        NA
Run Code Online (Sandbox Code Playgroud)

这仍然远离C++性能,但它是朝着正确方向迈出的一步.