Matlab:parfor循环和单元格数组不起作用

时间:2015-11-06 21:36:30

标签: matlab parfor

我收到以下错误:“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}视为临时变量。

2 个答案:

答案 0 :(得分:1)

问题是在该行上创建的:

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

和表面在这里:

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

ind的大小是"未知"在执行parfor之前到MATLAB,因此无法运行。 parfor不会以连续的顺序运行,因此最重要的是事先指定所有必需的大小。可能你可以在调用clear X_bs之前使用y(bb)绕过它,这会将它们从内存中删除,并确保包含的矩阵的大小不同于上一次迭代所分配的矩阵。

如果另一方面这不能解决问题,则无法将其与此并行化,因为每次都使用随机大小的矩阵。为了扩展这一点:rand(N(ii))可以生成相当多的数字。无论范围如何,重要的事实是范围 indeterminable ,这意味着在执行它之前你无法知道它是什么。即使这通常没有问题,因为单元格将存储任何旧的矩阵大小,parfor环境需要才能知道所有大小,以便在分配之前优化内存和CPU使用率工作岗位。

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

答案 1 :(得分:0)

解决方案(感谢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。