【问题标题】:MATLAB parfor index exceeds the number of array elementsMATLAB parfor 索引超出数组元素的数量
【发布时间】:2020-07-27 16:28:55
【问题描述】:

为什么即使 MATLAB 不应该转到 switch 语句的第一个 case,它也会抛出错误?下面是最小的例子:

mycase = 2;
non_crack_bytes = 1:6000;
syn_crack_bytes = 1:10000;
imgCount = 10000;
parfor j = 1 : imgCount
    switch mycase
        case 1
            if ~(non_crack_bytes(j) == 0)
                % Do something
            else
                continue;
            end
        case 2
            if ~(syn_crack_bytes(j) == 0)
                % Do something
            else
                continue;
            end
    end        
end

我得到的错误是:

Error using ScratchPaperFile>(parfor supply)
Index exceeds the number of array elements (6000).
Error in ScratchPaperFile (line 10)
parfor j = 1 : imgCount

【问题讨论】:

  • 我最好的猜测是,Matlab 试图在 parfor-entry 上变得聪明,并做了一些循环启发式,这在这种情况下是错误的。当您更改为 10.000 时,这将按预期工作,并且错误也发生在循环条目上。责备他们没有适当的调试消息或检查工具。
  • @Jay-Pi:这与聪明无关。 MATLAB 需要跨实例划分数据数组。检查循环内的代码,它看到两个数组以j 为索引,因此需要将这两个数组分开。但是其中一个不够大,所以会出错。如果它更聪明一点,它会注意到mycase 是恒定的并且永远不会进入开关的一个分支,它会在分割数组之前优化该分支。
  • @CrisLuengo Matlab 不返回有用的消息也无济于事。 documentation 没有描述数组的划分或者我错过了什么?
  • @Jay-Pi:您的文档页面链接到此:mathworks.com/help/parallel-computing/…
  • @CrisLuengo 谢谢。不过,要求不在第一页上,这有点奇怪。

标签: matlab parfor


【解决方案1】:

@David 的回答显示了一个有效的解决方法,但它起作用的原因并不完全是它看起来的那样。

要运行parfor 循环,MATLAB 会分析循环中使用的每个变量和classifies them。在原始代码中,non_crack_bytes 被归类为“切片输入”变量——换句话说,MATLAB 认为循环的每次迭代都需要来自non_crack_bytes 的单个值,对应于循环索引j。该错误发生在工作人员尝试从non_crack_bytes 读取之前很久 - 客户端尝试发送它认为工作人员需要的non_crack_bytes 的元素时发生错误。 (这就是错误提到“parfor supply”的原因,这是一个与发送切片循环输入相关的内部术语)。

@David 的修复在循环内引入了对non_crack_bytes 的额外访问,将其从“切片输入”变量更改为“广播”变量。这意味着客户端将整个non_crack_bytes 发送给每个工作人员。这就是为什么不会发生错误,而不是仔细索引的原因。事实上,你也可以像这样修复循环:

parfor j = 1:imgCount
    size(non_crack_bytes); % access whole of non_crack_bytes
    switch mycase
        case 1
            if non_crack_bytes(j) ~= 0
        ... % etc.

是整个non_crack_bytes 的访问权迫使分析将其视为“广播”变量,从而防止错误发生。

【讨论】:

  • 有趣。这暴露了使用 switch 语句“注释掉代码”的低效率:您正在将未使用的数据发送到工作节点。那么最好使用实际的注释语法。
【解决方案2】:

@Jay-Pi 在他们的评论中指出了这个问题。 Matlab 对parfor 循环很小心,所以在这里你需要更明确地说明不会发生任何不好的事情。

mycase = 2;
non_crack_bytes = 1:6000;
syn_crack_bytes = 1:10000;
imgCount = 10000;
parfor j = 1 : imgCount
    switch mycase
        case 1
            if j<=numel(non_crack_bytes) & ~(non_crack_bytes(j) == 0)
                % Do something
            else
                continue;
            end
        case 2
            if ~(syn_crack_bytes(j) == 0)
                % Do something
            else
                continue;
            end
    end
end

【讨论】:

    猜你喜欢
    • 2022-01-06
    • 1970-01-01
    • 2019-05-06
    • 1970-01-01
    • 2016-12-23
    • 1970-01-01
    • 2018-08-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多