【问题标题】:Matlab: parfor loop and cell arrays not workingMatlab:parfor循环和单元阵列不起作用
【发布时间】:2015-11-06 21:36:29
【问题描述】:

我收到以下错误:“parfor 中的变量 X_bs 不能 分类”尝试运行以下 parfor 循环时:

  y = zeros(1000,1)
        parfor bb = 1:1000
            rng(bb)
            % deleted line: X_bs{8} = [];
            for ii = 1:8
                ind = ceil(N(ii)*rand(N(ii),1));
                X_bs{ii} = X{ii}(ind,:);
            end 

           y(bb) = another_function(X_bs)

        end

X 是一个 1x8 元胞数组,每个元胞包含一个 N(ii)x4 矩阵(N(ii) 变化)。代码重新采样X 的行并创建一个名为X_bs 的元胞数组。我通过一个函数传递X_bs,该函数输出我感兴趣的变量y(bb)

为什么会出现此错误?我该如何解决这个问题?

这是一个例子:

 X{1} = [1 ; 2 ; 3]
 X{2} = [4 ; 5 ; 6; 7]
 N(1) = 3 % size of X{1}
 N(2) = 4 % size of X{2}
    parfor bb=1:10
        rng(bb)
        for ii = 1:2
            X_bs{ii} = zeros(N(ii),1);
            ind = ceil(N(ii)*rand(N(ii),1));
            X_bs{ii} = X{ii}(ind,:);
        end
        % Output is a function of X_bs.  For illustration, say it is the sum
        y(bb) = sum(X_bs{1}) + sum(X_bs{2});
    end

上面的代码得到了与前面相同的错误:“parfor 中的变量 X_bs 无法分类”。这是一个更简单的版本,它可以工作并且不使用单元结构:

X = [1 ; 2 ; 3]
N = 3; %size of X
parfor bb=1:10
    rng(bb)
    X_bs = zeros(N,1);
    ind = ceil(N*rand(N,1));
    X_bs= X(ind,:);
    y(bb) = sum(X_bs) 
end

问题(我认为)在于覆盖单元结构。也许 parfor 将单元结构视为切片变量而不是临时变量。有什么想法吗?

更新:Adriaan 提示随机向量ind 和细胞结构X_bs{ii} 存在问题。这是一个更简单的示例,它不调用随机向量 ind 并且仍然有相同的错误:

X{1} = [1 ; 2 ; 3]
 X{2} = [4 ; 5 ; 6; 7]
 N(1) = 3 % size of X{1}
 N(2) = 4 % size of X{2}
    parfor bb=1:10
        for ii = 1:2
            X_bs{ii} = X{ii};
        end
        % Output is a function of X_bs.  For illustration, say it is the sum
        y(bb) = sum(X_bs{1}) + sum(X_bs{2});
    end

因此,我相当肯定 MatLab 没有将单元结构 X_bs{ii} 视为临时变量。

【问题讨论】:

  • 我编辑了 share_bs 并将其更改为 X_bs 以避免混淆。 X_bs 应该是一个临时变量。删除行 X_bs{8} = []; 后我仍然收到错误

标签: matlab parfor


【解决方案1】:

问题创建就行了:

ind = ceil(N(ii)*rand(N(ii),1));

这里是表面:

X_bs{ii} = X{ii}(ind,:);

在执行parfor 之前,ind 的大小对于 MATLAB 来说是“未知的”,因此无法运行。 parfor 不会以连续的顺序运行,因此事先指定所有必需的大小至关重要。也许您可以在调用y(bb) 之前使用clear X_bs 来规避这个问题,这会将它们从内存中删除,并确保包含的矩阵与您分配的前一次迭代的大小没有不同。

另一方面,如果这不能解决问题,则无法并行化,因为您每次都使用随机大小的矩阵。对此进行扩展:rand(N(ii)) 可以产生相当多的数字。不管那个范围是什么,重要的事实是范围是不确定的,这意味着在执行它之前你无法知道它会是什么。即使这通常没有问题,因为单元格将存储任何旧矩阵大小,parfor 环境要求事先知道所有大小,以便在分配作业之前优化内存和 CPU 使用工人。

如果可能:获取最大值ind 可以达到并将临时变量中所需的矩阵初始化为最大允许大小并仅访问使用的条目。

【讨论】:

  • 阅读了parfor 文档后,这是一个最终的猜测:将everything 放在parfor 的函数中,该函数将bb 作为输入参数。这样parfor 很可能会运行,但我不确定它是否会加快速度。
  • 谢谢。我会看看这是否有效。它可能会因为它是我用来调用 CVX 或 Knitro 的类似技巧 - MatLab 在 parfor 循环中调用 CVX 时遇到问题,但在循环内嵌套一个函数工作得非常好。
【解决方案2】:

解决方案(感谢 Andriaan 的评论)是将生成 X_bs 的 forloop 放入嵌套函数 randomize_X 中。有关工作示例的解决方案,请参见下文:

X{1} = [1 ; 2 ; 3]
X{2} = [4 ; 5 ; 6; 7]
N(1) = 3 % size of X{1}
N(2) = 4 % size of X{2}
parfor bb=1:10
    [X_bs] = randomize_X(X,N)
    % Output is a function of X_bs.  For illustration, say it is the sum
    y(bb) = sum(X_bs{1}) + sum(X_bs{2});
end

在哪里

function [X_bs] = randomize_X(X,N)
  for ii = 1:2
      X_bs{ii} = zeros(N(ii),1);
      ind = ceil(N(ii)*rand(N(ii),1));
      X_bs{ii} = X{ii}(ind,:);
  end
end

我相当确定parfor 循环将单元结构视为切片变量,因此需要预先指定它并且不能在parfor 循环中被覆盖。为了解决这个问题,一个简单的技巧是将单元结构的计算发送到另一个函数。 parfoor 循环与优化工具箱 CVX 有类似的问题。可以使用相同的技巧 - 在 parfor 内的子例程中调用 CVX。

【讨论】:

    猜你喜欢
    • 2013-06-07
    • 1970-01-01
    • 1970-01-01
    • 2020-03-30
    • 1970-01-01
    • 1970-01-01
    • 2018-01-10
    • 2016-02-04
    • 1970-01-01
    相关资源
    最近更新 更多