我的循环很慢。那是因为if语句吗?

时间:2017-10-05 00:12:48

标签: performance julia

我读了this post并意识到朱莉娅的循环速度更快。因此,我决定将矢量化代码更改为循环。但是,我必须在循环中使用一些if语句,但是在添加了更多if语句后,我的循环速度变慢了。

考虑一下我直接从帖子中复制的摘录:

function devectorized()
    a = [1.0, 1.0]
    b = [2.0, 2.0]
    x = [NaN, NaN]

    for i in 1:1000000
        for index in 1:2
            x[index] = a[index] + b[index]
        end
    end

    return
end

function time(N)
    timings = Array(Float64, N)

    # Force compilation
    devectorized()

    for itr in 1:N
        timings[itr] = @elapsed devectorized()
    end

    return timings
end

然后我添加了一些if语句来测试速度:

function devectorized2()
    a = [1.0, 1.0]
    b = [2.0, 2.0]
    x = [NaN, NaN]

    for i in 1:1000000
        for index in 1:2

             ####repeat this 6 times
            if index * i < 20
                x[index] = a[index] - b[index]
            else
                x[index] = a[index] + b[index]
            end
             ####

        end
    end

    return
end

我重复了六次这个块:

            if index * i < 20
                x[index] = a[index] - b[index]
            else
                x[index] = a[index] + b[index]
            end

为了简洁起见,我不会在示例代码中重复此块。在重复if语句6次之后,devectorized2()花了3倍的时间。

我有两个问题:

  1. 是否有更好的方法来实现if语句?
  2. 为什么if语句这么慢?我知道朱莉娅正试图以符合C的方式做循环。朱莉娅提供更好的翻译&#34; Julia和C之间的这些if语句只会让翻译过程变得更加困难吗?

1 个答案:

答案 0 :(得分:2)

首先,我不认为这里的表现很奇怪,因为你在为你的功能添加了很多工作。

其次,你实际上应该return x,否则编译器可能会决定你没有使用x,只是跳过整个计算,这会彻底混淆时间。

第三,回答你的问题1:你可以这样实现:

x[index] = a[index] + ifelse(index * i < 20, -1, 1) * b[index]

在某些情况下,这可能会更快,但不一定在您的情况下,分支很容易预测。有时您也可以使用Bool来获得加速,例如:

x[index] = a[index] + (2*(index * i >= 20)-1) * b[index]

同样,在你的例子中,这没有多大帮助,但有时候这种方法可以给你一个不错的加速。

BTW:循环不再总是优于矢量化代码。您链接的帖子很旧。看一下this blog post,它展示了矢量化代码如何实现与循环代码类似的性能。但是,在许多情况下,循环是实现目标的最清晰,最简单,最快捷的方法。