代码之家  ›  专栏  ›  技术社区  ›  paugier

如何在Julia中加速多个广播

  •  2
  • paugier  · 技术社区  · 7 年前

    function my_multi_broadcast(a)
        10 * (2*a.^2 + 4*a.^3) + 2 ./ a
    end
    
    arr = ones(1000, 1000)
    my_multi_broadcast(arr)
    

    我想只是我写得不对。。。在茱莉亚,怎样才能加速这种“多重广播”?我想/希望我不需要花费这些循环。。。

    在第一个答案后编辑

    非常感谢。在我的设置中,Pythran解决方案(就地和异地)的速度仍然快1.5到2倍(没有OpenMP)。有没有办法激活Julia中的SIMD指令?还是另一种加速CPU计算的方法?

    Python代码:

    from transonic import jit
    
    @jit
    def broadcast(a):
        return 10 * (2*a**2 + 4*a**3) + 2 / a
    
    @jit
    def broadcast_inplace(a):
        a[:] = 10 * (2*a**2 + 4*a**3) + 2 / a
    

    编辑后 @simd

    看来 @simd 不开箱即用,即仅在行首添加。

    ERROR: LoadError: LoadError: Base.SimdLoop.SimdError("for loop expected")
    Stacktrace:
     [1] compile(::Expr, ::Bool) at ./simdloop.jl:54
     [2] @simd(::LineNumberNode, ::Module, ::Any) at ./simdloop.jl:126
     [3] include at ./boot.jl:317 [inlined]
     [4] include_relative(::Module, ::String) at ./loading.jl:1044
     [5] include(::Module, ::String) at ./sysimg.jl:29
     [6] exec_options(::Base.JLOptions) at ./client.jl:231
     [7] _start() at ./client.jl:425
    

    似乎我们有这样一个例子,简单的Python/Numpy代码可以用Pythran比用Julia更快地得到加速(除非在Julia中有加速的方法?未来的朱莉娅版本可能会解决这个问题)。有趣的。。。

    1 回复  |  直到 7 年前
        1
  •  13
  •   Bogumił Kamiński    7 年前

    julia> function my_multi_broadcast2(a)
               @. 10 * (2*a^2 + 4*a^3) + 2 / a
           end
    my_multi_broadcast2 (generic function with 1 method)
    

    不同之处在于 10 * (2*a.^2 + 4*a.^3) + 2 ./ a * + 没有广播。

    书写 @. 10 * (2*a^2 + 4*a^3) + 2 / a 10 .* (2 .* a.^2 .+ 4 .* a.^3) .+ 2 ./ a .

    这里是性能的比较

    julia> @btime my_multi_broadcast($arr);
      58.146 ms (18 allocations: 61.04 MiB)
    
    julia> @btime my_multi_broadcast2($arr);
      5.982 ms (4 allocations: 7.63 MiB)
    

    它与Pythran /C++相比如何,因为我们得到大约10x的加速?

    arr 以书面形式落实:

    julia> function my_multi_broadcast3(a)
               @. a = 10 * (2*a^2 + 4*a^3) + 2 / a
           end
    my_multi_broadcast3 (generic function with 1 method)
    
    julia> @btime my_multi_broadcast3($arr);
      1.840 ms (0 allocations: 0 bytes)
    

    这是更快,没有零分配(我不知道你是否想修改 放置或创建一个新数组,以便我展示这两种方法)。

    推荐文章