Matlab用于非分类变量

Matlab用于非分类变量,matlab,parfor,Matlab,Parfor,以下代码根据向量v计算A的矩阵元素。我尝试使用parfor来加速计算,因为v的维数非常大。我得到一个错误“Aparfor中的变量A无法分类”。对如何解决这个问题有什么建议吗 A = zeros(n,n); for kk = 1:D % sk = <expressions...> % ek = <expressions...> parfor ll = 1:D % sl = <expressions...>

以下代码根据向量v计算A的矩阵元素。我尝试使用
parfor
来加速计算,因为
v
的维数非常大。我得到一个错误“A
parfor
中的变量
A
无法分类”。对如何解决这个问题有什么建议吗

A = zeros(n,n);
for kk = 1:D
    % sk = <expressions...>
    % ek = <expressions...>
    parfor ll = 1:D
        % sl = <expressions...>
        % el = <expressions...>
        if (ek == el)
            A(sk,sl) = A(sk,sl) + v(kk) * v(ll);
        end
    end
end
A=0(n,n);
对于kk=1:D
%sk=
%埃克=
parforll=1:D
%sl=
%el=
如果(ek==el)
A(sk,sl)=A(sk,sl)+v(kk)*v(ll);
结束
结束
结束

问题在于,您将
A
分布在不同的内核上,但会自行调整其值。核心如何知道条目
a(sk,sl)
没有在不同的核心上更改?它需要检查这一点,与所有其他内核通信,消除任何并行计算,这就是为什么MATLAB对此抱怨的原因:

您可以通过在
parfor
-循环之外创建
a
的副本来避免此问题

A = zeros(n,n);
B = A;
for kk = 1:D
    % sk = <expressions...>
    % ek = <expressions...>
    parfor ll = 1:D
        % sl = <expressions...>
        % el = <expressions...>
        if (ek == el)
            B(sk,sl) = A(sk,sl) + v(kk) * v(ll);
        end
    end
end
A=0(n,n);
B=A;
对于kk=1:D
%sk=
%埃克=
parforll=1:D
%sl=
%el=
如果(ek==el)
B(sk,sl)=A(sk,sl)+v(kk)*v(ll);
结束
结束
结束

问题在于,您将
A
分布在不同的内核上,但会自行调整其值。核心如何知道条目
a(sk,sl)
没有在不同的核心上更改?它需要检查这一点,与所有其他内核通信,消除任何并行计算,这就是为什么MATLAB对此抱怨的原因:

您可以通过在
parfor
-循环之外创建
a
的副本来避免此问题

A = zeros(n,n);
B = A;
for kk = 1:D
    % sk = <expressions...>
    % ek = <expressions...>
    parfor ll = 1:D
        % sl = <expressions...>
        % el = <expressions...>
        if (ek == el)
            B(sk,sl) = A(sk,sl) + v(kk) * v(ll);
        end
    end
end
A=0(n,n);
B=A;
对于kk=1:D
%sk=
%埃克=
parforll=1:D
%sl=
%el=
如果(ek==el)
B(sk,sl)=A(sk,sl)+v(kk)*v(ll);
结束
结束
结束

您可以将其表述为一个over
a
,如下所示:

parfor ll 1:D
    % compute stuff...

    % Make a new matrix for the increment
    Aincrement = zeros(n, n);
    % Fill out the element of the increment
    Aincrement(sk, sl) = v(kk) * v(ll);
    % Increment the whole of A so that parfor can 
    % treat A as a reduction variable
    A = A + Aincrement;
end

如果
n
很大,这很可能是低效的。

您可以将其表述为一个over
a
,如下所示:

parfor ll 1:D
    % compute stuff...

    % Make a new matrix for the increment
    Aincrement = zeros(n, n);
    % Fill out the element of the increment
    Aincrement(sk, sl) = v(kk) * v(ll);
    % Increment the whole of A so that parfor can 
    % treat A as a reduction variable
    A = A + Aincrement;
end

如果
n
很大,这很可能是低效的。

抱歉,但此解决方案很可能不会产生相同的输出。
A
用零初始化并添加到循环中的原因是多个循环迭代将产生相同的
(sk,sl)
值。如果不是这样,就没有理由添加到
A
,因为
A(sk,sl)
只会是零。您的诊断是正确的,但解决方法是不要使用
palor
。这不是一个适合非共享内存并行的任务。是的,没错,@CrisLuengo。在没有看到代码的情况下,我无法建议任何适当的并行化解决方案=(抱歉,但此解决方案很可能不会产生相同的输出。
A
用零初始化并添加到循环中,原因是多个循环迭代将产生相同的
(sk,sl)
值。如果不是这样,就没有理由添加到
A
,因为
A(sk,sl)
将为零。您的诊断是正确的,但解决方案是不使用
palor
。这不是一项适合非共享内存并行的任务。是的,没错,@CrisLuengo。如果没有看到代码,我无法建议任何合适的并行解决方案=(