Parallel processing 朱莉娅:如何并行执行函数?

Parallel processing 朱莉娅:如何并行执行函数?,parallel-processing,julia,Parallel Processing,Julia,我想并行运行函数。这些函数在循环中执行多次 coordSys = SharedArray{Bool}([true,false,true,true]); dir = SharedArray{Int8}([1,2,3,2]); load = SharedArray{Float64}([8,-7.5,7,-8.5]); L = SharedArray{Float64}([400,450,600,500]); r = SharedArray{Float64}([0.0 0.0 1.0; 0.0 -1.0

我想并行运行函数。这些函数在循环中执行多次

coordSys = SharedArray{Bool}([true,false,true,true]);
dir = SharedArray{Int8}([1,2,3,2]);
load = SharedArray{Float64}([8,-7.5,7,-8.5]);
L = SharedArray{Float64}([400,450,600,500]);
r = SharedArray{Float64}([0.0 0.0 1.0; 0.0 -1.0 0.0; 1.0 0.0 0.0 
                          0.0 0.0 1.0; 0.0 -1.0 0.0; 1.0 0.0 0.0 
                          0.0 0.0 1.0; 0.0 -1.0 0.0; 1.0 0.0 0.0 
                          0.0 0.0 1.0; 0.0 -1.0 0.0; 1.0 0.0 0.0]);
显然,这些向量将是巨大的,但为了简单起见,我只是把这个有限的大小

没有并行计算的操作:

function unifLoad(coordSys,dir,load,L,ri)
    if coordSys == true
        if dir == 1
            Q = [load;0;0];
        elseif dir == 2
            Q = [0;load;0];
        elseif dir == 3
            Q = [0;0;load];
        end
        q = ri*Q; #matrix multiplication
        P = q[1]*L/2;
        V = q[2]*L/2;
        M = -q[3]*L*L/12;
        f = [P;V;M];
    else
        f = [1.0;1.0;1.0];
    end
    return f
end
运行循环:

var = zeros(12)
for i = 1:length(L)
    var[3*(i-1)+1:3*i] = unifLoad(coordSys[i],dir[i],load[i],L[i],r[3*(i-1)+1:3*i,:]);
end
返回值为:

var
12-element Array{Float64,1}:
    0.0      
    0.0      
   -1.06667e5
    1.0      
    1.0      
    1.0      
 2100.0      
    0.0      
   -0.0      
    0.0      
 2125.0      
   -0.0
var_parallel
12-element SharedArray{Float64,1}:
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
并行计算操作

我一直在尝试并行实现相同的函数,但没有得到相同的结果

# addprocs(3)

@everywhere function unifLoad_Parallel(coordSys,dir,load,L,ri)
    if coordSys == true
        if dir == 1
            Q = [load;0;0];
        elseif dir == 2
            Q = [0;load;0];
        elseif dir == 3
            Q = [0;0;load];
        end
        q = ri*Q; # Matrix multiplication (ri -> Array 3x3)
        P = q[1]*L/2;
        V = q[2]*L/2;
        M = -q[3]*L*L/12;
        f = [P;V;M];
    else
        f = [1.0;1.0;1.0];
    end
    return f
end 
运行并行循环:

var_parallel = SharedArray{Float64}(12);

@parallel for i = 1:length(L)
        var_parallel[3*(i-1)+1:3*i] = unifLoad_Parallel(coordSys[i],dir[i],load[i],L[i],r[3*(i-1)+1:3*i,:]);
end
返回值为:

var
12-element Array{Float64,1}:
    0.0      
    0.0      
   -1.06667e5
    1.0      
    1.0      
    1.0      
 2100.0      
    0.0      
   -0.0      
    0.0      
 2125.0      
   -0.0
var_parallel
12-element SharedArray{Float64,1}:
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0
 0.0

在我的Julia 0.6.3上,并行代码返回相同的结果,因此我无法重现该问题(我也没有遇到@SalchiPapa reports的问题)

然而,我想指出的是,这段代码实际上应该能够更快地处理线程(我假设真正的问题要大得多)。下面是您可以使用的代码(我使用了一个与您的等效的实现,它稍微短一点,但唯一重要的相关变化是我将其包装在一个函数中,该函数提供了显著的性能提升)。关键问题是除了
var
之外的所有数组都是共享的,但只能读取。而
var
只在每个条目中写入一次,而不从中读取。在这种情况下,使用开销较低的线程是安全的

下面是一个示例代码(在启动JULIA之前,您必须定义
JULIA\u NUM\u TREADS
环境变量,并将其设置为您想要的线程数-很可能
4
就是您想要的):

这里还有一个使用类似思想进行并行处理的简化代码:

coordSys = SharedArray{Bool}([true,false,true,true]);
dir = SharedArray{Int8}([1,2,3,2]);
load = SharedArray{Float64}([8,-7.5,7,-8.5]);
L = SharedArray{Float64}([400,450,600,500]);
r = SharedArray{Float64}([0.0 0.0 1.0; 0.0 -1.0 0.0; 1.0 0.0 0.0 
                          0.0 0.0 1.0; 0.0 -1.0 0.0; 1.0 0.0 0.0 
                          0.0 0.0 1.0; 0.0 -1.0 0.0; 1.0 0.0 0.0 
                          0.0 0.0 1.0; 0.0 -1.0 0.0; 1.0 0.0 0.0]);

@everywhere unifLoad(coordSys,dir,load,L,r,i) =
        coordSys ? load * L * r[3*(i-1)+1:3*i, dir] .* [0.5, 0.5, -L/12] : [1.0, 1.0, 1.0]

vcat(pmap(i -> unifLoad(coordSys[i],dir[i],load[i],L[i],r,i), 1:length(L))...)

这里的
pmap
主要用于简化代码,这样您就不需要
@sync

我得到一个边界错误:
错误:在worker 2上:边界错误:尝试访问索引[1]处的0元素数组{Bool,1}
如果我使用:
@sync@parallel for。。。结束
以等待计算完成。