我一直在运行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%的时间用"=="运算.有没有任何矢量化的方法更快地做到这一点?
第二个问题是我将耗尽内存 - 随着范围变大,这种方法的可扩展性不高.是否有一种很好的方法可以保留可矢量化,但不会尝试将子集保留在内存中?
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++性能,但它是朝着正确方向迈出的一步.