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

Performance 我的循环很慢。这是因为if语句吗?,performance,julia,Performance,Julia,我阅读并意识到朱莉娅的循环更快。因此,我决定将向量化代码更改为循环。然而,我不得不在循环中使用一些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]

我阅读并意识到朱莉娅的循环更快。因此,我决定将向量化代码更改为循环。然而,我不得不在循环中使用一些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
函数devectorized2()
a=[1.0,1.0]
b=[2.0,2.0]
x=[NaN,NaN]
对于我来说,1:1000000
对于1:2的索引
####重复6次
如果索引*i<20
x[index]=a[index]-b[index]
其他的
x[index]=a[index]+b[index]
结束
####
结束
结束
返回
结束
我重复了六次这个街区:

            if index * i < 20
                x[index] = a[index] - b[index]
            else
                x[index] = a[index] + b[index]
            end
如果索引*i<20
x[index]=a[index]-b[index]
其他的
x[index]=a[index]+b[index]
结束
为了简洁起见,我不会在示例代码中重复此块。重复if语句6次后,
devectorized2()
所用的时间是原来的3倍

我有两个问题:

  • 是否有更好的方法实现if语句
  • 为什么if语句如此缓慢?我知道Julia正在尝试以与C匹配的方式进行循环。Julia是否在Julia和C之间提供了更好的“翻译”,而这些if语句只是使翻译过程更加困难

  • 首先,我不认为这里的性能很奇怪,因为您正在为函数添加大量工作

    其次,您实际上应该在这里
    返回x
    ,否则编译器可能会认为您没有使用
    x
    ,而跳过整个计算,这将彻底混淆计时

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

    x[index] = a[index] + ifelse(index * i < 20, -1, 1) * b[index]
    
    x[index] = a[index] + (2*(index * i >= 20)-1) * b[index]
    
    同样,在您的示例中,这并没有多大帮助,但在某些情况下,这种方法可以给您一个不错的加速


    顺便说一句:循环不再比矢量化代码更可取,这并不一定总是正确的。你链接到的帖子很旧。看一看,它显示了矢量化代码如何实现与循环代码类似的性能。不过,在许多情况下,循环是实现目标的最清晰、最简单、最快的方法。

    首先,我不认为这里的性能很奇怪,因为您正在为函数添加大量工作

    其次,您实际上应该在这里
    返回x
    ,否则编译器可能会认为您没有使用
    x
    ,而跳过整个计算,这将彻底混淆计时

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

    x[index] = a[index] + ifelse(index * i < 20, -1, 1) * b[index]
    
    x[index] = a[index] + (2*(index * i >= 20)-1) * b[index]
    
    同样,在您的示例中,这并没有多大帮助,但在某些情况下,这种方法可以给您一个不错的加速


    顺便说一句:循环不再比矢量化代码更可取,这并不一定总是正确的。你链接到的帖子很旧。看一看,它显示了矢量化代码如何实现与循环代码类似的性能。不过,在许多情况下,循环是实现目标最清晰、最简单、最快的方式。

    您将循环的内部部分重复了6次,结果只慢了3倍而不是6倍?听起来不错。。。如果我没看错的话,它的工作量应该是你的6倍。这只是我能做什么?如果你做6倍的加法,它会慢6倍,因为它必须做6倍的计算。你对此无能为力。这在任何语言中都是正确的。在C或Fortran中试试看。一个提示:对于i>20,你不需要检查i*indexy是否重复了循环的内部6次,它只慢了3倍而不是6倍?听起来不错。。。如果我没看错的话,它的工作量应该是你的6倍。这只是我能做什么?如果你做6倍的加法,它会慢6倍,因为它必须做6倍的计算。你对此无能为力。这在任何语言中都是正确的。在C或Fortran中试试看。一个提示:对于i>20,您不需要检查i*索引