1

我编写了一个简单的化学模拟,它可以并行计算大量网格框的属性。因此,我使用并行循环索引 Y 维度:

function[outputArray] = stackTest()

numX = 10;
numY = 10;
numZ = 10;
outputArray = zeros(numX,numY,numZ);
for iX = 1:numX
    parfor iY = 1:numY
        coreArray = outputArray(iX,iY,:);
        for iZ = 1:numZ
            tempNum = iX*iY*iZ;
            coreArray(1,1,iZ) = tempNum;
        end
        outputArray(iX,iY,:) = coreArray;
    end
end
end

这工作正常。但是,我使用布尔值来控制是否执行某些操作,如下面的代码所示。for这在 Y 上使用简单循环时效果很好,但在使用 时parfor,代码失败,声明optionalArg未定义:

function[outputArray] = stackTest(controlArg)

numX = 10;
numY = 10;
numZ = 10;
outputArray = zeros(numX,numY,numZ);
if (controlArg)
    optionalArg = 10;
end
for iX = 1:numX
    parfor iY = 1:numY
        coreArray = outputArray(iX,iY,:);
        for iZ = 1:numZ
            tempNum = iX*iY*iZ;
            if controlArg
                tempNum = tempNum * optionalArg;
            end
            coreArray(1,1,iZ) = tempNum;
        end
        outputArray(iX,iY,:) = coreArray;
    end
end
end

stackTest现在工作正常 if controlArg = true,但不是 if controlArg = false; 我发现的唯一解决方法是定义optionalArg独立于controlArg. 不用说这是问题的简化版本,但我会感谢任何可以向我解释的人;我怀疑这是parfor循环与全局变量有关的问题的一个子集,但是由于我没有定义全局变量,所以我有点困惑。

问候,

跳过

4

1 回答 1

0

何时controlArg为假,optionalArg未定义。我猜 MATLAB 不相信你controlArg永远是假的(我的意思是说它没有机制来推断它,尽管对于上面的代码,人类可能认为这是显而易见的)。因此,它不能保证此时您的代码不需要parfor知道任何迭代:optionalArg

        if controlArg
            tempNum = tempNum * optionalArg;
        end

为了快速修复,optionalArg请在没有周围的 if 子句的情况下进行定义——controlArg无论如何在使用它之前再次检查。或者,尝试用optionalArg10*controlArg或所有三行替换为将0(false) 映射到 1 和1(true) 映射到所需值的数学表达式optionalArg,例如tempNum = tempNum * (controlArg*9+1);)。

顺便说一句:也许您可以更多地了解实际问题(不一定在这个问题中)。上面的输出数组可以由一两行代码生成,我猜想 MATLAB 的优点之一是一次对许多类似操作的矢量化计算(无需显式并行化)也可以应用于您的问题(即您可能不需要三层for循环。

于 2013-02-20T19:24:02.133 回答