R中的矢量化复杂算法

时间:2014-06-17 04:48:05

标签: r performance vectorization

我的代码多次调用以下函数。我已经使用Rprof发现它占用了执行时间的1/3。

我听说通过矢量化可以使R更快。但是,我使用的算法访问两个不同列表中的两个索引,所以我不知道任何* ply函数是如何工作的。

还有什么可以做的来优化这个吗?

n是整数,u和v是复数列表

psi <- function(n, u, v)
{
    psi = complex(real = 0, imaginary = 0)

    for (i in 1 : (n - 1))
    {
        for (j in (i + 1) : n)
        {
            psi = psi + log(u[i] * v[j] - u[j] * v[i])
        }
    }

    return (psi * 3)
}

2 个答案:

答案 0 :(得分:1)

如果我正确阅读了您的代码,对于案例n=4,您的总和归结为

log(u[1]*v[2] - u[2]*v[1]) +
log(u[1]*v[3] - u[3]*v[1]) +
log(u[1]*v[4] - u[4]*v[1]) +

log(u[2]*v[3] - u[3]*v[2]) +
log(u[2]*v[4] - u[4]*v[2]) +

log(u[3]*v[4] - u[4]*v[3])

实际上只是n选择2的所有可能组合。您可以使用combn()创建这样的索引列表。

psi <- function(n,u,v) {
    mx <- function(p) {a<-p[1]; b<-p[2]; log(u[a]*v[b]-u[b]*v[a])}
    sum(combn(n,2, FUN=mx)) * 3
}

这里内部mx函数负责每对索引的计算。这似乎要快得多。我想你想确保他们得到相同的结果。我很难生成测试输入,但没有让log生气。

答案 1 :(得分:1)

我相信以下内容可能会解决您的问题。我之所以选择这种表达方式,是因为我觉得它已经非常透明了。基本上我只是提前生成了i和j的向量,并且像你一样使用它们,但同时用作向量(复制并粘贴你的等式)。

psi <- function(n,u,v) {
    j <- combn(n, 2) #I'll overwrite j later to conserve memory
    i <- j[1,]
    j <- j[2,]
    sum(log(u[i] * v[j] - u[j] * v[i])) * 3
}

只要n不是一个非常大的数字,这将比你的循环快得多,因为它必须在内存中生成和维护你同时使用你的循环生成的整个组合集。但是,无论如何,这会打破你的长期计算。

要显示等效性,请考虑比较生成指数的方法与当前指数的结果。

n <- 5
combn(n, 2)

for (i in 1 : (n - 1))
{
    for (j in (i + 1) : n)
    {
        print(c(i, j))
    }
}