【问题标题】:Basic operations combining two SharedArrays结合两个 SharedArrays 的基本操作
【发布时间】:2015-12-17 12:42:21
【问题描述】:

我在过去一个月左右的时间里学习了 julia,我印象非常深刻。特别是我正在分析大量的气候模型输出,我将所有这些都放入SharedArrays 并同时调整和绘制它们。到目前为止,它非常快速高效,而且我有相当多的代码库。我当前的问题是创建一个可以对两个共享数组执行基本操作的函数。我已经成功编写了一个函数,该函数需要两个数组以及您希望如何处理它们。该代码基于 julia 文档并行部分中的示例,并使用myrange 函数,如图所示

function myrange(q::SharedArray)
    idx = indexpids(q)
    #@show (idx)
    if idx == 0
        # This worker is not assigned a piece
        return 1:0, 1:0
        print("NO WORKERS ASSIGNED")
    end
    nchunks = length(procs(q))
    splits = [round(Int, s) for s in linspace(0,length(q),nchunks+1)]
    splits[idx]+1:splits[idx+1]
end

function combine_arrays_chunk!(array_1,array_2,output_array,func, length_range);
    #@show (length_range)
    for i in length_range
        output_array[i] = func(array_1[i], array_2[i]);
        #hardwired example for func = +
        #output_array[i] = +(array_1[i], array_2[i]);
    end
    output_array
end

combine_arrays_shared_chunk!(array_1,array_2,output_array,func) = combine_arrays_chunk!(array_1,array_2,output_array,func, myrange(array_1));

function combine_arrays_shared(array_1::SharedArray,array_2::SharedArray,func)
    if size(array_1)!=size(array_2)
        return print("inputs not of the same size")
    end
    output_array=SharedArray(Float64,size(array_1));
    @sync begin
        for p in procs(array_1)
            @async remotecall_wait(p, combine_arrays_shared_chunk!, array_1,array_2,output_array,func)
        end
    end
    output_array
end

一个人可以做的事情

strain_div  = combine_arrays_shared(eps_1,eps_2,+);
strain_tot  = combine_arrays_shared(eps_1,eps_2,hypot);

如果结果正确,则根据需要将输出作为共享数组。但是......它很慢。实际上,将sharedarray 组合为一个处理器上的普通数组,计算然后转换回sharedarray 实际上更快(无论如何,对于我的测试用例,每个数组大约 200MB,当我移动到 GB 时,我猜不是) .我可以硬连线 combine_arrays_shared 函数只做加法(或其他一些功能),然后你会得到速度提升,但函数类型在 combine_arrays_shared 内传递,整个事情很慢(比硬连线慢 10 倍添加)。

我查看了FastAnonymous.jl 包,但我看不出它在这种情况下是如何工作的。我试过了,失败了。有什么想法吗?

我可能只是为我使用的每个基本函数编写不同的 combine_arrays_... 函数,或者将 func 参数作为选项并从 combine_arrays_shared 中调用不同的函数,但我希望它更优雅!这也是了解更多有关 Julia 的好方法。

哈利

【问题讨论】:

    标签: arrays function parallel-processing julia


    【解决方案1】:

    这个问题其实与 SharedArrays 无关,只是“我如何将函数作为参数传递并获得更好的性能?”

    FastAnonymous 的工作方式——与很快在 julia 中的闭包工作方式类似——是使用 call 方法创建一个类型。如果您由于某种原因在使用 FastAnonymous 时遇到问题,您可以随时手动进行:

    julia> immutable Foo end
    
    julia> Base.call(f::Foo, x, y) = x*y
    call (generic function with 1036 methods)
    
    julia> function applyf(f, X)
               s = zero(eltype(X))
               for x in X
                   s += f(x, x)
               end
               s
           end
    applyf (generic function with 1 method)
    
    julia> X = rand(10^6);
    
    julia> f = Foo()
    Foo()
    
    # Run the function once with each type of argument to JIT-compile
    julia> applyf(f, X)
    333375.63216645207
    
    julia> applyf(*, X)
    333375.63216645207
    
    # Compile anything used by @time
    julia> @time 1
      0.000004 seconds (148 allocations: 10.151 KB)
    1
    
    # Now let's benchmark
    julia> @time applyf(f, X)
      0.002860 seconds (5 allocations: 176 bytes)
    333433.439233112
    
    julia> @time applyf(*, X)
      0.142411 seconds (4.00 M allocations: 61.035 MB, 19.24% gc time)
    333433.439233112
    

    请注意速度的大幅提升和内存消耗的大幅减少。

    【讨论】:

    • 这是一个正确回答问题的例子!现在这更有意义了,所以我可以将类型 f 分配给我需要的函数,然后有效地传递函数。有没有办法可以在函数中分配这种类型?所以对于我上面的例子,顶部的combine_arrays_shared 会做分配,然后函数被有效地传递给combine_arrays_chunk! 函数?我试试看。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-01
    • 1970-01-01
    • 2018-12-07
    • 2021-04-05
    • 1970-01-01
    • 2011-01-16
    • 2018-04-23
    相关资源
    最近更新 更多