加速 Julia 写得很糟糕的 R 示例 [英] Speeding up Julia's poorly written R examples

查看:15
本文介绍了加速 Julia 写得很糟糕的 R 示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

比较性能与 R 的 Julia 示例似乎特别复杂.https://github.com/JuliaLang/julia/blob/master/test/perf/perf.R

The Julia examples to compare performance against R seem particularly convoluted. https://github.com/JuliaLang/julia/blob/master/test/perf/perf.R

您可以从以下两种算法中获得的最快性能是多少(最好说明您所做的更改以使其更像 R)?

What is the fastest performance you can eke out of the two algorithms below (preferably with an explanation of what you changed to make it more R-like)?

## mandel

mandel = function(z) {
    c = z
    maxiter = 80
    for (n in 1:maxiter) {
        if (Mod(z) > 2) return(n-1)
        z = z^2+c
    }
    return(maxiter)
}

mandelperf = function() {
    re = seq(-2,0.5,.1)
    im = seq(-1,1,.1)
    M = matrix(0.0,nrow=length(re),ncol=length(im))
    count = 1
    for (r in re) {
        for (i in im) {
            M[count] = mandel(complex(real=r,imag=i))
            count = count + 1
        }
    }
    return(M)
}

assert(sum(mandelperf()) == 14791)

## quicksort ##

qsort_kernel = function(a, lo, hi) {
    i = lo
    j = hi
    while (i < hi) {
        pivot = a[floor((lo+hi)/2)]
        while (i <= j) {
            while (a[i] < pivot) i = i + 1
            while (a[j] > pivot) j = j - 1
            if (i <= j) {
                t = a[i]
                a[i] = a[j]
                a[j] = t
            }
            i = i + 1;
            j = j - 1;
        }
        if (lo < j) qsort_kernel(a, lo, j)
        lo = i
        j = hi
    }
    return(a)
}

qsort = function(a) {
  return(qsort_kernel(a, 1, length(a)))
}

sortperf = function(n) {
    v = runif(n)
    return(qsort(v))
}

sortperf(5000)

推荐答案

嗯,在 Mandelbrot 示例中,矩阵 M 的维度已转置

Hmm, in the Mandelbrot example the matrix M has its dimensions transposed

M = matrix(0.0,nrow=length(im), ncol=length(re))

因为它是通过增加内部循环中的 count 来填充的(im 的连续值).我的实现在 mandelperf.1 中创建了一个复数向量并对所有元素进行操作,使用索引和子集来跟踪向量的哪些元素尚未满足条件 Mod(z) <= 2

because it's filled by incrementing count in the inner loop (successive values of im). My implementation creates a vector of complex numbers in mandelperf.1 and operates on all elements, using an index and subsetting to keep track of which elements of the vector have not yet satisfied the condition Mod(z) <= 2

mandel.1 = function(z, maxiter=80L) {
    c <- z
    result <- integer(length(z))
    i <- seq_along(z)
    n <- 0L
    while (n < maxiter && length(z)) {
        j <- Mod(z) <= 2
        if (!all(j)) {
            result[i[!j]] <- n
            i <- i[j]
            z <- z[j]
            c <- c[j]
        }
        z <- z^2 + c
        n <- n + 1L
    }
    result[i] <- maxiter
    result
}

mandelperf.1 = function() {
    re = seq(-2,0.5,.1)
    im = seq(-1,1,.1)
    mandel.1(complex(real=rep(re, each=length(im)),
                     imaginary=im))
}

对于 13 倍的加速(结果相等但不相同,因为原始返回数字而不是整数值).

for a 13-fold speed-up (the results are equal but not identical because the original returns numeric rather than integer values).

> library(rbenchmark)
> benchmark(mandelperf(), mandelperf.1(),
+           columns=c("test", "elapsed", "relative"),
+           order="relative")
            test elapsed relative
2 mandelperf.1()   0.412  1.00000
1   mandelperf()   5.705 13.84709

> all.equal(sum(mandelperf()), sum(mandelperf.1()))
[1] TRUE

快速排序示例实际上并没有排序

The quicksort example doesn't actually sort

> set.seed(123L); qsort(sample(5))
[1] 2 4 1 3 5

但我的主要加速是围绕枢轴矢量化分区

but my main speed-up was to vectorize the partition around the pivot

qsort_kernel.1 = function(a) {
    if (length(a) < 2L)
        return(a)
    pivot <- a[floor(length(a) / 2)]
    c(qsort_kernel.1(a[a < pivot]), a[a == pivot], qsort_kernel.1(a[a > pivot]))
}

qsort.1 = function(a) {
    qsort_kernel.1(a)
}

sortperf.1 = function(n) {
    v = runif(n)
    return(qsort.1(v))
}

7 倍加速(与未校正的原始版本相比)

for a 7-fold speedup (in comparison to the uncorrected original)

> benchmark(sortperf(5000), sortperf.1(5000),
+           columns=c("test", "elapsed", "relative"),
+           order="relative")
              test elapsed relative
2 sortperf.1(5000)    6.60 1.000000
1   sortperf(5000)   47.73 7.231818

由于在最初的比较中,对于 mandel,Julia 比 R 快 30 倍,对于快速排序快 500 倍,因此上述实现仍然没有真正的竞争力.

Since in the original comparison Julia is about 30 times faster than R for mandel, and 500 times faster for quicksort, the implementations above are still not really competitive.

这篇关于加速 Julia 写得很糟糕的 R 示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆